# Add and verify a domain
Source: https://resend.com/docs/add-a-domain

Get started sending emails by adding a domain to your account.

Resend sends emails using a domain you own. Before you can send or receive emails with Resend, you must have a verified domain associated with your account.

<Info>
  If you don't own a domain, please purchase one from a domain registrar such as
  [Cloudflare](https://www.cloudflare.com/) or
  [Namecheap](https://www.namecheap.com/) before continuing.
</Info>

## Add a domain

You can add and verify a domain you own in four ways:

* in the [**Domains** Dashboard page](/docs/dashboard/domains/introduction)
* using the [Resend API](/docs/api-reference/domains/create-domain)
* with a [Resend CLI command](/docs/cli#domains)
* with the [Resend MCP server](/docs/mcp-server)

To add a new domain from the Resend Dashboard:

<Steps>
  <Step title="In your Resend Dashboard, navigate to the Domains page." />

  <Step title="Click the Add Domain button." />

  <Step title="Enter a domain including a subdomain to use for your Resend emails.">
    We strongly recommend sending emails from a subdomain (e.g., `notifications.example.com`) instead of your root domain (`example.com`) to conform to deliverability best practices.

    Choose a subdomain that reflects the purpose of your emails, such as `customers.example.com` or `updates.example.com`.

    You can have multiple subdomains associated with your root domain. But, each one must be configured and verified individually.

    If you add a domain already used by another team, the dashboard will notify you and you can [claim the domain](/docs/dashboard/domains/claim) to transfer it to your team.
  </Step>

  <Step title="Choose a region from the list provided.">
    Select a region to send your emails from. Choose one that is closest to the majority of your recipients.
  </Step>

  <Step title="(optional) Enter a custom subdomain for the Return-Path address if desired.">
    Return-Path defaults to `send.example.com`, although you can [provide a custom path](/docs/dashboard/domains/custom-return-path).
  </Step>

  <Step title="Update your DNS records with values provided by Resend.">
    View the **Records** tab for your domain to find the records to provide to your DNS host provider. Adding these records will verify that you own the domain and have the correct permissions to send and receive emails.

    Provide the DKIM and SPF configurations (`TXT` and `MX` records) to your DNS provider. These records must match exactly what Resend generated. Copy and paste the records to avoid configuration errors.

    <Tip>
      Consult one of our [DNS provider guides](/docs/knowledge-base/introduction) for specific examples of updating your DNS records with your host.
    </Tip>
  </Step>

  <Step title="Wait for DNS verification to complete">
    When this process is completed correctly, your domain will often verify within 15 minutes of adding the DNS records. However, DNS changes can occasionally take up to 72 hours to propagate globally.

    You can use Resend's [dns.email tool](https://dns.email/) to check that your records are visible publicly. If verification has not completed after 72 hours, use the “Restart verification” button in the Resend dashboard to trigger a fresh verification check.
  </Step>

  <Step title="Add a DMARC record.">
    After your domain is verified, you can then [implement DMARC](/docs/dashboard/domains/dmarc) to build additional trust in your domain and protect against email spoofing.

    This is an email authentication protocol to verify email senders and to allow receivers to reject unauthenticated messages, and is important for email deliverability.
  </Step>

  <Step title="(optional) Update your domain's Resend configuration options.">
    After your domain is verified, you may wish to [enable open and click tracking](/docs/dashboard/domains/tracking) or [enforce Transport Layer Security (TLS)](/docs/dashboard/domains/tls).
  </Step>
</Steps>

## Learn more

<CardGroup>
  <Card title="Manage domains" icon="tools" href="/dashboard/domains/introduction">
    View, create, edit, delete, and manage your domains.
  </Card>

  <Card title="Multi-tenant domain setup" icon="people-group" href="/knowledge-base/setting-up-resend-for-multi-tenants">
    Learn how to configure Resend for SaaS platforms where tenants send emails
    from their own domains.
  </Card>
</CardGroup>

## Next steps

<CardGroup>
  <Card title="Add a DMARC record" icon="globe" href="/dashboard/domains/dmarc">
    Implement DMARC to build trust in your domain and protect against email
    spoofing.
  </Card>

  <Card title="Quickstart tutorials" icon="stopwatch" href="/introduction">
    Send your first transactional email with a quick tutorial for your language
    or framework.
  </Card>
</CardGroup>


# Agent Email Inbox Skill
Source: https://resend.com/docs/agent-email-inbox-skill

Give your AI agent a secure email inbox to receive and act on inbound emails.

The Agent Email Inbox skill enables AI agents to securely receive and respond to emails through Resend's webhook-based architecture. It provides security patterns that prevent untrusted email content from controlling your agent, including sender allowlists, content filtering, and sandboxed processing.

## Why your agent needs a secure inbox

An AI agent's inbox receives **untrusted input**. Without proper security, anyone who knows your agent's email address can send instructions that your agent will execute. The Agent Email Inbox skill solves this with a leveled security approach built in from the start.

Unlike polling-based approaches, Resend uses **webhooks** for inbound email. Your agent is notified instantly when an email arrives. No cron jobs, no wasted API calls checking empty inboxes.

## Installation

This skill is part of the [resend-skills](https://github.com/resend/resend-skills) repository, which also includes the [Resend skill](/docs/resend-skill) for sending emails. When you run the install command, you'll be prompted to choose which skills to install.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
npx skills add resend/resend-skills
```

## Advantages

* **5 security levels**: From strict sender allowlists to human-in-the-loop approval, choose the right level of security for your use case.
* **Real-time webhook architecture**: Event-driven design means your agent reacts to emails in seconds, not minutes.
* **Webhook signature verification**: Built-in patterns for verifying Resend webhook signatures to prevent spoofed events.
* **Multi-language SDK support**: Works with Node.js, Python, Go, Ruby, PHP, Rust, Java, and .NET.
* **Common threat protection**: Built-in guidance for handling prompt injection, sender spoofing, and email flooding.

## Architecture

```
Email → Resend → Webhook → Your Server → Validate
                                             ↓
                                     Process or Reject
```

Your agent only processes emails that pass your chosen security level. Rejected emails are logged and silently acknowledged to prevent retries.

## Security Levels

Choose a security level before setting up your webhook endpoint. Start with **Level 1** and relax only if needed.

| Level | Name                 | Best For                                                  |
| ----- | -------------------- | --------------------------------------------------------- |
| **1** | Strict Allowlist     | Most use cases, only process emails from known senders    |
| **2** | Domain Allowlist     | Organization-wide access from trusted domains             |
| **3** | Content Filtering    | Accept from anyone, but filter unsafe patterns            |
| **4** | Sandboxed Processing | Process all emails with restricted agent capabilities     |
| **5** | Human-in-the-Loop    | Require human approval for actions from untrusted senders |

Each level includes full implementation code in the skill. After installation, your AI agent will have access to the detailed security patterns and can help you implement the right level.

## Example

A minimal webhook handler that verifies the signature, checks the sender against an allowlist, and retrieves the full email content:

```js theme={"theme":{"light":"github-light","dark":"vesper"}}
import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);
const ALLOWED_SENDERS = ['your@email.com'];

async function handler(req) {
  const payload = await req.text();

  const event = resend.webhooks.verify({
    payload,
    headers: {
      id: req.headers.get('svix-id'),
      timestamp: req.headers.get('svix-timestamp'),
      signature: req.headers.get('svix-signature'),
    },
    secret: process.env.RESEND_WEBHOOK_SECRET,
  });

  if (event.type === 'email.received') {
    if (!ALLOWED_SENDERS.includes(event.data.from.toLowerCase())) {
      return new Response('OK', { status: 200 });
    }

    const { data: email } = await resend.emails.receiving.get(
      event.data.email_id,
    );

    await processEmailForAgent(email);
  }

  return new Response('OK', { status: 200 });
}
```

## Learn More

<CardGroup>
  <Card title="OpenClaw Setup Guide" icon="robot" href="/openclaw-guide">
    Step-by-step guide for giving an OpenClaw agent a fully functional email
    inbox.
  </Card>

  <Card title="View on GitHub" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-skills/tree/main/skills/agent-email-inbox">
    See the full source code, security patterns, and documentation.
  </Card>
</CardGroup>


# AI onboarding
Source: https://resend.com/docs/ai-onboarding

Everything you need to onboard your AI agent to Resend.

If you're developing with AI, Resend offers several resources to improve your experience.

* [Resend MCP Server](#resend-mcp-server)
* [Resend CLI](#resend-cli)
* [Resend Docs for Agents](#resend-docs-for-agents)
* [Email Skills for Agents](#email-skills-for-agents)
* [Quick Start Guides](#quick-start-guides)
* [OpenClaw Guide](#openclaw-guide)
* [Chat SDK](#chat-sdk)
* [AI Builder Guides](#ai-builder-guides)
* [AI Integrations](#ai-integrations)

## Prerequisite: Create an API Key

A human must create the Resend account. Once you have an account, you'll need to [create an API key](/docs/create-an-api-key). With an API key, your agent can perform many other tasks.

<Info>
  To send or receive with Resend, you'll need to [verify a domain](https://resend.com/domains). While an agent can [create a domain](/docs/api-reference/domains/create-domain), the API returns DNS records you will need to add in your DNS provider before [verifying your DNS records](/docs/api-reference/domains/verify-domain). You may find it easier to verify your domain in the dashboard.
</Info>

## Resend MCP Server

MCP is an open protocol that standardizes how applications provide context to LLMs. Among other benefits, it provides LLMs tools to act on your behalf. Our [MCP server](https://github.com/resend/resend-mcp) is open-source and covers our full API surface area.

Resend hosts the MCP server, so you can connect any MCP client without installing anything:

```
https://mcp.resend.com/mcp
```

When you connect, your client authenticates with OAuth by opening a browser to log in to Resend. Clients that can't complete a browser login can pass an API key as a Bearer token instead. You can also run the server locally with `npx` using the `resend-mcp` package on NPM.

Claude and Codex also offer one-click installs that bundle the MCP server and every Resend skill:

* [Resend connector for Claude](https://claude.ai/directory/connectors/resend)
* [Resend plugin for Codex](https://chatgpt.com/plugins/plugin_asdk_app_6a3c407853888191beddc2151c2b6f8b?open_in_codex)

<Card title="MCP Server" icon="microchip-ai" href="/mcp-server">
  View setup instructions for Claude, Cursor, Codex, Copilot, Windsurf,
  Antigravity, and more.
</Card>

## Resend CLI

The Resend CLI lets you send emails, manage your account, and develop locally, all from the terminal. It's built for humans, AI agents, and CI/CD pipelines.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
# Authenticate
resend login

# Send an email
resend emails send \
  --from "you@example.com" \
  --to hello@example.com \
  --subject "Hello" \
  --text "Sent from my terminal."
```

The CLI also includes a full local webhook setup for developing with inbound email events without deploying anything.

<Card title="Resend CLI" icon="terminal" href="/cli">
  Install the CLI and set up a local webhook development environment.
</Card>

## Resend Docs for Agents

You can give your agent current docs in a context-aware way in three ways:

1. **Markdown docs**

   Every doc includes a markdown version (append `md` to any page)

   ```
   Docs for this page: https://resend.com/docs/ai-onboarding.md
   ```

2. **Full llms.txt**

   Give your agent all our docs in a single file.

   ```
   Here are the Resend docs: https://resend.com/docs/llms-full.txt
   ```

3. **MCP Docs server**

   For a more structured approach using MCP tools, you can install our MCP docs server in any MCP client, like Cursor, Codex, or Claude Code.

   ```
   npx add-mcp https://resend.com/docs/mcp
   ```

## Email Skills for Agents

Skills give AI agents specialized knowledge for specific tasks.

Install skills with a single command:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
npx skills add resend/resend-skills
```

Or install individually:

| Skill                                               | Install                                      | What it does                                                                                                       |
| --------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| [Resend](/docs/resend-skill)                             | `npx skills add resend/resend-skills`        | Send and receive emails, handle errors, and prevent duplicate sends. Get code examples from various SDKs.          |
| [React Email](/docs/react-email-skill)                   | `npx skills add resend/react-email`          | Build emails in React, Tailwind, and TypeScript. Audit existing React emails for style and cross-client rendering. |
| [Email Best Practices](/docs/email-best-practices-skill) | `npx skills add resend/email-best-practices` | Audit SPF/DKIM/DMARC setup, compliance (CAN-SPAM, GDPR), webhook handling                                          |

## Quick Start Guides

The documentation includes quick start guides for common tasks with Resend. They contain step-by-step instructions for sending emails, creating templates, and more. Copy the prompt for your agent or click to open in Cursor.

<Prompt description="Example agent quick start guide for sending emails." icon="envelope">
  Resend provides two endpoints for sending emails:

  | Approach   | Endpoint             | Use Case                                                                  |
  | ---------- | -------------------- | ------------------------------------------------------------------------- |
  | **Single** | `POST /emails`       | Individual transactional emails, emails with attachments, scheduled sends |
  | **Batch**  | `POST /emails/batch` | Multiple distinct emails in one request (max 100), bulk notifications     |

  **Choose batch when:**

  * Sending 2+ distinct emails at once
  * Reducing API calls is important (by default, rate limit is 10 requests per second)
  * No attachments or scheduling needed

  **Choose single when:**

  * Sending one email
  * Email needs attachments
  * Email needs to be scheduled
  * Different recipients need different timing

  ## Quick Start

  1. **Detect project language** from config files (package.json, requirements.txt, go.mod, etc.)
  2. **Install SDK** (preferred) or use cURL
  3. **Choose single or batch** based on the decision matrix above
  4. **Implement best practices** - Idempotency keys, error handling, retries

  ## Best Practices (Critical for Production)

  Always implement these for production email sending.

  ### Idempotency Keys

  Prevent duplicate emails when retrying failed requests.

  | Key Facts             |                                                                  |
  | --------------------- | ---------------------------------------------------------------- |
  | **Format (single)**   | `<event-type>/<entity-id>` (e.g., `welcome-email/user-123`)      |
  | **Format (batch)**    | `batch-<event-type>/<batch-id>` (e.g., `batch-orders/batch-456`) |
  | **Expiration**        | 24 hours                                                         |
  | **Max length**        | 256 characters                                                   |
  | **Duplicate payload** | Returns original response without resending                      |
  | **Different payload** | Returns 409 error                                                |

  ### Error Handling

  | Code     | Action                                                                                       |
  | -------- | -------------------------------------------------------------------------------------------- |
  | 400, 422 | Fix request parameters, don't retry                                                          |
  | 401, 403 | Check API key / verify domain, don't retry                                                   |
  | 409      | Idempotency conflict - use new key or fix payload                                            |
  | 429      | Rate limited - retry with exponential backoff (by default, rate limit is 10 requests/second) |
  | 500      | Server error - retry with exponential backoff                                                |

  ### Retry Strategy

  * **Backoff:** Exponential (1s, 2s, 4s...)
  * **Max retries:** 3-5 for most use cases
  * **Only retry:** 429 (rate limit) and 500 (server error)
  * **Always use:** Idempotency keys when retrying

  ## Single Email

  **Endpoint:** `POST /emails` (prefer SDK over cURL)

  ### Required Parameters

  | Parameter        | Type      | Description                                         |
  | ---------------- | --------- | --------------------------------------------------- |
  | `from`           | string    | Sender address. Format: `"Name <email@domain.com>"` |
  | `to`             | string\[] | Recipient addresses (max 50)                        |
  | `subject`        | string    | Email subject line                                  |
  | `html` or `text` | string    | Email body content                                  |

  ### Optional Parameters

  | Parameter        | Type      | Description                       |
  | ---------------- | --------- | --------------------------------- |
  | `cc`             | string\[] | CC recipients                     |
  | `bcc`            | string\[] | BCC recipients                    |
  | `reply_to`\*     | string\[] | Reply-to addresses                |
  | `scheduled_at`\* | string    | Schedule send time (ISO 8601)     |
  | `attachments`    | array     | File attachments (max 40MB total) |
  | `tags`           | array     | Key/value pairs for tracking      |
  | `headers`        | object    | Custom headers                    |

  \*Parameter naming varies by SDK (e.g., `replyTo` in Node.js, `reply_to` in Python).

  ### Minimal Example (Node.js)

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.emails.send(
    {
      from: 'Acme <onboarding@resend.dev>',
      to: ['delivered@resend.dev'],
      subject: 'Hello World',
      html: '<p>Email body here</p>',
    },
    { idempotencyKey: `welcome-email/${userId}` },
  );

  if (error) {
    console.error('Failed:', error.message);
    return;
  }
  console.log('Sent:', data.id);
  ```

  ## Batch Email

  **Endpoint:** `POST /emails/batch` (but prefer SDK over cURL)

  ### Limitations

  * **No attachments** - Use single sends for emails with attachments
  * **No scheduling** - Use single sends for scheduled emails
  * **Atomic** - If one email fails validation, the entire batch fails
  * **Max 100 emails** per request
  * **Max 50 recipients** per individual email in the batch

  ### Pre-validation

  Since the entire batch fails on any validation error, validate all emails before sending:

  * Check required fields (from, to, subject, html/text)
  * Validate email formats
  * Ensure batch size is less than or equal to 100

  ### Minimal Example (Node.js)

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.batch.send(
    [
      {
        from: 'Acme <hello@example.com>',
        to: ['delivered@resend.dev'],
        subject: 'Order Shipped',
        html: '<p>Your order has shipped!</p>',
      },
      {
        from: 'Acme <hello@example.com>',
        to: ['delivered@resend.dev'],
        subject: 'Order Confirmed',
        html: '<p>Your order is confirmed!</p>',
      },
    ],
    { idempotencyKey: `batch-orders/${batchId}` },
  );

  if (error) {
    console.error('Batch failed:', error.message);
    return;
  }
  console.log(
    'Sent:',
    data.map((e) => e.id),
  );
  ```
</Prompt>

## OpenClaw Guide

Equipping your agent with its own email inbox can be a powerful tool to unlock new workflows. Alternatively, give it access to your Resend account to support agentic flows for sending and receiving emails.

<Card title="Email Automation for OpenClaw using Resend" icon="lobster" href="/openclaw-guide">
  View the OpenClaw guide.
</Card>

## Chat SDK

The `@resend/chat-sdk-adapter` package is a Vercel Chat SDK adapter that turns email into a two-way communication channel. Receive inbound emails through webhooks, reply through the Resend API, and let the adapter handle threading automatically. It also supports card emails, attachments, and proactive outreach.

<Card title="Chat SDK" icon="comments" href="/chat-sdk">
  Build conversational email experiences with the Chat SDK adapter.
</Card>

## AI Builder Guides

Get started using Resend with popular AI builders:

* [Anything Integration](/docs/anything-integration)
* [Lovable Integration](/docs/lovable-integration)
* [v0 Integration](/docs/v0-integration)
* [Bolt.new Integration](/docs/bolt-new-integration)
* [Replit Integration](/docs/replit-integration)
* [Base44 Integration](/docs/base44-integration)
* [Leap.new Integration](/docs/leap-new-integration)

## AI Integrations

Several AI tools have created integrations for working with Resend. Visit their documentation for information on integrating Resend with their tools.

<CardGroup>
  <Card title="Lovable" href="https://docs.lovable.dev/integrations/resend" icon={<LovableIcon />}>
    Tell the Lovable AI to send emails
  </Card>

  <Card title="Anything" href="https://www.createanything.com/docs/integrations/resend" icon={<AnythingIcon />}>
    Add email to your Anything projects
  </Card>

  <Card title="Wildcard" href="https://github.com/wild-card-ai/agents-json/blob/master/examples/resend.ipynb" icon={<WildcardIcon />}>
    Send natural language emails using Wildcard
  </Card>

  <Card title="mcp.run" href="https://www.mcp.run/nilslice/resend" icon={<McpRunIcon />}>
    Build email AI agents using mcp.run
  </Card>

  <Card title="Rocket" href="https://docs.rocket.new/integrations/resend" icon={<RocketIcon />}>
    Send emails from apps built with Rocket
  </Card>

  <Card title="Base44" href="https://docs.base44.com/Integrations/Resend-integration" icon={<Base44Icon />}>
    Add email to your Base44 apps
  </Card>

  <Card title="Leap.new" href="https://docs.leap.new/integrations/resend" icon={<LeapNewIcon />}>
    Add email to your Leap apps
  </Card>

  <Card title="Parsley" href="https://www.parsley.id/integrations/resend" icon={<ParsleyIcon />}>
    Send alerts and follow-ups with Parsley
  </Card>

  <Card title="Pica" href="https://www.picaos.com/integrations/resend" icon={<PicaIcon />}>
    Integrate Pica with Resend
  </Card>
</CardGroup>


# How to add the Resend integration to your Anything project
Source: https://resend.com/docs/anything-integration

Learn how to add the Resend integration to your Anything project.

[Anything](https://createanything.com) is a platform for building web sites, tools, apps, and projects via chat. With their [Resend integration](https://www.createanything.com/docs/integrations/resend), you can send emails from your Anything project.

If you prefer to watch a video, check out our video walkthrough below.

<YouTube />

## Guide

<Steps>
  <Step title="Call the Resend integration in Anything">
    Type `/Resend` in the chat and select the integration, and ask Anything to add email functionality to your project.

    <img alt="adding the Resend integration to a Anything chat" />
  </Step>

  <Step title="Add your Resend API key">
    Anything usually prompts you for a Resend API key, which you can add in the [Resend Dashboard](https://resend.com/api-keys). If Anything doesn't prompt you for a Resend API key, click the **More options** <Icon icon="ellipsis-vertical" /> button and select **Secrets**.

    Click the <Icon icon="plus" /> **Add new secret** button.

    * **Name:** `RESEND_API_KEY`
    * **Value:** Your Resend API key (e.g., `re_xxxxxxxxx0`)

    Learn more about [Secrets in Create](https://www.createanything.com/docs/essentials#project-settings).
  </Step>

  <Step title="Add a custom domain to your Resend account">
    By default, you can only send emails to your own email address.

    To send emails to other email addresses:

    1. Add a [custom domain to your Resend account](https://resend.com/domains).
    2. Add the custom domain to the `from` field in the `resend` function in Create.

    Learn more about [Functions in Create](https://www.createanything.com/docs/builder/functions).
  </Step>
</Steps>


# Create API key
Source: https://resend.com/docs/api-reference/api-keys/create-api-key

POST /api-keys
Add a new API key to authenticate communications with Resend.

## Body Parameters

<ParamField type="string">
  The API key name. Maximum 50 characters.
</ParamField>

<ParamField type="full_access | sending_access">
  The API key can have full access to Resend's API or be only restricted to send emails.

  * `full_access`: Can create, delete, get, and update any resource.
  * `sending_access`: Can only send emails.
</ParamField>

<ResendParamField type="string">
  Restrict an API key to send emails only from a specific domain. This is only
  used when the `permission` is set to `sending_access`.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.apiKeys.create({ name: 'Production' });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->apiKeys->create([
    'name' => 'Production'
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.ApiKeys.CreateParams = {
    "name": "Production",
  }

  resend.ApiKeys.create(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    name: "Production"
  }
  Resend::ApiKeys.create(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")
  	params := &resend.CreateApiKeyRequest{
  		Name: "Production",
  	}
  	client.ApiKeys.Create(params)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::CreateApiKeyOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _api_key = resend
      .api_keys
      .create(CreateApiKeyOptions::new("Production"))
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateApiKeyOptions params = CreateApiKeyOptions
                  .builder()
                  .name("Production").build();

          CreateApiKeyResponse apiKey = resend.apiKeys().create(params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ApiKeyCreateAsync( "Production" );
  Console.WriteLine( "Token={0}", resp.Content.Token );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/api-keys' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "name": "Production"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend api-keys create --name Production
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "id": "dacf4072-4119-4d88-932f-6202748ac7c8",
    "object": "api_key",
    "token": "re_c1tpEyD8_NKFusih9vKVQknRAQfmFcWCv"
  }
  ```
</ResponseExample>


# Delete API key
Source: https://resend.com/docs/api-reference/api-keys/delete-api-key

DELETE /api-keys/:api_key_id
Remove an existing API key.

## Path Parameters

<ResendParamField type="string">
  The API key ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.apiKeys.remove(
    'b6d24b8e-af0b-4c3c-be0c-359bbd97381e',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->apiKeys->remove('b6d24b8e-af0b-4c3c-be0c-359bbd97381e');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"
  resend.ApiKeys.remove(api_key_id="b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::ApiKeys.remove "b6d24b8e-af0b-4c3c-be0c-359bbd97381e"
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")
  	client.ApiKeys.Remove("b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    resend
      .api_keys
      .delete("b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          resend.apiKeys().remove("b6d24b8e-af0b-4c3c-be0c-359bbd97381e");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.ApiKeyDeleteAsync( new Guid( "b6d24b8e-af0b-4c3c-be0c-359bbd97381e" ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X DELETE 'https://api.resend.com/api-keys/b6d24b8e-af0b-4c3c-be0c-359bbd97381e' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend api-keys delete b6d24b8e-af0b-4c3c-be0c-359bbd97381e
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "api_key",
    "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
    "deleted": true
  }
  ```
</ResponseExample>


# List API keys
Source: https://resend.com/docs/api-reference/api-keys/list-api-keys

GET /api-keys
Retrieve a list of API keys for the authenticated user.

<QueryParams type="API keys" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.apiKeys.list();
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->apiKeys->list();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"
  resend.ApiKeys.list()
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::ApiKeys.list
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")
  	client.ApiKeys.List()
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result, list_opts::ListOptions};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _api_keys = resend.api_keys.list(ListOptions::default()).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          resend.apiKeys().list();
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ApiKeyListAsync();
  Console.WriteLine( "Nr keys={0}", resp.Content.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/api-keys' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend api-keys list
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "91f3200a-df72-4654-b0cd-f202395f5354",
        "name": "Production",
        "created_at": "2026-04-08 00:11:13.110779+00",
        "last_used_at": "2026-11-01 17:09:51.813959+00"
      }
    ]
  }
  ```
</ResponseExample>


# Cancel Broadcast
Source: https://resend.com/docs/api-reference/broadcasts/cancel-broadcast

POST /broadcasts/:broadcast_id/cancel
Cancel a queued or scheduled broadcast.

You can only cancel Broadcasts that are `queued` or `scheduled`. Canceling a `queued` Broadcast stops it mid-send. Any emails already sent are not affected, but no further emails will go out.

## Path Parameters

<ResendParamField type="string">
  The broadcast ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.broadcasts.cancel(
    '559ac32e-9ef5-46fb-82a1-b76b840c0f7b',
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/broadcasts/559ac32e-9ef5-46fb-82a1-b76b840c0f7b/cancel' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "broadcast",
    "id": "559ac32e-9ef5-46fb-82a1-b76b840c0f7b"
  }
  ```
</ResponseExample>


# Create Broadcast
Source: https://resend.com/docs/api-reference/broadcasts/create-broadcast

POST /broadcasts
Create a new broadcast to send to your contacts.

## Body Parameters

<ResendParamField type="string">
  The ID of the segment you want to send to.

  <Info>
    Audiences are now called Segments. Follow the [Migration
    Guide](/docs/dashboard/segments/migrating-from-audiences-to-segments).
  </Info>
</ResendParamField>

<ParamField type="string">
  Sender email address.

  To include a friendly name, pass the sender as `Name <email@example.com>`, for example `Acme <onboarding@example.dev>`.
</ParamField>

<ParamField type="string">
  Email subject.
</ParamField>

<ResendParamField type="string | string[]">
  Reply-to email address. For multiple addresses, send as an array of strings.
</ResendParamField>

<ParamField type="string">
  The HTML version of the message. You can include Contact Properties in the
  body of the Broadcast. Learn more about [Contact
  Properties](/docs/dashboard/audiences/contacts).
</ParamField>

<ParamField type="string">
  The plain text version of the message. You can include Contact Properties in the body of the Broadcast. Learn more about [Contact Properties](/docs/dashboard/audiences/contacts).

  <Info>
    If not provided, the HTML will be used to generate a plain text version. You
    can opt out of this behavior by setting value to an empty string.
  </Info>
</ParamField>

<ParamField type="React.ReactNode">
  The React component used to write the message. *Only available in the Node.js
  SDK.*
</ParamField>

<ParamField type="string">
  The friendly name of the broadcast. Only used for internal reference.
</ParamField>

<ResendParamField type="string">
  The topic ID that the broadcast will be scoped to.
</ResendParamField>

<ParamField type="boolean">
  Send the broadcast immediately after creation. Defaults to `false`.

  <Info>
    When set to `true`, the broadcast will be sent or scheduled (if `scheduled_at` is provided) without requiring a separate call to the [Send Broadcast](/docs/api-reference/broadcasts/send-broadcast) endpoint.
  </Info>
</ParamField>

<ResendParamField type="string">
  Schedule the broadcast to be sent later. The date should be in natural language (e.g.: `in 1 min`) or ISO 8601 format (e.g: `2026-08-05T11:52:01.858Z`).

  <Warning>
    This parameter requires `send` to be set to `true`.
  </Warning>
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Create a draft broadcast
  const { data, error } = await resend.broadcasts.create({
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf',
    from: 'Acme <onboarding@resend.dev>',
    subject: 'hello world',
    html: 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
  });

  // Create and send immediately
  const { data, error } = await resend.broadcasts.create({
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf',
    from: 'Acme <onboarding@resend.dev>',
    subject: 'hello world',
    html: 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
    send: true,
  });

  // Create and schedule
  const { data, error } = await resend.broadcasts.create({
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf',
    from: 'Acme <onboarding@resend.dev>',
    subject: 'hello world',
    html: 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
    send: true,
    scheduledAt: 'in 1 hour',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Create a draft broadcast
  $resend->broadcasts->create([
    'segment_id' => '78261eea-8f8b-4381-83c6-79fa7120f1cf',
    'from' => 'Acme <onboarding@resend.dev>',
    'subject' => 'hello world',
    'html' => 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
  ]);

  // Create and send immediately
  $resend->broadcasts->create([
    'segment_id' => '78261eea-8f8b-4381-83c6-79fa7120f1cf',
    'from' => 'Acme <onboarding@resend.dev>',
    'subject' => 'hello world',
    'html' => 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
    'send' => true,
  ]);

  // Create and schedule
  $resend->broadcasts->create([
    'segment_id' => '78261eea-8f8b-4381-83c6-79fa7120f1cf',
    'from' => 'Acme <onboarding@resend.dev>',
    'subject' => 'hello world',
    'html' => 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
    'send' => true,
    'scheduled_at' => 'in 1 hour',
  ]);
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  // Create a draft broadcast
  params: resend.Broadcasts.CreateParams = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
  }
  resend.Broadcasts.create(params)

  // Create and send immediately
  params: resend.Broadcasts.CreateParams = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true,
  }
  resend.Broadcasts.create(params)

  // Create and schedule
  params: resend.Broadcasts.CreateParams = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true,
    "scheduled_at": "in 1 hour",
  }
  resend.Broadcasts.create(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  // Create a draft broadcast
  params = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "hello world",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
  }
  Resend::Broadcasts.create(params)

  // Create and send immediately
  params = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true,
  }
  Resend::Broadcasts.create(params)

  // Create and schedule
  params = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true,
    "scheduled_at": "in 1 hour",
  }
  Resend::Broadcasts.create(params)

  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  // Create a draft broadcast
  params := &resend.CreateBroadcastRequest{
    SegmentId: "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    From:       "Acme <onboarding@resend.dev>",
    Html:       "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    Subject:    "Hello, world!",
  }
  broadcast, _ := client.Broadcasts.Create(params)

  // Create and send immediately
  params = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true,
  }
  broadcast, _ := client.Broadcasts.Create(params)

  // Create and schedule
  params = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true,
    "scheduled_at": "in 1 hour",
  }
  broadcast, _ := client.Broadcasts.Create(params)
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::CreateBroadcastOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let segment_id = "78261eea-8f8b-4381-83c6-79fa7120f1cf";
    let from = "Acme <onboarding@resend.dev>";
    let subject = "hello world";
    let html = "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}";

    let opts = CreateBroadcastOptions::new(segment_id, from, subject).with_html(html);

    // Create a draft broadcast
    let _broadcast = resend.broadcasts.create(opts.clone()).await?;

    // Create and send immediately
    let _broadcast = resend
      .broadcasts
      .create(opts.clone().with_send(true))
      .await?;

    // Create and schedule
    let _broadcast = resend
      .broadcasts
      .create(opts.with_send(true).with_scheduled_at("in 1 hour"))
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend resend = new Resend("re_xxxxxxxxx");

  // Create a draft broadcast
  CreateBroadcastOptions params = CreateBroadcastOptions.builder()
      .segmentId("78261eea-8f8b-4381-83c6-79fa7120f1cf")
      .from("Acme <onboarding@resend.dev>")
      .subject("hello world")
      .html("Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}")
      .build();
  CreateBroadcastResponseSuccess data = resend.broadcasts().create(params);

  // Create and send immediately
  CreateBroadcastOptions params = CreateBroadcastOptions.builder()
      .segmentId("78261eea-8f8b-4381-83c6-79fa7120f1cf")
      .from("Acme <onboarding@resend.dev>")
      .subject("hello world")
      .html("Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}")
      .send(true)
      .build();
  CreateBroadcastResponseSuccess data = resend.broadcasts().create(params);

  // Create and schedule
  CreateBroadcastOptions params = CreateBroadcastOptions.builder()
      .segmentId("78261eea-8f8b-4381-83c6-79fa7120f1cf")
      .from("Acme <onboarding@resend.dev>")
      .subject("hello world")
      .html("Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}")
      .send(true)
      .scheduledAt("in 1 hour")
      .build();
  CreateBroadcastResponseSuccess data = resend.broadcasts().create(params);
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  // Create a draft broadcast
  var resp = await resend.BroadcastAddAsync(
      new BroadcastData()
      {
          DisplayName = "Example Broadcast",
          SegmentId = new Guid( "78261eea-8f8b-4381-83c6-79fa7120f1cf" ),
          From = "Acme <onboarding@resend.dev>",
          Subject = "Hello, world!",
          HtmlBody = "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
      }
  );

  Console.WriteLine( "Broadcast Id={0}", resp.Content );

  // Create and send immediately
  var resp = await resend.BroadcastAddAsync(
      new BroadcastData()
      {
          DisplayName = "Example Broadcast",
          SegmentId = new Guid( "78261eea-8f8b-4381-83c6-79fa7120f1cf" ),
          From = "Acme <onboarding@resend.dev>",
          Subject = "Hello, world!",
          HtmlBody = "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
          Send = true,
      }
  );

  Console.WriteLine( "Broadcast Id={0}", resp.Content );

  // Create and schedule
  var resp = await resend.BroadcastAddAsync(
      new BroadcastData()
      {
          DisplayName = "Example Broadcast",
          SegmentId = new Guid( "78261eea-8f8b-4381-83c6-79fa7120f1cf" ),
          From = "Acme <onboarding@resend.dev>",
          Subject = "Hello, world!",
          HtmlBody = "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
          Send = true,
          ScheduledAt = DateTime.UtcNow.AddHours( 1 ),
      }
  );

  Console.WriteLine( "Broadcast Id={0}", resp.Content );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Create a draft broadcast
  curl -X POST 'https://api.resend.com/broadcasts' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'
  {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "hello world",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}"
  }'

  # Create and send immediately
  curl -X POST 'https://api.resend.com/broadcasts' \
   -H 'Authorization: Bearer re_xxxxxxxxx' \
   -H 'Content-Type: application/json' \
   -d $'
  {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "hello world",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true
  }'

  # Create and schedule
  curl -X POST 'https://api.resend.com/broadcasts' \
   -H 'Authorization: Bearer re_xxxxxxxxx' \
   -H 'Content-Type: application/json' \
   -d $'
  {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "hello world",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true,
    "scheduled_at": "in 1 hour"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Create a draft broadcast
  resend broadcasts create \
    --from "Acme <onboarding@resend.dev>" \
    --subject "hello world" \
    --segment-id 78261eea-8f8b-4381-83c6-79fa7120f1cf \
    --html "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}"

  # Create and send immediately
  resend broadcasts create \
    --from "Acme <onboarding@resend.dev>" \
    --subject "hello world" \
    --segment-id 78261eea-8f8b-4381-83c6-79fa7120f1cf \
    --html "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}" \
    --send

  # Create and schedule
  resend broadcasts create \
    --from "Acme <onboarding@resend.dev>" \
    --subject "hello world" \
    --segment-id 78261eea-8f8b-4381-83c6-79fa7120f1cf \
    --html "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}" \
    --send \
    --scheduled-at "in 1 hour"
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "broadcast",
    "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794"
  }
  ```
</ResponseExample>


# Delete Broadcast
Source: https://resend.com/docs/api-reference/broadcasts/delete-broadcast

DELETE /broadcasts/:broadcast_id
Remove an existing broadcast.

You can only delete Broadcasts that have not yet been sent (i.e., `draft` or `scheduled`). Deleting a `scheduled` Broadcast also cancels the scheduled delivery and the email will not be sent.

## Path Parameters

<ResendParamField type="string">
  The broadcast ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.broadcasts.remove(
    '559ac32e-9ef5-46fb-82a1-b76b840c0f7b',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->broadcasts->remove('559ac32e-9ef5-46fb-82a1-b76b840c0f7b');
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Broadcasts.remove(id="559ac32e-9ef5-46fb-82a1-b76b840c0f7b")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Broadcasts.remove("559ac32e-9ef5-46fb-82a1-b76b840c0f7b")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Broadcasts.Remove("559ac32e-9ef5-46fb-82a1-b76b840c0f7b")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _deleted = resend
      .broadcasts
      .delete("559ac32e-9ef5-46fb-82a1-b76b840c0f7b")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend resend = new Resend("re_xxxxxxxxx");

  RemoveBroadcastResponseSuccess data = resend.broadcasts().remove("559ac32e-9ef5-46fb-82a1-b76b840c0f7b");
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.BroadcastDeleteAsync( new Guid( "559ac32e-9ef5-46fb-82a1-b76b840c0f7b" ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X DELETE 'https://api.resend.com/broadcasts/559ac32e-9ef5-46fb-82a1-b76b840c0f7b' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend broadcasts delete 559ac32e-9ef5-46fb-82a1-b76b840c0f7b
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "broadcast",
    "id": "559ac32e-9ef5-46fb-82a1-b76b840c0f7b",
    "deleted": true
  }
  ```
</ResponseExample>


# Retrieve Broadcast
Source: https://resend.com/docs/api-reference/broadcasts/get-broadcast

GET /broadcasts/:broadcast_id
Retrieve a single broadcast.

You can retrieve broadcasts created via both this API and the Resend dashboard.

## Path Parameters

<ResendParamField type="string">
  The broadcast ID.
</ResendParamField>

<Info>
  See all available `status` types in [the Broadcasts
  overview](/docs/dashboard/broadcasts/manage-broadcasts#understand-broadcast-statuses).
</Info>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.broadcasts.get(
    '559ac32e-9ef5-46fb-82a1-b76b840c0f7b',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->broadcasts->get('559ac32e-9ef5-46fb-82a1-b76b840c0f7b');
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Broadcasts.get(id="559ac32e-9ef5-46fb-82a1-b76b840c0f7b")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Broadcasts.get("559ac32e-9ef5-46fb-82a1-b76b840c0f7b")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Broadcasts.Get("559ac32e-9ef5-46fb-82a1-b76b840c0f7b")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _broadcast = resend
      .broadcasts
      .get("559ac32e-9ef5-46fb-82a1-b76b840c0f7b")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend resend = new Resend("re_xxxxxxxxx");

  GetBroadcastResponseSuccess data = resend.broadcasts().get("559ac32e-9ef5-46fb-82a1-b76b840c0f7b");
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.BroadcastRetrieveAsync( new Guid( "559ac32e-9ef5-46fb-82a1-b76b840c0f7b" ) );
  Console.WriteLine( "Broadcast name={0}", resp.Content.DisplayName );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/broadcasts/559ac32e-9ef5-46fb-82a1-b76b840c0f7b' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend broadcasts get 559ac32e-9ef5-46fb-82a1-b76b840c0f7b
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "broadcast",
    "id": "559ac32e-9ef5-46fb-82a1-b76b840c0f7b",
    "name": "Announcements",
    "audience_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf", // now called segment_id
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "hello world",
    "reply_to": null,
    "preview_text": "Check out our latest announcements",
    "html": "<p>Hello {{{contact.first_name|there}}}!</p>",
    "text": "Hello {{{contact.first_name|there}}}!",
    "status": "draft",
    "created_at": "2026-12-01 19:32:22.980+00",
    "scheduled_at": null,
    "sent_at": null,
    "topic_id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e"
  }
  ```
</ResponseExample>


# Retrieve Metrics
Source: https://resend.com/docs/api-reference/broadcasts/get-broadcasts-metrics

GET /broadcasts/metrics
Retrieve account-wide broadcast metrics, aggregated across all broadcasts.

<Warning>
  Broadcast metrics and recipients are currently in private beta and only
  available to a limited number of users. APIs might change before it is generally available.
  [Get in touch](https://resend.com/contact) if you're interested in testing
  this feature.

  <span />

  Once you have access, upgrade your Resend SDK to use the methods on this
  page:

  <CodeGroup>
    ```bash Node.js theme={"theme":{"light":"github-light","dark":"vesper"}} theme={"theme":{"light":"github-light","dark":"vesper"}}
    npm install resend@6.19.0-preview-headless-dashboard.7
    ```
  </CodeGroup>
</Warning>

<Note>
  Metrics are retained according to your plan's data retention window.
  Requesting a `start_date` older than your retention window returns data
  clamped to the oldest date your plan retains. This doesn't apply when
  `broadcast_id` is set.
</Note>

<Note>
  Responses are cached for up to 15 minutes, so a request for the same range may
  return slightly stale data within that window.
</Note>

## Query Parameters

<ParamField type="string">
  The start of the date range, as an ISO 8601 date (`2026-07-01`) or datetime
  (`2026-07-01T00:00:00Z`). Must be on or before `end_date`. Defaults to 6 days
  before `end_date`, unless `broadcast_id` is set, in which case it defaults to
  `2023-01-01` instead, since no broadcast could exist before Resend launched.
</ParamField>

<ParamField type="string">
  The end of the date range, as an ISO 8601 date or datetime. Values in the
  future are clamped to the current time. Defaults to now.
</ParamField>

<ParamField type="string">
  The IANA timezone (e.g. `America/New_York`) used to bucket periods when
  `period` is in `dimensions`.
</ParamField>

<ParamField type="hourly | daily | weekly | monthly">
  The bucket size used when `period` is in `dimensions`. Accepted but has no
  effect otherwise.
</ParamField>

<ParamField type="string[]">
  Comma-separated list of metrics to include in the response. Defaults to all
  of the following:

  `delivered`, `complained`, `suppressed`, `bounced`, `bounced_transient`,
  `bounced_permanent`, `bounced_undetermined`, `opened`, `clicked`,
  `unsubscribed`, `delivery_delayed`, `failed`, `sent`, `unique_opened`,
  `unique_clicked`, `delivery_rate`, `open_rate`, `click_rate`, `bounce_rate`,
  `complaint_rate`, `unsubscribe_rate`
</ParamField>

<ParamField type="string[]">
  Comma-separated list of dimensions to break the response down by. Combine
  `period` with `broadcast` for a joint breakdown (one row per unique `period`

  * `broadcast` pair). Defaults to `[]`, returning a single `totals` row for
    the whole range, with no `data`.

  Possible values:

  * `period`: one row per `granularity` period, in chronological order.
  * `broadcast`: one row per broadcast, including its `name` resolved from your
    account.
</ParamField>

<ParamField type="string[]">
  Comma-separated list of broadcast IDs to restrict the response to, up to 100.
</ParamField>

<RequestExample>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/broadcasts/metrics?start_date=2026-07-01&end_date=2026-07-08&metrics=sent,delivered,open_rate&dimensions=period,broadcast' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "metrics",
    "start_date": "2026-07-01T00:00:00.000Z",
    "end_date": "2026-07-08T00:00:00.000Z",
    "metrics": ["sent", "delivered", "open_rate"],
    "dimensions": ["period", "broadcast"],
    "granularity": "daily",
    "totals": {
      "sent": 1204,
      "delivered": 1180,
      "open_rate": 50.0
    },
    "data": [
      {
        "period": "2026-07-01",
        "id": "d91cd9bd-1176-4f47-2a4b-fce2d5399cbf",
        "name": "July Newsletter",
        "sent": 172,
        "delivered": 169,
        "open_rate": 49.7
      }
    ]
  }
  ```
</ResponseExample>


# List Clicked Links
Source: https://resend.com/docs/api-reference/broadcasts/list-broadcast-clicked-links

GET /broadcasts/:broadcast_id/clicked-links
Retrieve the links clicked in a broadcast.

<Warning>
  Broadcast metrics and recipients are currently in private beta and only
  available to a limited number of users. APIs might change before it is generally available.
  [Get in touch](https://resend.com/contact) if you're interested in testing
  this feature.

  <span />

  Once you have access, upgrade your Resend SDK to use the methods on this
  page:

  <CodeGroup>
    ```bash Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
    npm install resend@6.19.0-preview-headless-dashboard.7
    ```
  </CodeGroup>
</Warning>

Retrieve every link clicked in a broadcast, ranked by total clicks. Results are
paginated with cursors. See [Pagination](/docs/api-reference/pagination) for how
`after` and `before` work.

<Info>
  Responses are cached for up to 15 minutes, so requesting the same page again
  may return slightly stale data within that window.
</Info>

## Path Parameters

<ResendParamField type="string">
  The broadcast ID.
</ResendParamField>

## Query Parameters

<ResendParamField type="number">
  Number of links to return. Between `1` and `100`. Defaults to `20`.
</ResendParamField>

<ResendParamField type="string">
  Cursor to fetch the page after this link. Cannot be used with `before`.
</ResendParamField>

<ResendParamField type="string">
  Cursor to fetch the page before this link. Cannot be used with `after`.
</ResendParamField>

## Response Fields

<ParamField type="string">
  Always `list`.
</ParamField>

<ParamField type="boolean">
  Whether more links exist beyond this page.
</ParamField>

<ParamField type="array">
  The clicked links, ordered by total clicks, descending.

  <Expandable title="properties">
    <ParamField type="string">
      An opaque cursor for this row, used only for pagination. It does not
      identify any entity in Resend.
    </ParamField>

    <ParamField type="string">
      The URL that was clicked.
    </ParamField>

    <ParamField type="number">
      Total clicks on this link, including repeat clicks by the same
      recipient.
    </ParamField>

    <ParamField type="number">
      The number of distinct recipients who clicked this link.
    </ParamField>
  </Expandable>
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.broadcasts.clickedLinks(
    '559ac32e-9ef5-46fb-82a1-b76b840c0f7b',
    { limit: 20 },
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/broadcasts/559ac32e-9ef5-46fb-82a1-b76b840c0f7b/clicked-links?limit=20' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": true,
    "data": [
      {
        "id": "b2Zmc2V0OjA",
        "url": "https://resend.com/pricing",
        "clicks": 42,
        "unique_clicks": 30
      },
      {
        "id": "b2Zmc2V0OjE",
        "url": "https://resend.com/docs",
        "clicks": 17,
        "unique_clicks": 15
      }
    ]
  }
  ```
</ResponseExample>


# List Recipients
Source: https://resend.com/docs/api-reference/broadcasts/list-broadcast-recipients

GET /broadcasts/:broadcast_id/recipients
Retrieve the recipients of a broadcast for a given event type.

<Warning>
  Broadcast metrics and recipients are currently in private beta and only
  available to a limited number of users. APIs might change before it is generally available.
  [Get in touch](https://resend.com/contact) if you're interested in testing
  this feature.

  <span />

  Once you have access, upgrade your Resend SDK to use the methods on this
  page:

  <CodeGroup>
    ```bash Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
    npm install resend@6.19.0-preview-headless-dashboard.7
    ```
  </CodeGroup>
</Warning>

Retrieve the recipients of a broadcast, filtered by a single event `type` (for
example everyone who `opened`, `clicked`, or `bounced`). Results are paginated
with cursors. See [Pagination](/docs/api-reference/pagination) for how `after` and
`before` work.

<Info>
  Responses are cached for up to 15 minutes, so requesting the same page again
  may return slightly stale data within that window.
</Info>

## Path Parameters

<ResendParamField type="string">
  The broadcast ID.
</ResendParamField>

## Query Parameters

<ResendParamField type="string">
  The event to filter recipients by. One of `sent`, `delivered`, `opened`,
  `clicked`, `bounced`, `complained`, `unsubscribed`, or `suppressed`.
</ResendParamField>

<ResendParamField type="number">
  Number of recipients to return. Between `1` and `100`. Defaults to `20`.
</ResendParamField>

<ResendParamField type="string">
  Cursor to fetch the page after this recipient. Cannot be used with `before`.
</ResendParamField>

<ResendParamField type="string">
  Cursor to fetch the page before this recipient. Cannot be used with `after`.
</ResendParamField>

<ResendParamField type="string">
  Filter recipients whose email contains this value.
</ResendParamField>

<ResendParamField type="string">
  Filter by bounce classification. One of `permanent`, `transient`, or
  `undetermined`. Can only be used with `type=bounced`.
</ResendParamField>

## Response Fields

<ParamField type="string">
  Always `list`.
</ParamField>

<ParamField type="boolean">
  Whether more recipients exist beyond this page.
</ParamField>

<ParamField type="array">
  The recipients matching the requested `type`.

  <Expandable title="properties">
    <ParamField type="string">
      An opaque cursor for this row, used only for pagination. It does not
      identify any entity in Resend. Use `contact_id` to reference the contact.
    </ParamField>

    <ParamField type="string | null">
      The matching contact's ID. `null` when the recipient's email no longer
      maps to a contact.
    </ParamField>

    <ParamField type="string">
      The recipient's email address.
    </ParamField>

    <ParamField type="number">
      How many times the recipient triggered the event. Only returned for
      `type=opened` and `type=clicked`.
    </ParamField>

    <ParamField type="string | null">
      The bounce classification: `permanent`, `transient`, or `undetermined`.
      Only returned for `type=bounced`.
    </ParamField>

    <ParamField type="array">
      The links this recipient clicked. Only returned for `type=clicked`.

      <Expandable title="properties">
        <ParamField type="string">
          The URL that was clicked.
        </ParamField>

        <ParamField type="number">
          How many times the recipient clicked this link.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.broadcasts.recipients(
    '559ac32e-9ef5-46fb-82a1-b76b840c0f7b',
    { type: 'clicked', limit: 20 },
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/broadcasts/559ac32e-9ef5-46fb-82a1-b76b840c0f7b/recipients?type=clicked&limit=20' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": true,
    "data": [
      {
        "id": "b2Zmc2V0OjA",
        "contact_id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
        "email": "carter@example.com",
        "count": 3,
        "clicked_links": [
          { "url": "https://resend.com/pricing", "clicks": 2 },
          { "url": "https://resend.com/docs", "clicks": 1 }
        ]
      },
      {
        "id": "b2Zmc2V0OjE",
        "contact_id": null,
        "email": "dana@example.com",
        "count": 1,
        "clicked_links": [{ "url": "https://resend.com/pricing", "clicks": 1 }]
      }
    ]
  }
  ```
</ResponseExample>


# List Broadcasts
Source: https://resend.com/docs/api-reference/broadcasts/list-broadcasts

GET /broadcasts
Retrieve a list of broadcast.

<Info>
  See all available `status` types in [the Broadcasts
  overview](/docs/dashboard/broadcasts/manage-broadcasts#understand-broadcast-statuses).
</Info>

<QueryParams type="broadcasts" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.broadcasts.list();
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->broadcasts->list();
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Broadcasts.list()
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Broadcasts.list()
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Broadcasts.List()
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result, list_opts::ListOptions};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _broadcasts = resend.broadcasts.list(ListOptions::default()).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend resend = new Resend("re_xxxxxxxxx");

  ListBroadcastsResponseSuccess data = resend.broadcasts().list();
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.BroadcastListAsync();
  Console.WriteLine( "Nr Broadcasts={0}", resp.Content.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/broadcasts' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend broadcasts list
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
        "name": "Announcements",
        "audience_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf", // now called segment_id
        "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
        "status": "draft",
        "created_at": "2026-11-01 15:13:31.723+00",
        "scheduled_at": null,
        "sent_at": null
      },
      {
        "id": "559ac32e-9ef5-46fb-82a1-b76b840c0f7b",
        "name": "Black Friday",
        "audience_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf", // now called segment_id
        "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
        "status": "sent",
        "created_at": "2026-12-01 19:32:22.980+00",
        "scheduled_at": "2026-12-02 19:32:22.980+00",
        "sent_at": "2026-12-02 19:32:22.980+00"
      }
    ]
  }
  ```
</ResponseExample>


# Send Broadcast
Source: https://resend.com/docs/api-reference/broadcasts/send-broadcast

POST /broadcasts/:broadcast_id/send
Start sending broadcasts to your audience through the Resend API.

<Note>You can send broadcasts only if they were created via the API.</Note>

## Path Parameters

<ResendParamField type="string">
  The broadcast ID.
</ResendParamField>

## Body Parameters

<ResendParamField type="string">
  Schedule email to be sent later. The date should be in natural language (e.g.:
  `in 1 min`) or ISO 8601 format (e.g: `2026-08-05T11:52:01.858Z`).
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.broadcasts.send(
    '559ac32e-9ef5-46fb-82a1-b76b840c0f7b',
    {
      scheduledAt: 'in 1 min',
    },
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->broadcasts->send('559ac32e-9ef5-46fb-82a1-b76b840c0f7b', [
    'scheduled_at' => 'in 1 min',
  ]);
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Broadcasts.SendParams = {
    "broadcast_id": "559ac32e-9ef5-46fb-82a1-b76b840c0f7b",
    "scheduled_at": "in 1 min"
  }
  resend.Broadcasts.send(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    broadcast_id: "559ac32e-9ef5-46fb-82a1-b76b840c0f7b",
    scheduled_at: "in 1 min"
  }
  Resend::Broadcasts.send(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	sendParams := &resend.SendBroadcastRequest{
  		BroadcastId: "559ac32e-9ef5-46fb-82a1-b76b840c0f7b",
  		ScheduledAt: "in 1 min",
  	}

  	client.Broadcasts.Send(sendParams)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::SendBroadcastOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let opts =
      SendBroadcastOptions::new("559ac32e-9ef5-46fb-82a1-b76b840c0f7b").with_scheduled_at("in 1 min");

    let _broadcast = resend.broadcasts.send(opts).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend resend = new Resend("re_xxxxxxxxx");

  SendBroadcastOptions params = SendBroadcastOptions.builder()
      .scheduledAt("in 1 min")
      .build();

  SendBroadcastResponseSuccess data = resend.broadcasts().send(params,
      "498ee8e4-7aa2-4eb5-9f04-4194848049d1");
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  // Send now
  await resend.BroadcastSendAsync( new Guid( "559ac32e-9ef5-46fb-82a1-b76b840c0f7b" ) );

  // Send in 5 mins
  await resend.BroadcastScheduleAsync(
      new Guid( "559ac32e-9ef5-46fb-82a1-b76b840c0f7b" ),
      DateTime.UtcNow.AddMinutes( 5 ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/broadcasts/559ac32e-9ef5-46fb-82a1-b76b840c0f7b/send' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "scheduled_at": "in 1 min"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend broadcasts send 559ac32e-9ef5-46fb-82a1-b76b840c0f7b --scheduled-at "in 1 min"
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794"
  }
  ```
</ResponseExample>


# Update Broadcast
Source: https://resend.com/docs/api-reference/broadcasts/update-broadcast

PATCH /broadcasts/:broadcast_id
Update a broadcast to send to your contacts.

## Path Parameters

<ResendParamField type="string">
  The ID of the broadcast you want to update.
</ResendParamField>

## Body Parameters

<ResendParamField type="string">
  The ID of the segment you want to send to.

  <Info>
    Audiences are now called Segments. Follow the [Migration
    Guide](/docs/dashboard/segments/migrating-from-audiences-to-segments).
  </Info>
</ResendParamField>

<ParamField type="string">
  Sender email address.

  To include a friendly name, use the format `"Your Name <sender@domain.com>"`.
</ParamField>

<ParamField type="string">
  Email subject.
</ParamField>

<ResendParamField type="string | string[]">
  Reply-to email address. For multiple addresses, send as an array of strings.
</ResendParamField>

<ParamField type="string">
  The HTML version of the message.
</ParamField>

<ParamField type="string">
  The plain text version of the message.

  <Info>
    If not provided, the HTML will be used to generate a plain text version. You
    can opt out of this behavior by setting value to an empty string.
  </Info>
</ParamField>

<ParamField type="React.ReactNode">
  The React component used to write the message. *Only available in the Node.js
  SDK.*
</ParamField>

<ParamField type="string">
  The friendly name of the broadcast. Only used for internal reference.
</ParamField>

<ResendParamField type="string">
  The topic ID that the broadcast will be scoped to.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.broadcasts.update(
    '49a3999c-0ce1-4ea6-ab68-afcd6dc2e794',
    {
      html: 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
    },
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->broadcasts->update('49a3999c-0ce1-4ea6-ab68-afcd6dc2e794', [
    'html' => 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
  ]);
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Broadcasts.UpdateParams = {
    "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}"
  }

  resend.Broadcasts.update(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
  }
  Resend::Broadcasts.update(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.UpdateBroadcastRequest{
  		Id:   "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
  		Html: "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
  	}

  	client.Broadcasts.Update(params)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::UpdateBroadcastOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let id = "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794";
    let html = "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}";

    let opts = UpdateBroadcastOptions::new().with_html(html);

    let _broadcast = resend.broadcasts.update(id, opts).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend resend = new Resend("re_xxxxxxxxx");

  UpdateBroadcastOptions params = UpdateBroadcastOptions.builder()
      .id("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794")
      .html("Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}")
      .build();

  UpdateBroadcastResponseSuccess data = resend.broadcasts().update(params);
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.BroadcastUpdateAsync(
      new Guid( "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794" ),
      new BroadcastUpdateData()
      {
          HtmlBody = "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
      }
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X PATCH 'https://api.resend.com/broadcasts/49a3999c-0ce1-4ea6-ab68-afcd6dc2e794' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend broadcasts update 49a3999c-0ce1-4ea6-ab68-afcd6dc2e794 \
    --html "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}"
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "broadcast",
    "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794"
  }
  ```
</ResponseExample>


# Create Contact Property
Source: https://resend.com/docs/api-reference/contact-properties/create-contact-property

POST /contact-properties
Create a custom property for your contacts.

## Body Parameters

<ResendParamField type="string">
  The property key. Max length is `50` characters. Only alphanumeric characters
  and underscores are allowed.
</ResendParamField>

<ResendParamField type="string">
  The property type. Possible values: `string` or `number`.
</ResendParamField>

<ResendParamField type="string | number">
  The default value to use when the property is not set for a contact. Must
  match the type specified in the `type` field.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.contactProperties.create({
    key: 'company_name',
    type: 'string',
    fallbackValue: 'Acme Corp',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->contactProperties->create([
    'key' => 'company_name',
    'type' => 'string',
    'fallback_value' => 'Acme Corp',
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  params = {
      "key": "company_name",
      "type": "string",
      "fallback_value": "Acme Corp",
  }

  contact_property = resend.ContactProperties.create(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  property = Resend::ContactProperties.create({
    key: "company_name",
    type: "string",
    fallback_value: "Acme Corp"
  })
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.CreateContactPropertyRequest{
  		Key:           "company_name",
  		Type:          "string",
  		FallbackValue: "Acme Corp",
  	}

  	property, err := client.ContactProperties.CreateWithContext(ctx, params)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(property)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{
    types::{CreateContactPropertyOptions, PropertyType},
    Resend, Result,
  };

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let contact_property = CreateContactPropertyOptions::new("company_name", PropertyType::String)
      .with_fallback("Acme Corp");

    let _contact_property = resend.contacts.create_property(contact_property).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      CreateContactPropertyOptions options = CreateContactPropertyOptions.builder()
        .key("company_name")
        .type("string")
        .fallbackValue("Acme Corp")
        .build();

      resend.contactProperties().create(options);
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ContactPropCreateAsync( new ContactPropertyData() {
    Key = "company_name",
    PropertyType = ContactPropertyType.String,
    DefaultValue = "Acme Corp",
  } );
  Console.WriteLine( "Prop Id={0}", resp.Content );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/contact-properties' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "key": "company_name",
    "type": "string",
    "fallback_value": "Acme Corp"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend contact-properties create \
    --key company_name \
    --type string \
    --fallback-value "Acme Corp"
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "contact_property",
    "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e"
  }
  ```
</ResponseExample>


# Delete Contact Property
Source: https://resend.com/docs/api-reference/contact-properties/delete-contact-property

DELETE /contact-properties/:contact_property_id
Remove an existing contact property.

## Path Parameters

<ResendParamField type="string">
  The Contact Property ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.contactProperties.remove(
    'b6d24b8e-af0b-4c3c-be0c-359bbd97381e',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->contactProperties->remove('b6d24b8e-af0b-4c3c-be0c-359bbd97381');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  contact_property = resend.ContactProperties.remove('b6d24b8e-af0b-4c3c-be0c-359bbd97381e')
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::ContactProperties.remove("b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	property, err := client.ContactProperties.RemoveWithContext(ctx, "b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(property)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _deleted = resend
      .contacts
      .delete_property("b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      resend.contactProperties().remove("b6d24b8e-af0b-4c3c-be0c-359bbd97381e");
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ContactPropDeleteAsync( new Guid( "b6d24b8e-af0b-4c3c-be0c-359bbd97381e" ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X DELETE 'https://api.resend.com/contact-properties/b6d24b8e-af0b-4c3c-be0c-359bbd97381e' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend contact-properties delete b6d24b8e-af0b-4c3c-be0c-359bbd97381e --yes
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "contact_property",
    "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
    "deleted": true
  }
  ```
</ResponseExample>


# Retrieve Contact Property
Source: https://resend.com/docs/api-reference/contact-properties/get-contact-property

GET /contact-properties/:contact_property_id
Retrieve a contact property by its ID.

## Path Parameters

<ResendParamField type="string">
  The Contact Property ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.contactProperties.get(
    'b6d24b8e-af0b-4c3c-be0c-359bbd97381e',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->contactProperties->get('b6d24b8e-af0b-4c3c-be0c-359bbd97381');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  contact_property = resend.ContactProperties.get('b6d24b8e-af0b-4c3c-be0c-359bbd97381e')
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  property = Resend::ContactProperties.get("b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	property, err := client.ContactProperties.GetWithContext(ctx, "b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(property)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _property = resend
      .contacts
      .get_property("b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      resend.contactProperties().get("b6d24b8e-af0b-4c3c-be0c-359bbd97381e");
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ContactPropRetrieveAsync( new Guid( "b6d24b8e-af0b-4c3c-be0c-359bbd97381e" ) );
  Console.WriteLine( "Prop Id={0}", resp.Content.Id );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/contact-properties/b6d24b8e-af0b-4c3c-be0c-359bbd97381e' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend contact-properties get b6d24b8e-af0b-4c3c-be0c-359bbd97381e
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "contact_property",
    "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
    "key": "company_name",
    "type": "string",
    "fallback_value": "Acme Corp",
    "created_at": "2026-04-08 00:11:13.110779+00"
  }
  ```
</ResponseExample>


# List Contact Properties
Source: https://resend.com/docs/api-reference/contact-properties/list-contact-properties

GET /contact-properties
Retrieve a list of contact properties.

<QueryParams type="contact-properties" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.contactProperties.list();
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->contactProperties->list();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  contact_properties = resend.ContactProperties.list()
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  properties = Resend::ContactProperties.list
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	properties, err := client.ContactProperties.ListWithContext(ctx)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(properties)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{list_opts::ListOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _contact_properties = resend
      .contacts
      .list_properties(ListOptions::default())
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      resend.contactProperties().list();
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ContactPropListAsync();
  Console.WriteLine( "Nr Props={0}", resp.Content.Data.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/contact-properties' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend contact-properties list
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
        "key": "company_name",
        "type": "string",
        "fallback_value": "Acme Corp",
        "created_at": "2026-04-08 00:11:13.110779+00"
      }
    ]
  }
  ```
</ResponseExample>


# Update Contact Property
Source: https://resend.com/docs/api-reference/contact-properties/update-contact-property

PATCH /contact-properties/:contact_property_id
Update an existing contact property.

## Path Parameters

<ResendParamField type="string">
  The Contact Property ID.
</ResendParamField>

<Note>
  The `key` and `type` fields cannot be changed after creation. This preserves
  data integrity for existing contact values.
</Note>

## Body Parameters

<ResendParamField type="string | number">
  The default value to use when the property is not set for a contact. Must
  match the type of the property.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.contactProperties.update({
    id: 'b6d24b8e-af0b-4c3c-be0c-359bbd97381e',
    fallbackValue: 'Example Company',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->contactProperties->update('b6d24b8e-af0b-4c3c-be0c-359bbd97381', [
    'fallback_value' => 'Example Company',
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  params = {
      "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
      "fallback_value": "Example Company",
  }

  contact_property = resend.ContactProperties.update(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  property = Resend::ContactProperties.update({
    id: "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
    fallback_value: "Example Company"
  })
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.UpdateContactPropertyRequest{
  		Id:            "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
  		FallbackValue: "Example Company",
  	}

  	property, err := client.ContactProperties.UpdateWithContext(ctx, params)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(property)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::ContactPropertyChanges, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let update = ContactPropertyChanges::default().with_fallback("Example Company");
    let _contact_property = resend
      .contacts
      .update_property("b6d24b8e-af0b-4c3c-be0c-359bbd97381e", update)
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      UpdateContactPropertyOptions options = UpdateContactPropertyOptions.builder()
        .id("b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
        .fallbackValue("Example Company")
        .build();

      resend.contactProperties().update(options);
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ContactPropUpdateAsync(
    new Guid( "b6d24b8e-af0b-4c3c-be0c-359bbd97381e" ),
    new ContactPropertyUpdateData() {
      DefaultValue = "Example Company",
    }
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X PATCH 'https://api.resend.com/contact-properties/b6d24b8e-af0b-4c3c-be0c-359bbd97381e' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "fallback_value": "Example Company"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend contact-properties update b6d24b8e-af0b-4c3c-be0c-359bbd97381e \
    --fallback-value "Example Company"
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "contact_property",
    "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e"
  }
  ```
</ResponseExample>


# Add Contact to Segment
Source: https://resend.com/docs/api-reference/contacts/add-contact-to-segment

POST /contacts/:contact_id/segments/:segment_id
Add an existing contact to a segment.

## Path Parameters

Either `id` or `email` must be provided.

<ParamField type="string">
  The Contact ID.
</ParamField>

<ParamField type="string">
  The Contact Email.
</ParamField>

<ResendParamField type="string">
  The Segment ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Add by contact id
  const { data, error } = await resend.contacts.segments.add({
    contactId: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf',
  });

  // Add by contact email
  const { data, error } = await resend.contacts.segments.add({
    email: 'steve.wozniak@gmail.com',
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Add by contact id
  $resend->contacts->segments->add(
    contact: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf'
  );

  // Add by contact email
  $resend->contacts->segments->add(
    contact: 'steve.wozniak@gmail.com',
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf'
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  # Add by contact id
  params = {
      "segment_id": '78261eea-8f8b-4381-83c6-79fa7120f1cf',
      "contact_id": 'e169aa45-1ecf-4183-9955-b1499d5701d3',
  }

  response = resend.Contacts.Segments.add(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require 'resend'

  Resend.api_key = 're_xxxxxxxxx'

  # Add by contact id
  result = Resend::Contacts::Segments.add(
    contact_id: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    segment_id: '78261eea-8f8b-4381-83c6-79fa7120f1cf'
  )

  # Add by contact email
  result = Resend::Contacts::Segments.add(
    email: 'steve.wozniak@gmail.com',
    segment_id: '78261eea-8f8b-4381-83c6-79fa7120f1cf'
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	// Add by contact id
  	addParams := &resend.AddContactSegmentRequest{
  		ContactId: "e169aa45-1ecf-4183-9955-b1499d5701d3",
  		SegmentId: "78261eea-8f8b-4381-83c6-79fa7120f1cf",
  	}

  	response, err := client.Contacts.Segments.AddWithContext(ctx, addParams)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(response)

  	// Add by contact email
  	addByEmailParams := &resend.AddContactSegmentRequest{
  		Email:     "steve.wozniak@gmail.com",
  		SegmentId: "78261eea-8f8b-4381-83c6-79fa7120f1cf",
  	}

  	response, err = client.Contacts.Segments.AddWithContext(ctx, addByEmailParams)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(response)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    // Update by contact id
    let _contact = resend
      .contacts
      .add_contact_segment(
        "e169aa45-1ecf-4183-9955-b1499d5701d3",
        "78261eea-8f8b-4381-83c6-79fa7120f1cf",
      )
      .await?;

    // // Update by contact email
    let _contact = resend
      .contacts
      .add_contact_segment(
        "steve.wozniak@gmail.com",
        "78261eea-8f8b-4381-83c6-79fa7120f1cf",
      )
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      // Add by contact id
      AddContactToSegmentOptions optionsById = AddContactToSegmentOptions.builder()
        .id("e169aa45-1ecf-4183-9955-b1499d5701d3")
        .segmentId("78261eea-8f8b-4381-83c6-79fa7120f1cf")
        .build();

      resend.contacts().segments().add(optionsById);

      // Add by contact email
      AddContactToSegmentOptions optionsByEmail = AddContactToSegmentOptions.builder()
        .email("steve.wozniak@gmail.com")
        .segmentId("78261eea-8f8b-4381-83c6-79fa7120f1cf")
        .build();

      resend.contacts().segments().add(optionsByEmail);
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.ContactAddToSegmentAsync(
      contactId: new Guid( "e169aa45-1ecf-4183-9955-b1499d5701d3" ),
      segmentId: new Guid( "78261eea-8f8b-4381-83c6-79fa7120f1cf" )
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  // Update by contact id
  curl -X POST 'https://api.resend.com/contacts/e169aa45-1ecf-4183-9955-b1499d5701d3/segments/78261eea-8f8b-4381-83c6-79fa7120f1cf' \
       -H 'Authorization: Bearer re_xxxxxxxxx'

  // Update by contact email
  curl -X POST 'https://api.resend.com/contacts/steve.wozniak@gmail.com/segments/78261eea-8f8b-4381-83c6-79fa7120f1cf' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Add by contact id
  resend contacts add-segment e169aa45-1ecf-4183-9955-b1499d5701d3 \
    --segment-id 78261eea-8f8b-4381-83c6-79fa7120f1cf

  # Add by contact email
  resend contacts add-segment steve.wozniak@gmail.com \
    --segment-id 78261eea-8f8b-4381-83c6-79fa7120f1cf
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "id": "78261eea-8f8b-4381-83c6-79fa7120f1cf"
  }
  ```
</ResponseExample>


# Create Contact
Source: https://resend.com/docs/api-reference/contacts/create-contact

POST /contacts
Create a contact.

## Body Parameters

<ParamField type="string">
  The email address of the contact.
</ParamField>

<ResendParamField type="string">
  The first name of the contact.
</ResendParamField>

<ResendParamField type="string">
  The last name of the contact.
</ResendParamField>

<ParamField type="boolean">
  The Contact's global subscription status. If set to `true`, the contact will
  be unsubscribed from all Broadcasts.
</ParamField>

<ParamField type="object">
  A map of custom property keys and values to create.

  <Expandable title="custom properties">
    <ParamField type="string">
      The property key.
    </ParamField>

    <ParamField type="string">
      The property value.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField type="array">
  Array of objects. Each object must contain the ID of the segment that you'd like to add the contact to.

  <Expandable title="segments">
    <ParamField type="string">
      The segment ID.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField type="array">
  Array of topic subscriptions for the contact.

  <Expandable title="topics">
    <ParamField type="string">
      The topic ID.
    </ParamField>

    <ParamField type="'opt_in' | 'opt_out'">
      The subscription status for this topic.
    </ParamField>
  </Expandable>
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.contacts.create({
    email: 'steve.wozniak@gmail.com',
    firstName: 'Steve',
    lastName: 'Wozniak',
    unsubscribed: false,
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->contacts->create(
    parameters: [
      'email' => 'steve.wozniak@gmail.com',
      'first_name' => 'Steve',
      'last_name' => 'Wozniak',
      'unsubscribed' => false
    ]
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Contacts.CreateParams = {
    "email": "steve.wozniak@gmail.com",
    "first_name": "Steve",
    "last_name": "Wozniak",
    "unsubscribed": False,
  }

  resend.Contacts.create(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    "email": "steve.wozniak@gmail.com",
    "first_name": "Steve",
    "last_name": "Wozniak",
    "unsubscribed": false,
  }

  Resend::Contacts.create(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.CreateContactRequest{
  		Email:        "steve.wozniak@gmail.com",
  		FirstName:    "Steve",
  		LastName:     "Wozniak",
  		Unsubscribed: false,
  	}

  	client.Contacts.Create(params)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::CreateContactOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let contact = CreateContactOptions::new("steve.wozniak@gmail.com")
      .with_first_name("Steve")
      .with_last_name("Wozniak")
      .with_unsubscribed(false);

    let _contact = resend.contacts.create(contact).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateContactOptions params = CreateContactOptions.builder()
                  .email("steve.wozniak@gmail.com")
                  .firstName("Steve")
                  .lastName("Wozniak")
                  .unsubscribed(false)
                  .build();

          CreateContactResponseSuccess data = resend.contacts().create(params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ContactAddAsync(
      new ContactData()
      {
          Email = "steve.wozniak@gmail.com",
          FirstName = "Steve",
          LastName = "Wozniak",
          IsUnsubscribed = false,
      }
  );
  Console.WriteLine( "Contact Id={0}", resp.Content );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/contacts' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "email": "steve.wozniak@gmail.com",
    "first_name": "Steve",
    "last_name": "Wozniak",
    "unsubscribed": false
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend contacts create \
    --email steve.wozniak@gmail.com \
    --first-name Steve \
    --last-name Wozniak
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "contact",
    "id": "479e3145-dd38-476b-932c-529ceb705947"
  }
  ```
</ResponseExample>


# Delete Contact
Source: https://resend.com/docs/api-reference/contacts/delete-contact

DELETE /contacts/:contact_id
Remove an existing contact.

## Path Parameters

Either `id` or `email` must be provided.

<ParamField type="string">
  The Contact ID.
</ParamField>

<ParamField type="string">
  The Contact email.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Delete by contact id
  const { data, error } = await resend.contacts.remove({
    id: '520784e2-887d-4c25-b53c-4ad46ad38100',
  });

  // Delete by contact email
  const { data, error } = await resend.contacts.remove({
    email: 'acme@example.com',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Delete by contact id
  $resend->contacts->remove(
    id: '520784e2-887d-4c25-b53c-4ad46ad38100'
  );

  // Delete by contact email
  $resend->contacts->remove(
    email: 'acme@example.com'
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  # Delete by contact id
  resend.Contacts.remove(
    id="520784e2-887d-4c25-b53c-4ad46ad38100"
  )

  # Delete by contact email
  resend.Contacts.remove(
    email="acme@example.com"
  )
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  # Delete by contact id
  Resend::Contacts.remove(
    id: "520784e2-887d-4c25-b53c-4ad46ad38100"
  )

  # Delete by contact email
  Resend::Contacts.remove(
    email: "acme@example.com"
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	// Delete by contact id
  	client.Contacts.Remove("520784e2-887d-4c25-b53c-4ad46ad38100")

  	// Delete by contact email
  	client.Contacts.Remove("acme@example.com")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    // Delete by contact id
    let _deleted = resend
      .contacts
      .delete("520784e2-887d-4c25-b53c-4ad46ad38100")
      .await?;

    // Delete by contact email
    let _deleted = resend
      .contacts
      .delete("acme@example.com")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          // Delete by contact id
          resend.contacts().remove(ContactRequestOptions.builder()
                          .id("520784e2-887d-4c25-b53c-4ad46ad38100")
                          .build());

          // Delete by contact email
          resend.contacts().remove(ContactRequestOptions.builder()
                          .email("acme@example.com")
                          .build());
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  // By Id
  await resend.ContactDeleteAsync(
      contactId: new Guid( "520784e2-887d-4c25-b53c-4ad46ad38100" )
  );

  // By Email
  await resend.ContactDeleteByEmailAsync(
      "acme@example.com"
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Delete by contact id
  curl -X DELETE 'https://api.resend.com/contacts/520784e2-887d-4c25-b53c-4ad46ad38100' \
       -H 'Authorization: Bearer re_xxxxxxxxx'

  # Deleted by contact email
  curl -X DELETE 'https://api.resend.com/contacts/acme@example.com' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Delete by contact id
  resend contacts delete 520784e2-887d-4c25-b53c-4ad46ad38100

  # Delete by contact email
  resend contacts delete acme@example.com
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "contact",
    "contact": "520784e2-887d-4c25-b53c-4ad46ad38100",
    "deleted": true
  }
  ```
</ResponseExample>


# Delete Contact Segment
Source: https://resend.com/docs/api-reference/contacts/delete-contact-segment

DELETE /contacts/:contact_id/segments/:segment_id
Remove an existing contact from a segment.

## Path Parameters

Either `id` or `email` must be provided.

<ParamField type="string">
  The Contact ID.
</ParamField>

<ParamField type="string">
  The Contact Email.
</ParamField>

<ResendParamField type="string">
  The Segment ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Remove by contact id
  const { data, error } = await resend.contacts.segments.remove({
    id: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf',
  });

  // Remove by contact email
  const { data, error } = await resend.contacts.segments.remove({
    email: 'steve.wozniak@gmail.com',
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Remove by contact id
  $resend->contacts->segments->remove(
    contact: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf'
  );

  // Remove by contact email
  $resend->contacts->segments->remove(
    contact: 'steve.wozniak@gmail.com',
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf'
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  # Remove by contact id
  params = {
      "segment_id": '78261eea-8f8b-4381-83c6-79fa7120f1cf',
      "contact_id": 'e169aa45-1ecf-4183-9955-b1499d5701d3',
  }

  response = resend.Contacts.Segments.remove(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require 'resend'

  Resend.api_key = 're_xxxxxxxxx'

  # Remove by contact id
  removed = Resend::Contacts::Segments.remove(
    contact_id: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    segment_id: '78261eea-8f8b-4381-83c6-79fa7120f1cf'
  )

  # Remove by contact email
  removed = Resend::Contacts::Segments.remove(
    email: 'steve.wozniak@gmail.com',
    segment_id: '78261eea-8f8b-4381-83c6-79fa7120f1cf'
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	// Remove by contact id
  	removeParams := &resend.RemoveContactSegmentRequest{
  		ContactId: "e169aa45-1ecf-4183-9955-b1499d5701d3",
  		SegmentId: "78261eea-8f8b-4381-83c6-79fa7120f1cf",
  	}

  	response, err := client.Contacts.Segments.RemoveWithContext(ctx, removeParams)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(response)

  	// Remove by contact email
  	removeByEmailParams := &resend.RemoveContactSegmentRequest{
  		Email:     "steve.wozniak@gmail.com",
  		SegmentId: "78261eea-8f8b-4381-83c6-79fa7120f1cf",
  	}

  	response, err = client.Contacts.Segments.RemoveWithContext(ctx, removeByEmailParams)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(response)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    // Update by contact id
    let _contact = resend
      .contacts
      .delete_contact_segment(
        "e169aa45-1ecf-4183-9955-b1499d5701d3",
        "78261eea-8f8b-4381-83c6-79fa7120f1cf",
      )
      .await?;

    // // Update by contact email
    let _contact = resend
      .contacts
      .delete_contact_segment(
        "steve.wozniak@gmail.com",
        "78261eea-8f8b-4381-83c6-79fa7120f1cf",
      )
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      // Remove by contact id
      RemoveContactFromSegmentOptions optionsById = RemoveContactFromSegmentOptions.builder()
        .id("e169aa45-1ecf-4183-9955-b1499d5701d3")
        .segmentId("78261eea-8f8b-4381-83c6-79fa7120f1cf")
        .build();

      resend.contacts().segments().remove(optionsById);

      // Remove by contact email
      RemoveContactFromSegmentOptions optionsByEmail = RemoveContactFromSegmentOptions.builder()
        .email("steve.wozniak@gmail.com")
        .segmentId("78261eea-8f8b-4381-83c6-79fa7120f1cf")
        .build();

      resend.contacts().segments().remove(optionsByEmail);
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.ContactRemoveFromSegmentAsync(
      contactId: new Guid( "e169aa45-1ecf-4183-9955-b1499d5701d3" ),
      segmentId: new Guid( "78261eea-8f8b-4381-83c6-79fa7120f1cf" )
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  // Update by contact id
  curl -X DELETE 'https://api.resend.com/contacts/e169aa45-1ecf-4183-9955-b1499d5701d3/segments/78261eea-8f8b-4381-83c6-79fa7120f1cf' \
       -H 'Authorization: Bearer re_xxxxxxxxx'

  // Update by contact email
  curl -X DELETE 'https://api.resend.com/contacts/steve.wozniak@gmail.com/segments/78261eea-8f8b-4381-83c6-79fa7120f1cf' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Remove by contact id
  resend contacts remove-segment e169aa45-1ecf-4183-9955-b1499d5701d3 78261eea-8f8b-4381-83c6-79fa7120f1cf

  # Remove by contact email
  resend contacts remove-segment steve.wozniak@gmail.com 78261eea-8f8b-4381-83c6-79fa7120f1cf
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "contact_segment",
    "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
    "audienceId": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "deleted": true
  }
  ```
</ResponseExample>


# Retrieve Contact
Source: https://resend.com/docs/api-reference/contacts/get-contact

GET /contacts/:contact_id
Retrieve a single contact.

## Path Parameters

Either `id` or `email` must be provided.

<ParamField type="string">
  The Contact ID.
</ParamField>

<ParamField type="string">
  The Contact Email.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Get by contact id
  const { data, error } = await resend.contacts.get({
    id: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
  });

  // Get by contact email
  const { data, error } = await resend.contacts.get({
    email: 'steve.wozniak@gmail.com',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Get by contact id
  $resend->contacts->get(
    id: 'e169aa45-1ecf-4183-9955-b1499d5701d3'
  );

  // Get by contact email
  $resend->contacts->get(
    email: 'steve.wozniak@gmail.com'
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  # Get by contact id
  resend.Contacts.get(
    id="e169aa45-1ecf-4183-9955-b1499d5701d3",
  )

  # Get by contact email
  resend.Contacts.get(
    email="steve.wozniak@gmail.com",
  )
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  # Get by contact id
  params = {
    "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
  }

  Resend::Contacts.get(params)

  # Get by contact email
  params = {
    "email": "steve.wozniak@gmail.com",
  }

  Resend::Contacts.get(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	// Get by contact id
  	client.Contacts.Get("e169aa45-1ecf-4183-9955-b1499d5701d3")

  	// Get by contact email
  	client.Contacts.Get("steve.wozniak@gmail.com")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    // Get by contact id
    let _contact = resend
      .contacts
      .get("e169aa45-1ecf-4183-9955-b1499d5701d3")
      .await?;

    // Get by contact email
    let _contact = resend
      .contacts
      .get("steve.wozniak@gmail.com")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          // Get by contact id
          GetContactOptions params = GetContactOptions.builder()
                  .id("e169aa45-1ecf-4183-9955-b1499d5701d3")
                  .build();

          // Get by contact email
          GetContactOptions params = GetContactOptions.builder()
                  .email("steve.wozniak@gmail.com")
                  .build();

          GetContactResponseSuccess data = resend.contacts().get(params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  // Get by contact id
  var resp1 = await resend.ContactRetrieveAsync(
      contactId: new Guid( "e169aa45-1ecf-4183-9955-b1499d5701d3" )
  );

  // Get by contact email
  var resp2 = await resend.ContactRetrieveByEmailAsync(
      email: "steve.wozniak@gmail.com"
  );

  Console.WriteLine( "Contact Email={0}", resp2.Content.Email );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Get by contact id
  curl -X GET 'https://api.resend.com/contacts/e169aa45-1ecf-4183-9955-b1499d5701d3' \
       -H 'Authorization: Bearer re_xxxxxxxxx'

  # Get by contact email
  curl -X GET 'https://api.resend.com/contacts/steve.wozniak@gmail.com' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Get by contact id
  resend contacts get e169aa45-1ecf-4183-9955-b1499d5701d3

  # Get by contact email
  resend contacts get steve.wozniak@gmail.com
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "contact",
    "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
    "email": "steve.wozniak@gmail.com",
    "first_name": "Steve",
    "last_name": "Wozniak",
    "created_at": "2026-10-06 23:47:56.678+00",
    "unsubscribed": false,
    "properties": {
      "company_name": {
        "value": "Acme Corp",
        "type": "string"
      },
      "department": {
        "value": "Engineering",
        "type": "string"
      }
    }
  }
  ```
</ResponseExample>


# Retrieve Contact Topics
Source: https://resend.com/docs/api-reference/contacts/get-contact-topics

GET /contacts/:contact_id/topics
Retrieve a list of topics subscriptions for a contact.

## Path Parameters

Either `id` or `email` must be provided.

<ParamField type="string">
  The Contact ID.
</ParamField>

<ParamField type="string">
  The Contact Email.
</ParamField>

<QueryParams type="topics" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Get by contact id
  const { data, error } = await resend.contacts.topics.list({
    id: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
  });

  // Get by contact email
  const { data, error } = await resend.contacts.topics.list({
    email: 'steve.wozniak@gmail.com',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Get by contact id
  $resend->contacts->topics->get('e169aa45-1ecf-4183-9955-b1499d5701d3');

  // Get by contact email
  $resend->contacts->topics->get('steve.wozniak@gmail.com');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  # Get by contact id
  topics = resend.Contacts.Topics.list(contact_id='e169aa45-1ecf-4183-9955-b1499d5701d3')

  # Get by contact email
  topics = resend.Contacts.Topics.list(email='steve.wozniak@gmail.com')
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  # Get by contact id
  contact_topics = Resend::Contacts::Topics.list(id: "e169aa45-1ecf-4183-9955-b1499d5701d3")

  # Get by contact email
  contact_topics = Resend::Contacts::Topics.list(id: "steve.wozniak@gmail.com")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	// Get by contact id
  	topics, err := client.Contacts.Topics.ListWithContext(ctx, &resend.ListContactTopicsRequest{
  		ContactId: "e169aa45-1ecf-4183-9955-b1499d5701d3",
  	})
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(topics)

  	// Get by contact email
  	topics, err = client.Contacts.Topics.ListWithContext(ctx, &resend.ListContactTopicsRequest{
  		Email: "steve.wozniak@gmail.com",
  	})
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(topics)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{list_opts::ListOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _topics = resend
      .contacts
      .get_contact_topics(
        "e169aa45-1ecf-4183-9955-b1499d5701d3",
        ListOptions::default(),
      )
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      // Get by contact id
      resend.contacts().topics().list("e169aa45-1ecf-4183-9955-b1499d5701d3");

      // Get by contact email
      resend.contacts().topics().list("steve.wozniak@gmail.com");
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ContactListTopicsAsync( new Guid( "e169aa45-1ecf-4183-9955-b1499d5701d3" ));
  Console.WriteLine( "Nr Topics={0}", resp.Content.Data.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  // Get by contact id
  curl -X GET 'https://api.resend.com/contacts/e169aa45-1ecf-4183-9955-b1499d5701d3/topics' \
       -H 'Authorization: Bearer re_xxxxxxxxx'

  // Get by contact email
  curl -X GET 'https://api.resend.com/contacts/steve.wozniak@gmail.com/topics' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Get by contact id
  resend contacts topics e169aa45-1ecf-4183-9955-b1499d5701d3

  # Get by contact email
  resend contacts topics steve.wozniak@gmail.com
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
        "name": "Product Updates",
        "description": "New features, and latest announcements.",
        "subscription": "opt_in"
      }
    ]
  }
  ```
</ResponseExample>


# List Contact Segments
Source: https://resend.com/docs/api-reference/contacts/list-contact-segments

GET /contacts/:contact_id/segments
Retrieve a list of segments that a contact is part of.

## Path Parameters

Either `id` or `email` must be provided.

<ParamField type="string">
  The Contact ID.
</ParamField>

<ParamField type="string">
  The Contact Email.
</ParamField>

<QueryParams type="segments" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.contacts.segments.list({
    id: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->contacts->segments->list(
    contactId: 'e169aa45-1ecf-4183-9955-b1499d5701d3'
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  params = {
      "contact_id": 'e169aa45-1ecf-4183-9955-b1499d5701d3',
  }

  segments = resend.Contacts.Segments.list(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require 'resend'

  Resend.api_key = 're_xxxxxxxxx'

  segments = Resend::Contacts::Segments.list(
    contact_id: 'e169aa45-1ecf-4183-9955-b1499d5701d3'
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	listParams := &resend.ListContactSegmentsRequest{
  		ContactId: "479e3145-dd38-476b-932c-529ceb705947",
  	}

  	client.Contacts.Segments.List(listParams)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result, list_opts::ListOptions};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _contacts = resend
      .contacts
      .list_contact_segment(
        "e169aa45-1ecf-4183-9955-b1499d5701d3",
        ListOptions::default()
      )
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      resend.contacts().segments().list("e169aa45-1ecf-4183-9955-b1499d5701d3");
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ContactListSegmentsAsync( new Guid( "e169aa45-1ecf-4183-9955-b1499d5701d3" ));
  Console.WriteLine( "Nr Segments={0}", resp.Content.Data.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/contacts/e169aa45-1ecf-4183-9955-b1499d5701d3/segments' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend contacts segments e169aa45-1ecf-4183-9955-b1499d5701d3
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "data": [
      {
        "id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
        "name": "Registered Users",
        "created_at": "2026-10-06 22:59:55.977+00"
      }
    ],
    "has_more": false
  }
  ```
</ResponseExample>


# List Contacts
Source: https://resend.com/docs/api-reference/contacts/list-contacts

GET /contacts
Show all contacts.

## Path Parameters

<ResendParamField type="string">
  The Segment ID to filter contacts by. If provided, only contacts in this Segment will be returned.
</ResendParamField>

<QueryParams type="contacts" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.contacts.list();
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->contacts->list();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Contacts.list()
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Contacts.list()
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Contacts.List()
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result, list_opts::ListOptions};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _contacts = resend
      .contacts
      .list(
          ListOptions::default(),
      )
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          ListContactsResponseSuccess data = resend.contacts().list();
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ContactListAsync();
  Console.WriteLine( "Nr Contacts={0}", resp.Content.Data.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/contacts' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend contacts list
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
        "email": "steve.wozniak@gmail.com",
        "first_name": "Steve",
        "last_name": "Wozniak",
        "created_at": "2026-10-06 23:47:56.678+00",
        "unsubscribed": false
      }
    ]
  }
  ```
</ResponseExample>


# Update Contact
Source: https://resend.com/docs/api-reference/contacts/update-contact

PATCH /contacts/:contact_id
Update an existing contact.

## Path Parameters

Either `id` or `email` must be provided.

<ParamField type="string">
  The Contact ID.
</ParamField>

<ParamField type="string">
  The Contact Email.
</ParamField>

## Body Parameters

<ResendParamField type="string">
  The first name of the contact.
</ResendParamField>

<ResendParamField type="string">
  The last name of the contact.
</ResendParamField>

<ParamField type="boolean">
  The Contact's global subscription status. If set to `true`, the contact will
  be unsubscribed from all Broadcasts.
</ParamField>

<ParamField type="object">
  A map of custom property keys and values to update.

  <Expandable title="custom properties">
    <ParamField type="string">
      The property key.
    </ParamField>

    <ParamField type="string">
      The property value.
    </ParamField>
  </Expandable>
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Update by contact id
  const { data, error } = await resend.contacts.update({
    id: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    unsubscribed: true,
  });

  // Update by contact email
  const { data, error } = await resend.contacts.update({
    email: 'acme@example.com',
    unsubscribed: true,
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Update by contact id
  $resend->contacts->update(
    id: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    parameters: [
      'unsubscribed' => true
    ]
  );

  // Update by contact email
  $resend->contacts->update(
    email: 'acme@example.com',
    parameters: [
      'unsubscribed' => true
    ]
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  # Update by contact id
  params: resend.Contacts.UpdateParams = {
    "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
    "unsubscribed": True,
  }

  resend.Contacts.update(params)

  # Update by contact email
  params: resend.Contacts.UpdateParams = {
    "email": "acme@example.com",
    "unsubscribed": True,
  }

  resend.Contacts.update(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  # Update by contact id
  params = {
    "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
    "unsubscribed": true,
  }

  Resend::Contacts.update(params)

  # Update by contact email
  params = {
    "email": "acme@example.com",
    "unsubscribed": true,
  }

  Resend::Contacts.update(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	// Update by contact id
  	params := &resend.UpdateContactRequest{
  		Id:           "e169aa45-1ecf-4183-9955-b1499d5701d3",
  		Unsubscribed: true,
  	}

  	client.Contacts.Update(params)

  	// Update by contact email
  	params = &resend.UpdateContactRequest{
  		Email:        "acme@example.com",
  		Unsubscribed: true,
  	}

  	client.Contacts.Update(params)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::ContactChanges, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let changes = ContactChanges::new().with_unsubscribed(true);

    // Update by contact id
    let _contact = resend
      .contacts
      .update("e169aa45-1ecf-4183-9955-b1499d5701d3", changes.clone())
      .await?;

    // Update by contact email
    let _contact = resend
      .contacts
      .update("acme@example.com", changes)
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          // Update by contact id
          UpdateContactOptions params = UpdateContactOptions.builder()
                  .id("e169aa45-1ecf-4183-9955-b1499d5701d3")
                  .unsubscribed(true)
                  .build();

          // Update by contact email
          UpdateContactOptions params = UpdateContactOptions.builder()
                  .email("acme@example.com")
                  .unsubscribed(true)
                  .build();

          UpdateContactResponseSuccess data = resend.contacts().update(params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  // By Id
  await resend.ContactUpdateAsync(
      contactId: new Guid( "e169aa45-1ecf-4183-9955-b1499d5701d3" ),
      new ContactData()
      {
          FirstName = "Stevie",
          LastName = "Wozniaks",
          IsUnsubscribed = true,
      }
  );

  // By Email
  await resend.ContactUpdateByEmailAsync(
      "acme@example.com",
      new ContactData()
      {
          FirstName = "Stevie",
          LastName = "Wozniaks",
          IsUnsubscribed = true,
      }
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Update by contact id
  curl -X PATCH 'https://api.resend.com/contacts/520784e2-887d-4c25-b53c-4ad46ad38100' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "unsubscribed": true
  }'

  # Update by contact email
  curl -X PATCH 'https://api.resend.com/contacts/acme@example.com' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "unsubscribed": true
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Update by contact id
  resend contacts update e169aa45-1ecf-4183-9955-b1499d5701d3 --unsubscribed

  # Update by contact email
  resend contacts update acme@example.com --unsubscribed
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "contact",
    "id": "479e3145-dd38-476b-932c-529ceb705947"
  }
  ```
</ResponseExample>


# Update Contact Topics
Source: https://resend.com/docs/api-reference/contacts/update-contact-topics

PATCH /contacts/:contact_id/topics
Update topic subscriptions for a contact.

## Path Parameters

Either `id` or `email` must be provided.

<ParamField type="string">
  The Contact ID.
</ParamField>

<ParamField type="string">
  The Contact Email.
</ParamField>

## Body Parameters

<ParamField type="array">
  Array of topic subscription updates.

  <Expandable title="properties">
    <ParamField type="string">
      The Topic ID.
    </ParamField>

    <ParamField type="string">
      The subscription action. Must be either `opt_in` or `opt_out`.
    </ParamField>
  </Expandable>
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Update by contact id
  const { data, error } = await resend.contacts.topics.update({
    id: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    topics: [
      {
        id: 'b6d24b8e-af0b-4c3c-be0c-359bbd97381e',
        subscription: 'opt_out',
      },
      {
        id: '07d84122-7224-4881-9c31-1c048e204602',
        subscription: 'opt_in',
      },
    ],
  });

  // Update by contact email
  const { data, error } = await resend.contacts.topics.update({
    email: 'steve.wozniak@gmail.com',
    topics: [
      {
        id: '07d84122-7224-4881-9c31-1c048e204602',
        subscription: 'opt_out',
      },
      {
        id: '07d84122-7224-4881-9c31-1c048e204602',
        subscription: 'opt_in',
      },
    ],
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Update by contact id
  $resend->contacts->topics->update('e169aa45-1ecf-4183-9955-b1499d5701d3', [
    [
      'id' => '07d84122-7224-4881-9c31-1c048e204602',
      'subscription' => 'opt_out',
    ],
    [
      'id' => '07d84122-7224-4881-9c31-1c048e204602',
      'subscription' => 'opt_in',
    ],
  ]);

  // Update by contact email
  $resend->contacts->topics->update('steve.wozniak@gmail.com', [
    [
      'id' => '07d84122-7224-4881-9c31-1c048e204602',
      'subscription' => 'opt_out',
    ],
    [
      'id' => '07d84122-7224-4881-9c31-1c048e204602',
      'subscription' => 'opt_in',
    ],
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  # Update by contact id
  params = {
      "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
      "topics": [
          {"id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e", "subscription": "opt_out"},
          {"id": "07d84122-7224-4881-9c31-1c048e204602", "subscription": "opt_in"},
      ],
  }

  response = resend.Contacts.Topics.update(params)

  # Update by contact email
  params_by_email = {
      "email": "steve.wozniak@gmail.com",
      "topics": [
          {"id": "07d84122-7224-4881-9c31-1c048e204602", "subscription": "opt_out"},
          {"id": "07d84122-7224-4881-9c31-1c048e204602", "subscription": "opt_in"},
      ],
  }

  response = resend.Contacts.Topics.update(params_by_email)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  # Update by contact id
  update_params = {
    id: "e169aa45-1ecf-4183-9955-b1499d5701d3",
    topics: [
      { id: "b6d24b8e-af0b-4c3c-be0c-359bbd97381e", subscription: "opt_out" },
      { id: "07d84122-7224-4881-9c31-1c048e204602", subscription: "opt_in" }
    ]
  }
  updated_topics = Resend::Contacts::Topics.update(update_params)

  # Update by contact email
  update_params = {
    email: "steve.wozniak@gmail.com",
    topics: [
      { id: "07d84122-7224-4881-9c31-1c048e204602", subscription: "opt_out" },
      { id: "07d84122-7224-4881-9c31-1c048e204602", subscription: "opt_in" }
    ]
  }
  updated_topics = Resend::Contacts::Topics.update(update_params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	// Update by contact id
  	params := &resend.UpdateContactTopicsRequest{
  		ContactId: "e169aa45-1ecf-4183-9955-b1499d5701d3",
  		Topics: []resend.TopicSubscriptionUpdate{
  			{
  				Id:           "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
  				Subscription: "opt_out",
  			},
  			{
  				Id:           "07d84122-7224-4881-9c31-1c048e204602",
  				Subscription: "opt_in",
  			},
  		},
  	}

  	updatedTopics, err := client.Contacts.Topics.UpdateWithContext(ctx, params)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(updatedTopics)

  	// Update by contact email
  	params = &resend.UpdateContactTopicsRequest{
  		Email: "steve.wozniak@gmail.com",
  		Topics: []resend.TopicSubscriptionUpdate{
  			{
  				Id:           "07d84122-7224-4881-9c31-1c048e204602",
  				Subscription: "opt_out",
  			},
  			{
  				Id:           "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
  				Subscription: "opt_in",
  			},
  		},
  	}

  	updatedTopics, err = client.Contacts.Topics.UpdateWithContext(ctx, params)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(updatedTopics)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{
    types::{SubscriptionType, UpdateContactTopicOptions},
    Resend, Result,
  };

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let topics = [
      UpdateContactTopicOptions::new(
        "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
        SubscriptionType::OptOut,
      ),
      UpdateContactTopicOptions::new(
        "07d84122-7224-4881-9c31-1c048e204602",
        SubscriptionType::OptIn,
      ),
    ];

    let _contact = resend
      .contacts
      .update_contact_topics("e169aa45-1ecf-4183-9955-b1499d5701d3", topics)
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      // Update by contact id
      UpdateContactTopicsOptions optionsById = UpdateContactTopicsOptions.builder()
                  .id("e169aa45-1ecf-4183-9955-b1499d5701d3")
                  .topics(ContactTopicOptions.builder()
                              .id("b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
                              .subscription("opt_out")
                              .build(),
                          ContactTopicOptions.builder()
                              .id("07d84122-7224-4881-9c31-1c048e204602")
                              .subscription("opt_in")
                              .build())
                  .build();

      resend.contacts().topics().update(optionsById);

      // Update by contact email
      UpdateContactTopicsOptions optionsByEmail = UpdateContactTopicsOptions.builder()
                  .email("steve.wozniak@gmail.com")
                  .topics(ContactTopicOptions.builder()
                              .id("07d84122-7224-4881-9c31-1c048e204602")
                              .subscription("opt_in")
                              .build(),
                          ContactTopicOptions.builder()
                              .id("b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
                              .subscription("opt_out")
                              .build())
                  .build();

      resend.contacts().topics().update(optionsById);
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var topics = new List<TopicSubscription>();

  topics.Add( new TopicSubscription() {
    Id = new Guid( "07d84122-7224-4881-9c31-1c048e204602" ),
    Subscription = SubscriptionType.OptIn,
  });

  topics.Add( new TopicSubscription() {
    Id = new Guid( "b6d24b8e-af0b-4c3c-be0c-359bbd97381e" ),
    Subscription = SubscriptionType.OptOut,
  });

  await resend.ContactUpdateTopicsAsync(
      new Guid( "e169aa45-1ecf-4183-9955-b1499d5701d3" ),
      topics );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  // Update by contact id
  curl -X PATCH 'https://api.resend.com/contacts/e169aa45-1ecf-4183-9955-b1499d5701d3/topics' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'[
        {
          "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
          "subscription": "opt_out"
        }
       ]'

  // Update by contact email
  curl -X PATCH 'https://api.resend.com/contacts/steve.wozniak@gmail.com/topics' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'[
        {
          "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
          "subscription": "opt_out"
        }
       ]'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Update by contact id
  resend contacts update-topics e169aa45-1ecf-4183-9955-b1499d5701d3 \
    --topics '[{"id":"b6d24b8e-af0b-4c3c-be0c-359bbd97381e","subscription":"opt_out"}]'

  # Update by contact email
  resend contacts update-topics steve.wozniak@gmail.com \
    --topics '[{"id":"b6d24b8e-af0b-4c3c-be0c-359bbd97381e","subscription":"opt_out"}]'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "contact_topics",
    "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e"
  }
  ```
</ResponseExample>


# Claim Domain
Source: https://resend.com/docs/api-reference/domains/claim-domain

POST /domains/claim
Claim a domain that is already verified by another team.

<Note>
  Use this endpoint when [creating a
  domain](/docs/api-reference/domains/create-domain) fails because the domain is
  already verified by another team. Resend creates a placeholder domain on your
  team and returns a `domain_claim` with a TXT record to add to your DNS. Learn
  more in [Claiming a domain](/docs/dashboard/domains/claim).
</Note>

## Body Parameters

<ParamField type="string">
  The name of the domain you want to claim.
</ParamField>

<ParamField type="string">
  The region where emails will be sent from. Possible values: `'us-east-1' |
      'eu-west-1' | 'sa-east-1' | 'ap-northeast-1'`
</ParamField>

<ResendParamField type="string">
  Choose a subdomain for the Return-Path address. Defaults to `send` (i.e.,
  `send.yourdomain.tld`). Avoid setting values that could undermine credibility
  (e.g. `testing`), as they may be exposed to recipients.
</ResendParamField>

<ResendParamField type="boolean">
  Track the open rate of each email.

  <Info>
    This setting is only applied if a `tracking_subdomain` is configured and verified.
  </Info>
</ResendParamField>

<ResendParamField type="boolean">
  Track clicks within the body of each HTML email.

  <Info>
    This setting is only applied if a `tracking_subdomain` is configured and verified.
  </Info>
</ResendParamField>

<ResendParamField type="string">
  Configure a custom subdomain for click and open tracking. For example, setting
  `"links"` on domain `example.com` will produce a CNAME record for
  `links.example.com`. Avoid setting values that have a negative connotation (e.g. `tracking`).

  Learn more about [custom tracking subdomains](/docs/dashboard/domains/tracking).
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.domains.claims.create({
    name: 'example.com',
  });
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Domains.Claims.CreateParams = {
    "name": "example.com",
  }

  resend.Domains.Claims.create(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = ENV["RESEND_API_KEY"]

  params = {
    name: "example.com",
  }
  claim = Resend::Domains::Claims.create(params)
  puts claim
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.CreateDomainClaimRequest{
  		Name: "example.com",
  	}

  	client.DomainClaims.Create(params)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result, types::CreateDomainClaimOptions};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let domain_claim = CreateDomainClaimOptions::new("example.com");
    let _data = resend.domains.claim(domain_claim).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          ClaimDomainOptions params = ClaimDomainOptions
                  .builder()
                  .name("example.com").build();

          DomainClaimResponseSuccess claim = resend.domains().claims().create(params);
      }
  }
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/domains/claim' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "name": "example.com"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend domains claim create --name example.com
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "domain_claim",
    "id": "dacf4072-4119-4d88-932f-6c6126d3a9d1",
    "name": "example.com",
    "status": "pending",
    "domain_id": "d91cd9bd-1176-453e-8fc1-35364d380206",
    "region": "us-east-1",
    "record": {
      "type": "TXT",
      "name": "example.com",
      "value": "resend-domain-verification=3f8a1c2d4e5b6a7f8091a2b3c4d5e6f7",
      "ttl": "Auto"
    },
    "blocked_reason": null,
    "failure_reason": null,
    "created_at": "2026-06-16 17:12:02.059593+00",
    "expires_at": "2026-06-23 17:12:02.059593+00"
  }
  ```
</ResponseExample>


# Create Domain
Source: https://resend.com/docs/api-reference/domains/create-domain

POST /domains
Create a domain through the Resend Email API.

## Body Parameters

<ParamField type="string">
  The name of the domain you want to create.
</ParamField>

<ParamField type="string">
  The region where emails will be sent from. Possible values: `'us-east-1' |
      'eu-west-1' | 'sa-east-1' | 'ap-northeast-1'`
</ParamField>

<ResendParamField type="string">
  For advanced use cases, choose a subdomain for the Return-Path address. The
  custom return path is used for SPF authentication, DMARC alignment, and
  handling bounced emails. Defaults to `send` (i.e., `send.yourdomain.tld`). Avoid
  setting values that could undermine credibility (e.g. `testing`), as they may
  be exposed to recipients.

  Learn more about [custom return paths](/docs/dashboard/domains/custom-return-path).
</ResendParamField>

<ResendParamField type="boolean">
  Track the open rate of each email.

  <Info>
    This setting is only applied if a `tracking_subdomain` is configured and verified.
  </Info>
</ResendParamField>

<ResendParamField type="boolean">
  Track clicks within the body of each HTML email.

  <Info>
    This setting is only applied if a `tracking_subdomain` is configured and verified.
  </Info>
</ResendParamField>

<ResendParamField type="string">
  Configure a custom subdomain for click and open tracking. For example, setting
  `"links"` on domain `example.com` will produce a CNAME record for
  `links.example.com`. Avoid setting values that have a negative connotation (e.g. `tracking`).

  Learn more about [custom tracking subdomains](/docs/dashboard/domains/tracking).
</ResendParamField>

<ParamField type="string">
  <ul>
    <li>
      `opportunistic`: Opportunistic TLS means that it always attempts to make a
      secure connection to the receiving mail server. If it can't establish a
      secure connection, it sends the message unencrypted.
    </li>

    <li>
      `enforced`: Enforced TLS on the other hand, requires that the email
      communication must use TLS no matter what. If the receiving server does
      not support TLS, the email will not be sent.
    </li>
  </ul>
</ParamField>

<ParamField type="object">
  Configure the domain capabilities for sending and receiving emails. At least one capability must be enabled.

  <Expandable title="properties">
    <ParamField type="string">
      Enable or disable sending emails from this domain. Possible values: `'enabled' | 'disabled'`
    </ParamField>

    <ParamField type="string">
      Enable or disable receiving emails to this domain. Possible values: `'enabled' | 'disabled'`
    </ParamField>
  </Expandable>
</ParamField>

<Info>
  See all available [domain `status`
  types](/docs/dashboard/domains/manage-domains#understand-a-domain-status).
</Info>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.domains.create({ name: 'example.com' });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->domains->create([
    'name' => 'example.com'
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Domains.CreateParams = {
    "name": "example.com",
  }

  resend.Domains.create(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = ENV["RESEND_API_KEY"]

  params = {
    name: "example.com",
  }
  domain = Resend::Domains.create(params)
  puts domain
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.CreateDomainRequest{
  		Name: "example.com",
  	}

  	client.Domains.Create(params)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::CreateDomainOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _domain = resend
      .domains
      .create(CreateDomainOptions::new("example.com"))
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateDomainOptions params = CreateDomainOptions
                  .builder()
                  .name("example.com").build();

          CreateDomainResponse domain = resend.domains().create(params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.DomainAddAsync( "example.com" );
  Console.WriteLine( "Domain Id={0}", resp.Content.Id );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/domains' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "name": "example.com"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend domains create --name example.com --region us-east-1
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "id": "4dd369bc-aa82-4ff3-97de-514ae3000ee0",
    "name": "example.com",
    "created_at": "2026-03-28 17:12:02.059593+00",
    "status": "not_started",
    "open_tracking": true,
    "click_tracking": false,
    "tracking_subdomain": "links",
    "capabilities": {
      "sending": "enabled",
      "receiving": "disabled"
    },
    "records": [
      {
        "record": "SPF",
        "name": "send",
        "type": "MX",
        "ttl": "Auto",
        "status": "not_started",
        "value": "feedback-smtp.us-east-1.amazonses.com",
        "priority": 10
      },
      {
        "record": "SPF",
        "name": "send",
        "value": "\"v=spf1 include:amazonses.com ~all\"",
        "type": "TXT",
        "ttl": "Auto",
        "status": "not_started"
      },
      {
        "record": "DKIM",
        "name": "nhapbbryle57yxg3fbjytyodgbt2kyyg._domainkey",
        "value": "nhapbbryle57yxg3fbjytyodgbt2kyyg.dkim.amazonses.com.",
        "type": "CNAME",
        "status": "not_started",
        "ttl": "Auto"
      },
      {
        "record": "DKIM",
        "name": "xbakwbe5fcscrhzshpap6kbxesf6pfgn._domainkey",
        "value": "xbakwbe5fcscrhzshpap6kbxesf6pfgn.dkim.amazonses.com.",
        "type": "CNAME",
        "status": "not_started",
        "ttl": "Auto"
      },
      {
        "record": "DKIM",
        "name": "txrcreso3dqbvcve45tqyosxwaegvhgn._domainkey",
        "value": "txrcreso3dqbvcve45tqyosxwaegvhgn.dkim.amazonses.com.",
        "type": "CNAME",
        "status": "not_started",
        "ttl": "Auto"
      },
      {
        "record": "Tracking",
        "name": "links.example.com",
        "type": "CNAME",
        "value": "links1.resend-dns.com",
        "ttl": "Auto",
        "status": "not_started"
      }
    ],
    "region": "us-east-1"
  }
  ```
</ResponseExample>


# Delete Domain
Source: https://resend.com/docs/api-reference/domains/delete-domain

DELETE /domains/:domain_id
Remove an existing domain.

<Warning>
  Removing a domain with a configured [custom tracking subdomain](/docs/dashboard/domains/tracking)
  will also remove the Resend provisioned proxy, breaking any existing email links that use that subdomain.

  To keep links working, set up your own proxy pointing to Resend’s tracking DNS records before removing the domain.
</Warning>

## Path Parameters

<ResendParamField type="string">
  The Domain ID.
</ResendParamField>

<RequestExample>
  ```js Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.domains.remove(
    'd91cd9bd-1176-453e-8fc1-35364d380206',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->domains->remove('d91cd9bd-1176-453e-8fc1-35364d380206');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Domains.remove(domain_id="d91cd9bd-1176-453e-8fc1-35364d380206")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = ENV["RESEND_API_KEY"]
  Resend::Domains.remove("d91cd9bd-1176-453e-8fc1-35364d380206")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Domains.Remove("d91cd9bd-1176-453e-8fc1-35364d380206")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _deleted = resend
      .domains
      .delete("d91cd9bd-1176-453e-8fc1-35364d380206")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          RemoveDomainResponse removed = resend.domains().remove("d91cd9bd-1176-453e-8fc1-35364d380206");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.DomainDeleteAsync( new Guid( "d91cd9bd-1176-453e-8fc1-35364d380206" ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X DELETE 'https://api.resend.com/domains/d91cd9bd-1176-453e-8fc1-35364d380206' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend domains delete d91cd9bd-1176-453e-8fc1-35364d380206
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "domain",
    "id": "d91cd9bd-1176-453e-8fc1-35364d380206",
    "deleted": true
  }
  ```
</ResponseExample>


# Retrieve Domain
Source: https://resend.com/docs/api-reference/domains/get-domain

GET /domains/:domain_id
Retrieve a single domain for the authenticated user.

## Path Parameters

<ResendParamField type="string">
  The Domain ID.
</ResendParamField>

<Info>
  See all available [domain `status`
  types](/docs/dashboard/domains/manage-domains#understand-a-domain-status).
</Info>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.domains.get(
    'd91cd9bd-1176-453e-8fc1-35364d380206',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->domains->get('d91cd9bd-1176-453e-8fc1-35364d380206');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Domains.get(domain_id="d91cd9bd-1176-453e-8fc1-35364d380206")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Domains.get "d91cd9bd-1176-453e-8fc1-35364d380206"
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Domains.Get("d91cd9bd-1176-453e-8fc1-35364d380206")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _domain = resend
      .domains
      .get("d91cd9bd-1176-453e-8fc1-35364d380206")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          Domain domain = resend.domains().get("d91cd9bd-1176-453e-8fc1-35364d380206");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.DomainRetrieveAsync( new Guid( "d91cd9bd-1176-453e-8fc1-35364d380206" ) );
  Console.WriteLine( "Domain Id={0}", resp.Content.Name );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/domains/d91cd9bd-1176-453e-8fc1-35364d380206' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend domains get d91cd9bd-1176-453e-8fc1-35364d380206
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "domain",
    "id": "d91cd9bd-1176-453e-8fc1-35364d380206",
    "name": "example.com",
    "status": "not_started",
    "created_at": "2026-04-26 20:21:26.347412+00",
    "region": "us-east-1",
    "open_tracking": true,
    "click_tracking": false,
    "tracking_subdomain": "links",
    "capabilities": {
      "sending": "enabled",
      "receiving": "disabled"
    },
    "records": [
      {
        "record": "SPF",
        "name": "send",
        "type": "MX",
        "ttl": "Auto",
        "status": "not_started",
        "value": "feedback-smtp.us-east-1.amazonses.com",
        "priority": 10
      },
      {
        "record": "SPF",
        "name": "send",
        "value": "\"v=spf1 include:amazonses.com ~all\"",
        "type": "TXT",
        "ttl": "Auto",
        "status": "not_started"
      },
      {
        "record": "DKIM",
        "name": "resend._domainkey",
        "value": "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsc4Lh8xilsngyKEgN2S84+21gn+x6SEXtjWvPiAAmnmggr5FWG42WnqczpzQ/mNblqHz4CDwUum6LtY6SdoOlDmrhvp5khA3cd661W9FlK3yp7+jVACQElS7d9O6jv8VsBbVg4COess3gyLE5RyxqF1vYsrEXqyM8TBz1n5AGkQIDAQA2",
        "type": "TXT",
        "status": "not_started",
        "ttl": "Auto"
      },
      {
        "record": "Tracking",
        "name": "links.example.com",
        "type": "CNAME",
        "value": "links1.resend-dns.com",
        "ttl": "Auto",
        "status": "not_started"
      }
    ]
  }
  ```
</ResponseExample>


# Get Domain Claim
Source: https://resend.com/docs/api-reference/domains/get-domain-claim

GET /domains/:domain_id/claim
Retrieve the latest claim for a domain.

<Note>
  Poll this endpoint to follow a claim's `status` after you [start a
  claim](/docs/api-reference/domains/claim-domain). The `domain_id` is the
  placeholder domain id returned in the `domain_claim` object.
</Note>

## Path Parameters

<ResendParamField type="string">
  The placeholder Domain ID returned when the claim was created.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.domains.claims.get(
    'd91cd9bd-1176-453e-8fc1-35364d380206',
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Domains.Claims.get(domain_id="d91cd9bd-1176-453e-8fc1-35364d380206")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = ENV["RESEND_API_KEY"]

  claim = Resend::Domains::Claims.get("d91cd9bd-1176-453e-8fc1-35364d380206")
  puts claim
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.DomainClaims.Get("d91cd9bd-1176-453e-8fc1-35364d380206")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _data = resend
      .domains
      .get_claim("d91cd9bd-1176-453e-8fc1-35364d380206")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          DomainClaimResponseSuccess claim = resend.domains().claims()
                  .get("d91cd9bd-1176-453e-8fc1-35364d380206");
      }
  }
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/domains/d91cd9bd-1176-453e-8fc1-35364d380206/claim' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend domains claim get d91cd9bd-1176-453e-8fc1-35364d380206
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "domain_claim",
    "id": "dacf4072-4119-4d88-932f-6c6126d3a9d1",
    "name": "example.com",
    "status": "pending",
    "domain_id": "d91cd9bd-1176-453e-8fc1-35364d380206",
    "region": "us-east-1",
    "record": {
      "type": "TXT",
      "name": "example.com",
      "value": "resend-domain-verification=3f8a1c2d4e5b6a7f8091a2b3c4d5e6f7",
      "ttl": "Auto"
    },
    "blocked_reason": null,
    "failure_reason": null,
    "created_at": "2026-06-16 17:12:02.059593+00",
    "expires_at": "2026-06-23 17:12:02.059593+00"
  }
  ```
</ResponseExample>


# List Domains
Source: https://resend.com/docs/api-reference/domains/list-domains

GET /domains
Retrieve a list of domains for the authenticated user.

<Info>
  See all available [domain `status`
  types](/docs/dashboard/domains/manage-domains#understand-a-domain-status).
</Info>

<QueryParams type="domains" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.domains.list();
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->domains->list();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"
  resend.Domains.list()
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = ENV["RESEND_API_KEY"]
  Resend::Domains.list
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Domains.List()
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result, list_opts::ListOptions};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _domains = resend.domains.list(ListOptions::default()).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          ListDomainsResponse response = resend.domains().list();
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.DomainListAsync();
  Console.WriteLine( "Nr Domains={0}", resp.Content.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/domains' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend domains list
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "d91cd9bd-1176-453e-8fc1-35364d380206",
        "name": "example.com",
        "status": "not_started",
        "created_at": "2026-04-26 20:21:26.347412+00",
        "region": "us-east-1",
        "open_tracking": true,
        "click_tracking": false,
        "capabilities": {
          "sending": "enabled",
          "receiving": "disabled"
        }
      }
    ]
  }
  ```
</ResponseExample>


# Update Domain
Source: https://resend.com/docs/api-reference/domains/update-domain

PATCH /domains/:domain_id
Update an existing domain.

## Path Parameters

<ResendParamField type="string">
  The Domain ID.
</ResendParamField>

## Body Parameters

<ResendParamField type="boolean">
  Track clicks within the body of each HTML email.

  <Info>
    This setting is only applied if a `tracking_subdomain` is configured and verified.
  </Info>
</ResendParamField>

<ResendParamField type="boolean">
  Track the open rate of each email.

  <Info>
    This setting is only applied if a `tracking_subdomain` is configured and verified.
  </Info>
</ResendParamField>

<ResendParamField type="string">
  Configure a custom subdomain for click and open tracking. For example, setting
  `"links"` on domain `example.com` will produce a CNAME record for
  `links.example.com`. Avoid setting values that have a negative connotation (e.g. `tracking`).

  This value can only be changed after it has been specified, never removed. This is to preserve any email links that
  may already be sent with the current tracking subdomain.

  After changing the tracking subdomain, a new DNS record must be verified, until then, the previous value is used.
  Do not remove old tracking DNS records, all previously used records remain active and are included in the response.

  Learn more about [custom tracking subdomains](/docs/dashboard/domains/tracking).
</ResendParamField>

<ParamField type="string">
  <ul>
    <li>
      `opportunistic`: Opportunistic TLS means that it always attempts to make a
      secure connection to the receiving mail server. If it can't establish a
      secure connection, it sends the message unencrypted.
    </li>

    <li>
      `enforced`: Enforced TLS on the other hand, requires that the email
      communication must use TLS no matter what. If the receiving server does
      not support TLS, the email will not be sent.
    </li>
  </ul>
</ParamField>

<ParamField type="object">
  Update the domain capabilities for sending and receiving emails. You can specify one or both fields. Omitted fields will keep their current value. At least one capability must remain enabled.

  <Expandable title="properties">
    <ParamField type="string">
      Enable or disable sending emails from this domain. Possible values: `'enabled' | 'disabled'`
    </ParamField>

    <ParamField type="string">
      Enable or disable receiving emails to this domain. Possible values: `'enabled' | 'disabled'`
    </ParamField>
  </Expandable>
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.domains.update({
    id: 'b8617ad3-b712-41d9-81a0-f7c3d879314e',
    openTracking: false,
    clickTracking: true,
    trackingSubdomain: 'links',
    tls: 'enforced',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->domains->update(
    'b8617ad3-b712-41d9-81a0-f7c3d879314e',
    [
      'open_tracking' => false,
      'click_tracking' => true,
      'tracking_subdomain' => 'links',
      'tls' => 'enforced',
    ]
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Domains.UpdateParams = {
    "id": "b8617ad3-b712-41d9-81a0-f7c3d879314e",
    "open_tracking": False,
    "click_tracking": True,
    "tracking_subdomain": "links",
    "tls": "enforced",
  }

  resend.Domains.update(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = "re_xxxxxxxxx"

  Resend::Domains.update({
    id: "b8617ad3-b712-41d9-81a0-f7c3d879314e",
    open_tracking: false,
    click_tracking: true,
    tracking_subdomain: "links",
    tls: "enforced",
  })
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	updateDomainParams := &resend.UpdateDomainRequest{
  		OpenTracking:      false,
  		ClickTracking:     true,
  		TrackingSubdomain: "links",
  		Tls:               resend.Enforced,
  	}

  	client.Domains.Update("b8617ad3-b712-41d9-81a0-f7c3d879314e", updateDomainParams)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::{DomainChanges, Tls}, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let changes = DomainChanges::new()
      .with_open_tracking(false)
      .with_click_tracking(true)
      .with_tracking_subdomain("links")
      .with_tls(Tls::Enforced);

    let _domain = resend
      .domains
      .update("b8617ad3-b712-41d9-81a0-f7c3d879314e", changes)
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend resend = new Resend("re_xxxxxxxxx");

  UpdateDomainOptions params = UpdateDomainOptions.builder()
                  .id("b8617ad3-b712-41d9-81a0-f7c3d879314e")
                  .openTracking(false)
                  .clickTracking(true)
                  .trackingSubdomain("links")
                  .tls(Tls.ENFORCED)
                  .build();

  resend.domains().update(params);
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.DomainUpdateAsync(
      new Guid( "b8617ad3-b712-41d9-81a0-f7c3d879314e" ),
      new DomainUpdateData()
      {
          TrackOpen = false,
          TrackClicks = true,
          TrackingSubdomain = "links",
          TlsMode = TlsMode.Enforced,
      }
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X PATCH 'https://api.resend.com/domains/b8617ad3-b712-41d9-81a0-f7c3d879314e' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "open_tracking": false,
    "click_tracking": true,
    "tracking_subdomain": "links",
    "tls": "enforced"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend domains update b8617ad3-b712-41d9-81a0-f7c3d879314e \
    --no-open-tracking \
    --click-tracking \
    --tracking-subdomain links \
    --tls enforced
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "domain",
    "id": "b8617ad3-b712-41d9-81a0-f7c3d879314e"
  }
  ```
</ResponseExample>


# Verify Domain
Source: https://resend.com/docs/api-reference/domains/verify-domain

POST /domains/:domain_id/verify
Verify an existing domain.

<Note>
  Calling this API endpoint triggers an **asynchronous domain verification
  process**. The domain will be temporarily marked as `pending` regardless of
  its current status while the verification is in progress. Since this request
  initiates the complete domain verification cycle, it will trigger
  `domain.updated` webhook events as the domain status changes during the
  verification process.
</Note>

<Note>
  **Claimed a domain?** A [domain claim](/docs/dashboard/domains/claim) transfers the
  domain into your account as a brand-new domain with its own DKIM keys, so the
  previous account's DNS records can't be reused. After the claim is
  `completed`, fetch the domain with [Get
  Domain](/docs/api-reference/domains/get-domain), update your DNS with the new DKIM
  record(s) it returns, then call this endpoint to verify it before sending or
  receiving email. See [DKIM
  records](/docs/dashboard/domains/manage-domains#what-are-dkim-records) for details.
</Note>

## Path Parameters

<ResendParamField type="string">
  The Domain ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.domains.verify(
    'd91cd9bd-1176-453e-8fc1-35364d380206',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->domains->verify('d91cd9bd-1176-453e-8fc1-35364d380206');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"
  resend.Domains.verify(domain_id="d91cd9bd-1176-453e-8fc1-35364d380206")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = ENV["RESEND_API_KEY"]
  Resend::Domains.verify("d91cd9bd-1176-453e-8fc1-35364d380206")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Domains.Verify("d91cd9bd-1176-453e-8fc1-35364d380206")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    resend
      .domains
      .verify("d91cd9bd-1176-453e-8fc1-35364d380206")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          VerifyDomainResponse verified = resend.domains().verify("d91cd9bd-1176-453e-8fc1-35364d380206");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.DomainVerifyAsync( new Guid( "d91cd9bd-1176-453e-8fc1-35364d380206" ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/domains/d91cd9bd-1176-453e-8fc1-35364d380206/verify' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend domains verify d91cd9bd-1176-453e-8fc1-35364d380206
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "domain",
    "id": "d91cd9bd-1176-453e-8fc1-35364d380206"
  }
  ```
</ResponseExample>


# Verify Domain Claim
Source: https://resend.com/docs/api-reference/domains/verify-domain-claim

POST /domains/:domain_id/claim/verify
Trigger DNS verification for a domain claim.

<Note>
  Calling this endpoint starts an **asynchronous verification process**. Resend
  checks the claim's TXT record and runs ownership-safety checks before
  transferring the domain to your team. Add the TXT record returned by [Claim
  Domain](/docs/api-reference/domains/claim-domain) before calling this, then poll
  [Get Domain Claim](/docs/api-reference/domains/get-domain-claim) to follow the
  `status`.
</Note>

<Note>
  **After the claim completes:** the domain is transferred to your account as a
  brand-new domain with its own DKIM keys, so the previous account's DNS records
  can't be reused. Fetch it with [Get
  Domain](/docs/api-reference/domains/get-domain), update your DNS with the new DKIM
  record(s), then run [Verify Domain](/docs/api-reference/domains/verify-domain) to
  finish setup before sending or receiving email. See [DKIM
  records](/docs/dashboard/domains/manage-domains#what-are-dkim-records) for details.
</Note>

## Path Parameters

<ResendParamField type="string">
  The placeholder Domain ID returned when the claim was created.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.domains.claims.verify(
    'd91cd9bd-1176-453e-8fc1-35364d380206',
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Domains.Claims.verify(domain_id="d91cd9bd-1176-453e-8fc1-35364d380206")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = ENV["RESEND_API_KEY"]

  claim = Resend::Domains::Claims.verify("d91cd9bd-1176-453e-8fc1-35364d380206")
  puts claim
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.DomainClaims.Verify("d91cd9bd-1176-453e-8fc1-35364d380206")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _data = resend
      .domains
      .verify_claim("d91cd9bd-1176-453e-8fc1-35364d380206")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          DomainClaimResponseSuccess claim = resend.domains().claims()
                  .verify("d91cd9bd-1176-453e-8fc1-35364d380206");
      }
  }
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/domains/d91cd9bd-1176-453e-8fc1-35364d380206/claim/verify' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend domains claim verify d91cd9bd-1176-453e-8fc1-35364d380206
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "domain_claim",
    "id": "dacf4072-4119-4d88-932f-6c6126d3a9d1",
    "name": "example.com",
    "status": "pending",
    "domain_id": "d91cd9bd-1176-453e-8fc1-35364d380206",
    "region": "us-east-1",
    "record": {
      "type": "TXT",
      "name": "example.com",
      "value": "resend-domain-verification=3f8a1c2d4e5b6a7f8091a2b3c4d5e6f7",
      "ttl": "Auto"
    },
    "blocked_reason": null,
    "failure_reason": null,
    "created_at": "2026-06-16 17:12:02.059593+00",
    "expires_at": "2026-06-23 17:12:02.059593+00"
  }
  ```
</ResponseExample>


# Cancel Email
Source: https://resend.com/docs/api-reference/emails/cancel-email

POST /emails/:email_id/cancel
Cancel a scheduled email.

## Path Parameters

<ParamField type="string">
  The Email ID.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.emails.cancel(
    '49a3999c-0ce1-4ea6-ab68-afcd6dc2e794',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->cancel('49a3999c-0ce1-4ea6-ab68-afcd6dc2e794');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"
  resend.Emails.cancel(email_id="49a3999c-0ce1-4ea6-ab68-afcd6dc2e794")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Emails.cancel("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	canceled, err := client.Emails.Cancel("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794")
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(canceled.Id)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _canceled = resend
      .emails
      .cancel("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CancelEmailResponse canceled = resend
            .emails()
            .cancel("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.EmailCancelAsync( new Guid( "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794" ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails/49a3999c-0ce1-4ea6-ab68-afcd6dc2e794/cancel' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails cancel 49a3999c-0ce1-4ea6-ab68-afcd6dc2e794
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "email",
    "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794"
  }
  ```
</ResponseExample>


# Retrieve Metrics
Source: https://resend.com/docs/api-reference/emails/get-metrics

GET /emails/metrics
Retrieve account-level email metrics.

<Warning>
  Email metrics are currently in private beta and only available to a
  limited number of users. APIs might change before it is generally available.
  [Get in touch](https://resend.com/contact) if you're interested in testing
  this feature.

  <span />

  Once you have access, upgrade your Resend SDK to use the methods on this
  page:

  <CodeGroup>
    ```bash Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
    npm install resend@6.19.0-preview-headless-dashboard.7
    ```
  </CodeGroup>
</Warning>

<Note>
  Metrics are retained according to your plan's data retention window.
  Requesting a `start_date` older than your retention window returns data
  clamped to the oldest date your plan retains.
</Note>

<Note>
  Responses are cached for up to 15 minutes, so a request for the same range may
  return slightly stale data within that window.
</Note>

## Query Parameters

<ParamField type="string">
  The start of the date range, as an ISO 8601 date (`2026-07-01`) or datetime
  (`2026-07-01T00:00:00Z`). Must be on or before `end_date`. Defaults to 6 days
  before `end_date`.
</ParamField>

<ParamField type="string">
  The end of the date range, as an ISO 8601 date or datetime. Values in the
  future are clamped to the current time. Defaults to now.
</ParamField>

<ParamField type="string">
  The IANA timezone (e.g. `America/New_York`) used to bucket periods when
  `period` is in `dimensions`.
</ParamField>

<ParamField type="hourly | daily | weekly | monthly">
  The bucket size used when `period` is in `dimensions`. Accepted but has no
  effect otherwise. The date range can't produce more than 10,000 periods at the
  chosen granularity. This limit only applies when `period` is in `dimensions`.
</ParamField>

<ParamField type="string[]">
  Comma-separated list of metrics to include in the response. Defaults to all
  of the following:

  `received`, `delivered`, `complained`, `suppressed`, `bounced`,
  `bounced_transient`, `bounced_permanent`, `bounced_undetermined`, `opened`,
  `clicked`, `unsubscribed`, `delivery_delayed`, `failed`, `sent`,
  `unique_opened`, `unique_clicked`, `delivery_rate`, `open_rate`, `click_rate`,
  `bounce_rate`, `complaint_rate`, `unsubscribe_rate`
</ParamField>

<ParamField type="string[]">
  Comma-separated list of dimensions to break the response down by. Combine
  `period` with `domain` or `email` for a joint breakdown (one row per unique
  `period` + `domain`/`email` pair). Defaults to `[]`, returning a single
  `totals` row for the whole range, with no `data`.

  Possible values:

  * `period`: one row per `granularity` period, in chronological order.
  * `domain`: one row per sending domain. Cannot be combined with `email`.
  * `email`: one row per email. Cannot be combined with `domain`.
</ParamField>

<ParamField type="string[]">
  Comma-separated list of sending domain IDs to restrict the response to.
  Unrecognized query params are ignored rather than rejected.
</ParamField>

<ParamField type="string[]">
  Comma-separated list of email IDs to restrict the response to. Cannot be
  combined with the `domain` dimension. Unrecognized query params are ignored
  rather than rejected.
</ParamField>

<RequestExample>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/emails/metrics?start_date=2026-07-01&end_date=2026-07-08&metrics=sent,delivered,open_rate&dimensions=period,domain' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "metrics",
    "start_date": "2026-07-01T00:00:00.000Z",
    "end_date": "2026-07-08T00:00:00.000Z",
    "metrics": ["sent", "delivered", "open_rate"],
    "dimensions": ["period", "domain"],
    "granularity": "daily",
    "totals": {
      "sent": 1204,
      "delivered": 1180,
      "open_rate": 50.0
    },
    "data": [
      {
        "period": "2026-07-01",
        "domain_id": "d91cd9bd-1176-4f47-2a4b-fce2d5399cbf",
        "domain_name": "example.com",
        "sent": 172,
        "delivered": 169,
        "open_rate": 49.7
      }
    ]
  }
  ```
</ResponseExample>


# List Attachments
Source: https://resend.com/docs/api-reference/emails/list-email-attachments

GET /emails/:email_id/attachments
Retrieve a list of attachments from a sent email.

<QueryParams type="attachments" />

## Path Parameters

<ParamField type="string">
  The Email ID.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.emails.attachments.list({
    emailId: '4ef9a417-02e9-4d39-ad75-9611e0fcc33c',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->attachments->list(
    emailId: '4ef9a417-02e9-4d39-ad75-9611e0fcc33c'
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  attachments = resend.Emails.Attachments.list(
    email_id='4ef9a417-02e9-4d39-ad75-9611e0fcc33c'
  )
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require 'resend'

  Resend.api_key = 're_xxxxxxxxx'

  Resend::Emails::Attachments.list(
    email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c"
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Emails.ListAttachmentsWithContext(
  		context.TODO(),
  		"4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
  	)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{list_opts::ListOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _email = resend
      .emails
      .list_attachments(
        "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
        ListOptions::default(),
      )
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      ListAttachmentsResponse response = resend.emails().listAttachments(
        "4ef9a417-02e9-4d39-ad75-9611e0fcc33c"
      );
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.EmailAttachmentListAsync( new Guid( "4ef9a417-02e9-4d39-ad75-9611e0fcc33c" ));
  Console.WriteLine( "Nr Attachments={0}", resp.Content.Data.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/emails/4ef9a417-02e9-4d39-ad75-9611e0fcc33c/attachments' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails attachments 4ef9a417-02e9-4d39-ad75-9611e0fcc33c
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "2a0c9ce0-3112-4728-976e-47ddcd16a318",
        "filename": "avatar.png",
        "size": 4096,
        "content_type": "image/png",
        "content_disposition": "inline",
        "content_id": "img001",
        "download_url": "https://outbound-cdn.resend.com/4ef9a417-02e9-4d39-ad75-9611e0fcc33c/attachments/2a0c9ce0-3112-4728-976e-47ddcd16a318?some-params=example&signature=sig-123",
        "expires_at": "2026-10-17T14:29:41.521Z"
      }
    ]
  }
  ```
</ResponseExample>


# List Sent Emails
Source: https://resend.com/docs/api-reference/emails/list-emails

GET /emails
Retrieve a list of emails sent by your team.

You can list all emails sent by your team. The list returns references to individual emails. If needed, you can use the `id` of an email to retrieve the email HTML to plain text using the [Retrieve Email](/docs/api-reference/emails/retrieve-email) endpoint or the [Retrieve Attachments](/docs/api-reference/emails/list-email-attachments) endpoint to get an email's attachments.

<Info>
  This endpoint only returns emails sent by your team. If you need to list
  emails received by your domain, use the [List Received
  Emails](/docs/api-reference/emails/list-received-emails) endpoint.
</Info>

<QueryParams type="emails" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.emails.list();
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->list();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"
  resend.Emails.list()
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = "re_xxxxxxxxx"
  emails = Resend::Emails.list
  puts emails
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	paginatedResp, err := client.Emails.ListWithOptions(ctx, nil)
  	if err != nil {
  		panic(err)
  	}

  	if paginatedResp.HasMore {
  		opts := &resend.ListOptions{
  			After: &paginatedResp.Data[len(paginatedResp.Data)-1].ID,
  		}
  		client.Emails.ListWithOptions(ctx, opts)
  	}
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{list_opts::ListOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _emails = resend.emails.list(ListOptions::default()).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          ListEmailsResponseSuccess emails = resend.emails().list();
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.EmailListAsync();
  Console.WriteLine( "Count={0}", resp.Content.Data.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails list
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
        "message_id": "<111-222-333@email.example.com>",
        "to": ["delivered@resend.dev"],
        "from": "Acme <onboarding@resend.dev>",
        "created_at": "2026-04-03 22:13:42.674981+00",
        "subject": "Hello World",
        "bcc": null,
        "cc": null,
        "reply_to": null,
        "last_event": "delivered",
        "scheduled_at": null
      },
      {
        "id": "3a9f8c2b-1e5d-4f8a-9c7b-2d6e5f8a9c7b",
        "message_id": "<444-555-666@email.example.com>",
        "to": ["user@example.com"],
        "from": "Acme <onboarding@resend.dev>",
        "created_at": "2026-04-03 21:45:12.345678+00",
        "subject": "Welcome to Acme",
        "bcc": null,
        "cc": null,
        "reply_to": null,
        "last_event": "opened",
        "scheduled_at": null
      }
    ]
  }
  ```
</ResponseExample>


# List Attachments
Source: https://resend.com/docs/api-reference/emails/list-received-email-attachments

GET /emails/receiving/:email_id/attachments
Retrieve a list of attachments from a received email.

<QueryParams type="attachments" />

## Path Parameters

<ParamField type="string">
  The Email ID.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.emails.receiving.attachments.list({
    emailId: '4ef9a417-02e9-4d39-ad75-9611e0fcc33c',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->receiving->attachments->list(
    emailId: '4ef9a417-02e9-4d39-ad75-9611e0fcc33c'
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  attachments = resend.Emails.Receiving.Attachments.list(
    email_id='4ef9a417-02e9-4d39-ad75-9611e0fcc33c'
  )
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require 'resend'

  Resend.api_key = 're_xxxxxxxxx'

  attachments = Resend::Emails::Receiving::Attachments.list(
    email_id: '4ef9a417-02e9-4d39-ad75-9611e0fcc33c'
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Emails.Receiving.ListAttachmentsWithContext(
  		context.TODO(),
  		"4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
  	)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{list_opts::ListOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _email = resend
      .receiving
      .list_attachments(
        "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
        ListOptions::default(),
      )
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      ListAttachmentsResponse response = resend.receiving().listAttachments(
        "4ef9a417-02e9-4d39-ad75-9611e0fcc33c"
      );
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ReceivedEmailAttachmentListAsync( new Guid( "4ef9a417-02e9-4d39-ad75-9611e0fcc33c" ));
  Console.WriteLine( "Nr Attachments={0}", resp.Content.Data.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/emails/receiving/4ef9a417-02e9-4d39-ad75-9611e0fcc33c/attachments' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails receiving attachments 4ef9a417-02e9-4d39-ad75-9611e0fcc33c
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "2a0c9ce0-3112-4728-976e-47ddcd16a318",
        "filename": "avatar.png",
        "size": 4096,
        "content_type": "image/png",
        "content_disposition": "inline",
        "content_id": "img001",
        "download_url": "https://inbound-cdn.resend.com/4ef9a417-02e9-4d39-ad75-9611e0fcc33c/attachments/2a0c9ce0-3112-4728-976e-47ddcd16a318?some-params=example&signature=sig-123",
        "expires_at": "2026-10-17T14:29:41.521Z"
      }
    ]
  }
  ```
</ResponseExample>


# List Received Emails
Source: https://resend.com/docs/api-reference/emails/list-received-emails

GET /emails/receiving
Retrieve a list of received emails for the authenticated user.

You can list all emails received by your team. The list returns references to individual emails. If needed, you can use the `id` of an email to retrieve the email HTML to plain text using the [Retrieve Received Email](/docs/api-reference/emails/retrieve-received-email) endpoint or the [Retrieve Received Attachment](/docs/api-reference/emails/retrieve-received-email-attachment) endpoint to get an email's attachments.

<Info>
  This endpoint only returns emails received by your team. If you need to list
  emails sent by your team, use the [List Sent
  Emails](/docs/api-reference/emails/list-emails) endpoint.
</Info>

<QueryParams type="emails" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.emails.receiving.list();
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->receiving->list();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Emails.Receiving.list()
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Emails::Receiving.list()
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Emails.Receiving.ListWithContext(context.TODO())
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{list_opts::ListOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _email = resend.receiving.list(ListOptions::default()).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      ListReceivedEmailsResponse response = resend.receiving().list();
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ReceivedEmailListAsync();
  Console.WriteLine( "Nr Received={0}", resp.Content.Data.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/emails/receiving' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails receiving list
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": true,
    "data": [
      {
        "id": "a39999a6-88e3-48b1-888b-beaabcde1b33",
        "to": ["recipient@example.com"],
        "from": "sender@example.com",
        "created_at": "2026-10-09T14:37:40.951Z",
        "subject": "Hello World",
        "bcc": [],
        "cc": [],
        "reply_to": [],
        "message_id": "<111-222-333@email.example.com>",
        "attachments": [
          {
            "filename": "example.txt",
            "content_type": "text/plain",
            "content_id": null,
            "content_disposition": "attachment",
            "id": "47e999c7-c89c-4999-bf32-aaaaa1c3ff21",
            "size": 13
          }
        ]
      }
    ]
  }
  ```
</ResponseExample>


# Retrieve Sent Email
Source: https://resend.com/docs/api-reference/emails/retrieve-email

GET /emails/:email_id
Retrieve a single sent email.

## Path Parameters

<ParamField type="string">
  The Email ID.
</ParamField>

<Info>
  See all available `last_event` types in [the Email Events
  overview](/docs/dashboard/emails/manage-emails#understand-email-events).
</Info>

<RequestExample>
  ```js Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.emails.get(
    '37e4414c-5e25-4dbc-a071-43552a4bd53b',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->get('37e4414c-5e25-4dbc-a071-43552a4bd53b');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"
  resend.Emails.get(email_id="4ef9a417-02e9-4d39-ad75-9611e0fcc33c")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = "re_xxxxxxxxx"
  email = Resend::Emails.get("4ef9a417-02e9-4d39-ad75-9611e0fcc33c")
  puts email
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Emails.Get("4ef9a417-02e9-4d39-ad75-9611e0fcc33c")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _email = resend
      .emails
      .get("4ef9a417-02e9-4d39-ad75-9611e0fcc33c")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          Email email = resend.emails().get("4ef9a417-02e9-4d39-ad75-9611e0fcc33c");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.EmailRetrieveAsync( new Guid( "4ef9a417-02e9-4d39-ad75-9611e0fcc33c" ) );
  Console.WriteLine( "Subject={0}", resp.Content.Subject );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/emails/4ef9a417-02e9-4d39-ad75-9611e0fcc33c' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails get 4ef9a417-02e9-4d39-ad75-9611e0fcc33c
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "email",
    "id": "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
    "message_id": "<111-222-333@email.example.com>",
    "to": ["delivered@resend.dev"],
    "from": "Acme <onboarding@resend.dev>",
    "created_at": "2026-04-03 22:13:42.674981+00",
    "subject": "Hello World",
    "html": "Congrats on sending your <strong>first email</strong>!",
    "text": null,
    "bcc": [],
    "cc": [],
    "reply_to": [],
    "last_event": "delivered",
    "scheduled_at": null,
    "tags": [
      {
        "name": "category",
        "value": "confirm_email"
      }
    ]
  }
  ```
</ResponseExample>


# Retrieve Attachment
Source: https://resend.com/docs/api-reference/emails/retrieve-email-attachment

GET /emails/:email_id/attachments/:attachment_id
Retrieve a single attachment from a sent email.

## Path Parameters

<ParamField type="string">
  The Attachment ID.
</ParamField>

<ParamField type="string">
  The Email ID.
</ParamField>

<RequestExample>
  ```js Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.emails.attachments.get({
    id: '2a0c9ce0-3112-4728-976e-47ddcd16a318',
    emailId: '4ef9a417-02e9-4d39-ad75-9611e0fcc33c',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->attachments->get(
    id: '2a0c9ce0-3112-4728-976e-47ddcd16a318',
    emailId: '4ef9a417-02e9-4d39-ad75-9611e0fcc33c'
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  attachment = resend.Emails.Attachments.get(
    email_id='4ef9a417-02e9-4d39-ad75-9611e0fcc33c',
    attachment_id='2a0c9ce0-3112-4728-976e-47ddcd16a318'
  )
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require 'resend'

  Resend.api_key = 're_xxxxxxxxx'

  Resend::Emails::Attachments.get(
    id: "2a0c9ce0-3112-4728-976e-47ddcd16a318",
    email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c"
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Emails.GetAttachmentWithContext(
  		context.TODO(),
  		"4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
  		"2a0c9ce0-3112-4728-976e-47ddcd16a318",
  	)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _email = resend
      .emails
      .get_attachment(
        "2a0c9ce0-3112-4728-976e-47ddcd16a318",
        "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
      )
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      AttachmentResponse attachment = resend.emails().getAttachment(
        "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
        "2a0c9ce0-3112-4728-976e-47ddcd16a318"
      );
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.EmailAttachmentRetrieveAsync(
    emailId: new Guid( "4ef9a417-02e9-4d39-ad75-9611e0fcc33c" ),
    attachmentId: new Guid( "2a0c9ce0-3112-4728-976e-47ddcd16a318" )
  );
  Console.WriteLine( "URL={0}", resp.Content.DownloadUrl );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/emails/4ef9a417-02e9-4d39-ad75-9611e0fcc33c/attachments/2a0c9ce0-3112-4728-976e-47ddcd16a318' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails attachment 4ef9a417-02e9-4d39-ad75-9611e0fcc33c 2a0c9ce0-3112-4728-976e-47ddcd16a318
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "attachment",
    "id": "2a0c9ce0-3112-4728-976e-47ddcd16a318",
    "filename": "avatar.png",
    "size": 4096,
    "content_type": "image/png",
    "content_disposition": "inline",
    "content_id": "img001",
    "download_url": "https://outbound-cdn.resend.com/4ef9a417-02e9-4d39-ad75-9611e0fcc33c/attachments/2a0c9ce0-3112-4728-976e-47ddcd16a318?some-params=example&signature=sig-123",
    "expires_at": "2026-10-17T14:29:41.521Z"
  }
  ```
</ResponseExample>


# Retrieve Received Email
Source: https://resend.com/docs/api-reference/emails/retrieve-received-email

GET /emails/receiving/:email_id
Retrieve a single received email.

## Path Parameters

<ParamField type="string">
  The ID for the received email.
</ParamField>

## Query Parameters

<ParamField type="'data_uri' | 'cid'">
  Controls how inline images are returned inside `html`. The response echoes
  the form actually served as `html_format` on the body.

  By default (or when set to `data_uri`), inline images appear in `html` as base64 `data:` URIs. Set `html_format=cid` to keep the original `<img src="cid:..." />` references instead. Each `cid:` matches the `content_id` of an attachment, so you can correlate inline images with entries in the `attachments` array and fetch them via the attachment download endpoint.
</ParamField>

<ParamField type="array">
  The recipient addresses the email was forwarded for, taken from the `for`
  clause of the message's `Received` headers.
</ParamField>

<ParamField type="object | null">
  Raw email content download information. Contains a signed URL to download the original email file including all attachments.

  <Expandable title="properties">
    <ParamField type="string">
      Signed CloudFront URL to download the raw email file.
    </ParamField>

    <ParamField type="string">
      ISO 8601 timestamp indicating when the download URL expires.
    </ParamField>
  </Expandable>
</ParamField>

<RequestExample>
  ```js Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.emails.receiving.get(
    '37e4414c-5e25-4dbc-a071-43552a4bd53b',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->receiving->get('37e4414c-5e25-4dbc-a071-43552a4bd53b');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Emails.Receiving.get(email_id="37e4414c-5e25-4dbc-a071-43552a4bd53b")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Emails::Receiving.get("37e4414c-5e25-4dbc-a071-43552a4bd53b")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Emails.Receiving.GetWithContext(
  		context.TODO(),
  		"37e4414c-5e25-4dbc-a071-43552a4bd53b",
  	)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _email = resend
      .receiving
      .get("37e4414c-5e25-4dbc-a071-43552a4bd53b")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      ReceivedEmail email = resend.receiving().get("37e4414c-5e25-4dbc-a071-43552a4bd53b");
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ReceivedEmailRetrieveAsync( new Guid( "4ef9a417-02e9-4d39-ad75-9611e0fcc33c" ) );
  Console.WriteLine( "Subject={0}", resp.Content.Subject );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/emails/receiving/4ef9a417-02e9-4d39-ad75-9611e0fcc33c' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails receiving get 4ef9a417-02e9-4d39-ad75-9611e0fcc33c
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "email",
    "id": "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
    "to": ["delivered@resend.dev"],
    "from": "onboarding@resend.dev",
    "created_at": "2026-04-03T22:13:42.674Z",
    "subject": "Hello World",
    "html": "Congrats on sending your <strong>first email</strong>!",
    "html_format": "data_uri",
    "text": null,
    "headers": {
      "from": "Acme <onboarding@resend.dev>",
      "return-path": "lucas.costa@resend.com",
      "mime-version": "1.0"
    },
    "bcc": [],
    "cc": [],
    "reply_to": [],
    "received_for": ["forwarded@example.com"],
    "message_id": "<111-222-333@email.example.com>",
    "raw": {
      "download_url": "https://example.resend.com/receiving/raw/054da427-439a-4e91-b785-e4fb1966285f?Signature=...",
      "expires_at": "2026-04-03T23:13:42.674Z"
    },
    "attachments": [
      {
        "id": "2a0c9ce0-3112-4728-976e-47ddcd16a318",
        "filename": "avatar.png",
        "content_type": "image/png",
        "content_disposition": "inline",
        "content_id": "img001",
        "size": 4096
      },
      {
        "id": "3b1d0df1-4223-5839-087f-54eedd27b419",
        "filename": "document.pdf",
        "content_type": "application/pdf",
        "content_disposition": null,
        "content_id": null,
        "size": 13264
      }
    ]
  }
  ```
</ResponseExample>


# Retrieve Attachment
Source: https://resend.com/docs/api-reference/emails/retrieve-received-email-attachment

GET /emails/receiving/:email_id/attachments/:attachment_id
Retrieve a single attachment from a received email.

## Path Parameters

<ParamField type="string">
  The Attachment ID.
</ParamField>

<ParamField type="string">
  The Email ID.
</ParamField>

<RequestExample>
  ```js Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.emails.receiving.attachments.get({
    id: '2a0c9ce0-3112-4728-976e-47ddcd16a318',
    emailId: '4ef9a417-02e9-4d39-ad75-9611e0fcc33c',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->receiving->attachments->get(
    id: '2a0c9ce0-3112-4728-976e-47ddcd16a318',
    emailId: '4ef9a417-02e9-4d39-ad75-9611e0fcc33c'
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  attachment = resend.Emails.Receiving.Attachments.get(
    email_id='4ef9a417-02e9-4d39-ad75-9611e0fcc33c',
    attachment_id='2a0c9ce0-3112-4728-976e-47ddcd16a318'
  )
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require 'resend'

  Resend.api_key = 're_xxxxxxxxx'

  attachment = Resend::Emails::Receiving::Attachments.get(
    id: '2a0c9ce0-3112-4728-976e-47ddcd16a318',
    email_id: '4ef9a417-02e9-4d39-ad75-9611e0fcc33c'
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Emails.Receiving.GetAttachmentWithContext(
  		context.TODO(),
  		"4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
  		"2a0c9ce0-3112-4728-976e-47ddcd16a318",
  	)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _email = resend
      .receiving
      .get_attachment(
        "2a0c9ce0-3112-4728-976e-47ddcd16a318",
        "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
      )
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      AttachmentDetails attachment = resend.receiving().getAttachment(
        "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
        "2a0c9ce0-3112-4728-976e-47ddcd16a318"
      );
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ReceivedEmailAttachmentRetrieveAsync(
    emailId: new Guid( "4ef9a417-02e9-4d39-ad75-9611e0fcc33c" ),
    attachmentId: new Guid( "2a0c9ce0-3112-4728-976e-47ddcd16a318" )
  );
  Console.WriteLine( "URL={0}", resp.Content.DownloadUrl );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/emails/receiving/4ef9a417-02e9-4d39-ad75-9611e0fcc33c/attachments/2a0c9ce0-3112-4728-976e-47ddcd16a318' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails receiving attachment 4ef9a417-02e9-4d39-ad75-9611e0fcc33c 2a0c9ce0-3112-4728-976e-47ddcd16a318
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "attachment",
    "id": "2a0c9ce0-3112-4728-976e-47ddcd16a318",
    "filename": "avatar.png",
    "size": 4096,
    "content_type": "image/png",
    "content_disposition": "inline",
    "content_id": "img001",
    "download_url": "https://inbound-cdn.resend.com/4ef9a417-02e9-4d39-ad75-9611e0fcc33c/attachments/2a0c9ce0-3112-4728-976e-47ddcd16a318?some-params=example&signature=sig-123",
    "expires_at": "2026-10-17T14:29:41.521Z"
  }
  ```
</ResponseExample>


# Send Batch Emails
Source: https://resend.com/docs/api-reference/emails/send-batch-emails

POST /emails/batch
Trigger up to 100 batch emails at once.

Instead of sending one email per HTTP request, Resend provides a batching endpoint that permits you to send up to 100 emails in a single API call.

## Body Parameters

<ParamField type="string">
  Sender email address.

  To include a friendly name, pass the sender as `Name <email@example.com>`, for example `Acme <onboarding@example.dev>`.
</ParamField>

<ParamField type="string | string[]">
  Recipient email address. For multiple addresses, send as an array of strings.
  Max 50.
</ParamField>

<ParamField type="string">
  Email subject.
</ParamField>

<ParamField type="string | string[]">
  Bcc recipient email address. For multiple addresses, send as an array of
  strings.
</ParamField>

<ParamField type="string | string[]">
  Cc recipient email address. For multiple addresses, send as an array of
  strings.
</ParamField>

<ResendParamField type="string">
  Schedule email to be sent later. The date should be in natural language (e.g.: `in 1 min`) or ISO 8601 format (e.g:
  `2026-08-05T11:52:01.858Z`).

  [See examples](/docs/dashboard/emails/schedule-email)
</ResendParamField>

<ResendParamField type="string | string[]">
  Reply-to email address. For multiple addresses, send as an array of strings.
</ResendParamField>

<ParamField type="string">
  The HTML version of the message.
</ParamField>

<ParamField type="string">
  The plain text version of the message.

  <Info>
    If not provided, the HTML will be used to generate a plain text version. You
    can opt out of this behavior by setting value to an empty string.
  </Info>
</ParamField>

<ParamField type="React.ReactNode">
  The React component used to write the message. *Only available in the Node.js
  SDK.*
</ParamField>

<ParamField type="object">
  Custom headers to add to the email.
</ParamField>

<ResendParamField type="string">
  The topic ID to receive the email.

  * If the recipient is a contact and has opted-in to the topic, the email is sent.
  * If the recipient is a contact and has opted-out of the topic, the email is not sent and will be marked as failed.
  * If the recipient is not a contact, the email is sent if the topic default subscription value is set to `opt-in`.

  <Note>Each email address (to, cc, bcc) is checked and handled separately.</Note>
</ResendParamField>

<ParamField type="array">
  Custom data passed in key/value pairs.

  [See examples](/docs/dashboard/emails/tags).

  <Expandable title="properties">
    <ParamField type="string">
      The name of the email tag.

      It can only contain ASCII letters (a–z, A–Z), numbers (0–9), underscores (\_), or dashes (-).

      It can contain no more than 256 characters.
    </ParamField>

    <ParamField type="string">
      The value of the email tag.

      It can only contain ASCII letters (a–z, A–Z), numbers (0–9), underscores (\_), or dashes (-).

      It can contain no more than 256 characters.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField type="object">
  To send using a template, provide a `template` object with:

  * `id`: the id *or* the alias of the published template
  * `variables`: an object with a key for each variable (if applicable)

  <Info>
    If a `template` is provided, you cannot send `html`, `text`, or `react` in the payload, otherwise the API will return a validation error.

    When sending a template, the payload for `from`, `subject`, and `reply_to` take precedence over the template's defaults for these fields. If the template does not provide a default value for these fields, you must provide them in the payload.
  </Info>
</ParamField>

<ParamField type="string">
  The id of the published email template. Required if `template` is provided. Only published templates can be used when sending emails.
</ParamField>

<ParamField type="object">
  Template variables object with key/value pairs.

  ```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
  variables: {
  	CTA: 'Sign up now',
  	CTA_LINK: 'https://example.com/signup'
  }
  ```

  When sending the template, the HTML will be parsed. If all the variables used in the template were provided, the email will be sent. If not, the call will throw a validation error.

  See the [errors reference](/docs/api-reference/errors) for more details or [learn more about templates](/docs/dashboard/templates/introduction).

  <Expandable title="properties">
    <ParamField type="string">
      The key of the variable.

      May only contain ASCII letters (a–z, A–Z), numbers (0–9), and underscores (\_). The following variable names are reserved and cannot be used: `FIRST_NAME`, `LAST_NAME`, `EMAIL`, `UNSUBSCRIBE_URL`.

      It can contain no more than 50 characters.
    </ParamField>

    <ParamField type="string | number">
      The value of the variable.

      Observe these technical limitations:

      * `string`: maximum length of 2,000 characters
      * `number`: not greater than 2^53 - 1
    </ParamField>
  </Expandable>
</ParamField>

## Headers

<ParamField type="string">
  Add an idempotency key to prevent duplicated emails.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**

  [Learn more about idempotency keys →](/docs/dashboard/emails/idempotency-keys)
</ParamField>

## Limitations

The `attachments` field is not supported yet.

## Response format

When the request succeeds, each entry in `data` corresponds to the email at the same index in the batch payload (0-based). The first email in your request will be the first entry in `data`, and so on.

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.batch.send([
    {
      from: 'Acme <onboarding@resend.dev>',
      to: ['foo@gmail.com'],
      subject: 'hello world',
      html: '<h1>it works!</h1>',
    },
    {
      from: 'Acme <onboarding@resend.dev>',
      to: ['bar@outlook.com'],
      subject: 'world hello',
      html: '<p>it works!</p>',
    },
  ]);
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->batch->send([
    [
      'from' => 'Acme <onboarding@resend.dev>',
      'to' => ['foo@gmail.com'],
      'subject' => 'hello world',
      'html' => '<h1>it works!</h1>',
    ],
    [
      'from' => 'Acme <onboarding@resend.dev>',
      'to' => ['bar@outlook.com'],
      'subject' => 'world hello',
      'html' => '<p>it works!</p>',
    ]
  ]);
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend
  from typing import List

  resend.api_key = "re_xxxxxxxxx"

  params: List[resend.Emails.SendParams] = [
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["foo@gmail.com"],
      "subject": "hello world",
      "html": "<h1>it works!</h1>",
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["bar@outlook.com"],
      "subject": "world hello",
      "html": "<p>it works!</p>",
    }
  ]

  resend.Batch.send(params)
  ```

  ```rb Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = 're_xxxxxxxxx'

  params = [
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["foo@gmail.com"],
      "subject": "hello world",
      "html": "<h1>it works!</h1>",
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["bar@outlook.com"],
      "subject": "world hello",
      "html": "<p>it works!</p>",
    }
  ]

  Resend::Batch.send(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"fmt"
  	"os"

  	"github.com/resend/resend-go/v3"
  )

  func main() {

    ctx := context.TODO()

    client := resend.NewClient("re_xxxxxxxxx")

    var batchEmails = []*resend.SendEmailRequest{
      {
        From:    "Acme <onboarding@resend.dev>",
        To:      []string{"foo@gmail.com"},
        Subject: "hello world",
        Html:    "<h1>it works!</h1>",
      },
      {
        From:    "Acme <onboarding@resend.dev>",
        To:      []string{"bar@outlook.com"},
        Subject: "world hello",
        Html:    "<p>it works!</p>",
      },
    }

    sent, err := client.Batch.SendWithContext(ctx, batchEmails)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Data)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::CreateEmailBaseOptions;
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let emails = vec![
      CreateEmailBaseOptions::new(
        "Acme <onboarding@resend.dev>",
        vec!["foo@gmail.com"],
        "hello world",
      )
      .with_html("<h1>it works!</h1>"),
      CreateEmailBaseOptions::new(
        "Acme <onboarding@resend.dev>",
        vec!["bar@outlook.com"],
        "world hello",
      )
      .with_html("<p>it works!</p>"),
    ];

    let _emails = resend.batch.send(emails).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateEmailOptions firstEmail = CreateEmailOptions.builder()
              .from("Acme <onboarding@resend.dev>")
              .to("foo@gmail.com")
              .subject("hello world")
              .html("<h1>it works!</h1>")
              .build();

          CreateEmailOptions secondEmail = CreateEmailOptions.builder()
              .from("Acme <onboarding@resend.dev>")
              .to("bar@outlook.com")
              .subject("world hello")
              .html("<p>it works!</p>")
              .build();

          CreateBatchEmailsResponse data = resend.batch().send(
              Arrays.asList(firstEmail, secondEmail)
          );
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var mail1 = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "foo@gmail.com",
      Subject = "hello world",
      HtmlBody = "<p>it works!</p>",
  };

  var mail2 = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "bar@outlook.com",
      Subject = "hello world",
      HtmlBody = "<p>it works!</p>",
  };

  var resp = await resend.EmailBatchAsync( [ mail1, mail2 ] );
  Console.WriteLine( "Nr Emails={0}", resp.Content.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails/batch' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'[
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["foo@gmail.com"],
      "subject": "hello world",
      "html": "<h1>it works!</h1>"
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["bar@outlook.com"],
      "subject": "world hello",
      "html": "<p>it works!</p>"
    }
  ]'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails batch --file ./path/to/emails.json
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "data": [
      {
        "id": "ae2014de-c168-4c61-8267-70d2662a1ce1"
      },
      {
        "id": "faccb7a5-8a28-4e9a-ac64-8da1cc3bc1cb"
      }
    ]
  }
  ```
</ResponseExample>


# Send Email
Source: https://resend.com/docs/api-reference/emails/send-email

POST /emails
Start sending emails through the Resend Email API.

## Body Parameters

<ParamField type="string">
  Sender email address.

  To include a friendly name, pass the sender as `Name <email@example.com>`, for example `Acme <onboarding@example.dev>`.
</ParamField>

<ParamField type="string | string[]">
  Recipient email address. For multiple addresses, send as an array of strings.
  Max 50.
</ParamField>

<ParamField type="string">
  Email subject.
</ParamField>

<ParamField type="string | string[]">
  Bcc recipient email address. For multiple addresses, send as an array of
  strings.
</ParamField>

<ParamField type="string | string[]">
  Cc recipient email address. For multiple addresses, send as an array of
  strings.
</ParamField>

<ResendParamField type="string">
  Schedule email to be sent later. The date should be in natural language (e.g.: `in 1 min`) or ISO 8601 format (e.g:
  `2026-08-05T11:52:01.858Z`).

  [See examples](/docs/dashboard/emails/schedule-email)
</ResendParamField>

<ResendParamField type="string | string[]">
  Reply-to email address. For multiple addresses, send as an array of strings.
</ResendParamField>

<ParamField type="string">
  The HTML version of the message.
</ParamField>

<ParamField type="string">
  The plain text version of the message.

  <Info>
    If not provided, the HTML will be used to generate a plain text version. You
    can opt out of this behavior by setting value to an empty string.
  </Info>
</ParamField>

<ParamField type="React.ReactNode">
  The React component used to write the message. *Only available in the Node.js
  SDK.*
</ParamField>

<ParamField type="object">
  Custom headers to add to the email.
</ParamField>

<ResendParamField type="string">
  The topic ID to receive the email.

  * If the recipient is a contact and has opted-in to the topic, the email is sent.
  * If the recipient is a contact and has opted-out of the topic, the email is not sent and will be marked as failed.
  * If the recipient is not a contact, the email is sent if the topic default subscription value is set to `opt-in`.

  <Note>Each email address (to, cc, bcc) is checked and handled separately.</Note>
</ResendParamField>

<ParamField type="array">
  Filename and content of attachments (max 40MB per email, after Base64 encoding of the attachments).

  [See examples](/docs/dashboard/emails/attachments)

  <Expandable title="properties">
    <ParamField type="buffer | string">
      Content of an attached file, passed as a buffer or Base64 string.
    </ParamField>

    <ParamField type="string">
      Name of attached file.
    </ParamField>

    <ParamField type="string">
      Path where the attachment file is hosted
    </ParamField>

    <ResendParamField type="string">
      Content type for the attachment, if not set will be derived from the filename property
    </ResendParamField>

    <ResendParamField type="string">
      You can embed images using the content id parameter for the attachment. To show the image, you need to include the ID in the `src` attribute of the `img` tag (e.g., `<img src="cid:...">`) of your HTML. [Learn about inline images](/docs/dashboard/emails/embed-inline-images).
    </ResendParamField>
  </Expandable>
</ParamField>

<ParamField type="array">
  Custom data passed in key/value pairs.

  [See examples](/docs/dashboard/emails/tags).

  <Expandable title="properties">
    <ParamField type="string">
      The name of the email tag.

      It can only contain ASCII letters (a–z, A–Z), numbers (0–9), underscores (\_), or dashes (-).

      It can contain no more than 256 characters.
    </ParamField>

    <ParamField type="string">
      The value of the email tag.

      It can only contain ASCII letters (a–z, A–Z), numbers (0–9), underscores (\_), or dashes (-).

      It can contain no more than 256 characters.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField type="object">
  To send using a template, provide a `template` object with:

  * `id`: the id *or* the alias of the published template
  * `variables`: an object with a key for each variable (if applicable)

  <Info>
    If a `template` is provided, you cannot send `html`, `text`, or `react` in the payload, otherwise the API will return a validation error.

    When sending a template, the payload for `from`, `subject`, and `reply_to` take precedence over the template's defaults for these fields. If the template does not provide a default value for these fields, you must provide them in the payload.
  </Info>
</ParamField>

<ParamField type="string">
  The id of the published email template. Required if `template` is provided. Only published templates can be used when sending emails.
</ParamField>

<ParamField type="object">
  Template variables object with key/value pairs.

  ```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
  variables: {
  	CTA: 'Sign up now',
  	CTA_LINK: 'https://example.com/signup'
  }
  ```

  When sending the template, the HTML will be parsed. If all the variables used in the template were provided, the email will be sent. If not, the call will throw a validation error.

  See the [errors reference](/docs/api-reference/errors) for more details or [learn more about templates](/docs/dashboard/templates/introduction).

  <Expandable title="properties">
    <ParamField type="string">
      The key of the variable.

      May only contain ASCII letters (a–z, A–Z), numbers (0–9), and underscores (\_). The following variable names are reserved and cannot be used: `FIRST_NAME`, `LAST_NAME`, `EMAIL`, `UNSUBSCRIBE_URL`.

      It can contain no more than 50 characters.
    </ParamField>

    <ParamField type="string | number">
      The value of the variable.

      Observe these technical limitations:

      * `string`: maximum length of 2,000 characters
      * `number`: not greater than 2^53 - 1
    </ParamField>
  </Expandable>
</ParamField>

## Headers

<ParamField type="string">
  Add an idempotency key to prevent duplicated emails.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**

  [Learn more](/docs/dashboard/emails/idempotency-keys)
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'hello world',
    html: '<p>it works!</p>',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->send([
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'hello world',
    'html' => '<p>it works!</p>'
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Emails.SendParams = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>"
  }

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

  ```rb Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>"
  }

  sent = Resend::Emails.send(params)
  puts sent
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
    ctx := context.TODO()
    client := resend.NewClient("re_xxxxxxxxx")

    params := &resend.SendEmailRequest{
        From:        "Acme <onboarding@resend.dev>",
        To:          []string{"delivered@resend.dev"},
        Subject:     "hello world",
        Html:        "<p>it works!</p>"
    }

    sent, err := client.Emails.SendWithContext(ctx, params)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Id)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::{CreateEmailBaseOptions};
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let from = "Acme <onboarding@resend.dev>";
    let to = ["delivered@resend.dev"];
    let subject = "hello world";
    let html = "<p>it works!</p>";

    let email = CreateEmailBaseOptions::new(from, to, subject)
      .with_html(html);

    let _email = resend.emails.send(email).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateEmailOptions params = CreateEmailOptions.builder()
                  .from("Acme <onboarding@resend.dev>")
                  .to("delivered@resend.dev")
                  .subject("hello world")
                  .html("<p>it works!</p>")
                  .build();

          CreateEmailResponse data = resend.emails().send(params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.EmailSendAsync( new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = "hello world",
      HtmlBody = "<p>it works!</p>",
  } );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails send \
    --from "Acme <onboarding@resend.dev>" \
    --to delivered@resend.dev \
    --subject "hello world" \
    --html "<p>it works!</p>"
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794"
  }
  ```
</ResponseExample>


# Update Email
Source: https://resend.com/docs/api-reference/emails/update-email

PATCH /emails/:email_id
Update a scheduled email.

## Path Parameters

<ParamField type="string">
  The Email ID.
</ParamField>

## Body Parameters

<ResendParamField type="string">
  Schedule email to be sent later. The date should be in ISO 8601 format (e.g:
  2026-08-05T11:52:01.858Z).
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const oneMinuteFromNow = new Date(Date.now() + 1000 * 60).toISOString();

  const { data, error } = await resend.emails.update({
    id: '49a3999c-0ce1-4ea6-ab68-afcd6dc2e794',
    scheduledAt: oneMinuteFromNow,
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $oneMinuteFromNow = (new DateTime())->modify('+1 minute')->format(DateTime::ISO8601);

  $resend->emails->update('49a3999c-0ce1-4ea6-ab68-afcd6dc2e794', [
    'scheduled_at' => $oneMinuteFromNow
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend
  from datetime import datetime, timedelta

  resend.api_key = "re_xxxxxxxxx"

  one_minute_from_now = (datetime.now() + timedelta(minutes=1)).isoformat()

  update_params: resend.Emails.UpdateParams = {
    "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
    "scheduled_at": one_minute_from_now
  }

  resend.Emails.update(params=update_params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  one_minute_from_now = (Time.now + 1 * 60).strftime("%Y-%m-%dT%H:%M:%S.%L%z")

  update_params = {
    "email_id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
    "scheduled_at": one_minute_from_now
  }

  Resend::Emails.update(update_params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"time"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	oneMinuteFromNow := time.Now().Add(time.Minute * time.Duration(1))
  	oneMinuteFromNowIso := oneMinuteFromNow.Format("2006-01-02T15:04:05-0700")

  	updateParams := &resend.UpdateEmailRequest{
  		Id:          "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
  		ScheduledAt: oneMinuteFromNowIso,
  	}

  	client.Emails.Update(updateParams)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use chrono::{Local, TimeDelta};
  use resend_rs::types::UpdateEmailOptions;
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let one_minute_from_now = Local::now()
      .checked_add_signed(TimeDelta::minutes(1))
      .unwrap()
      .to_rfc3339();

    let update = UpdateEmailOptions::new()
      .with_scheduled_at(&one_minute_from_now);

    let _email = resend
      .emails
      .update("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794", update)
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          String oneMinuteFromNow = Instant
            .now()
            .plus(1, ChronoUnit.MINUTES)
            .toString();

          UpdateEmailOptions updateParams = UpdateEmailOptions.builder()
                  .scheduledAt(oneMinuteFromNow)
                  .build();

          UpdateEmailResponse data = resend.emails().update("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794", updateParams);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.EmailRescheduleAsync(
      new Guid( "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794" ),
      DateTime.UtcNow.AddMinutes( 1 ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X PATCH 'https://api.resend.com/emails/49a3999c-0ce1-4ea6-ab68-afcd6dc2e794' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "scheduled_at": "2026-08-05T11:52:01.858Z"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails update 49a3999c-0ce1-4ea6-ab68-afcd6dc2e794 \
    --scheduled-at "2026-08-05T11:52:01.858Z"
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "email",
    "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794"
  }
  ```
</ResponseExample>


# Errors
Source: https://resend.com/docs/api-reference/errors

Troubleshoot problems with this comprehensive breakdown of all error codes.

## Error schema

Resend uses standard HTTP response codes for success and failure notifications, and errors are further classified by type.

### `invalid_idempotency_key`

* **Status:** 400
* **Message:** The key must be between 1–256 chars.
* **Suggested action:** Retry with a valid idempotency key.

### `validation_error`

* **Status:** 400
* **Message:** An error was found with one or more fields in the request.
* **Suggested action:** The message will contain more details about what field and error were found.

### `missing_api_key`

* **Status:** 401
* **Message:** Missing API key in the authorization header.
* **Suggested action:** Include the following header in the request: `Authorization: Bearer YOUR_API_KEY`.

### `restricted_api_key`

* **Status:** 401
* **Message:** This API key is restricted to only send emails.
* **Suggested action:** Make sure the API key has `Full access` to perform actions other than sending emails.

### `invalid_api_key`

* **Status:** 403
* **Message:** API key is invalid.
* **Suggested action:** Make sure the API key is correct or generate a new [API key in the dashboard](https://resend.com/api-keys).

### `validation_error`

* **Status:** 403
* **Message:** You can only send testing emails to your own email address (`youremail@domain.com`). To send emails to other recipients, please verify a domain at resend.com/domains, and change the `from` address to an email using this domain.
* **Suggested action:** In [Resend's Domain page](https://resend.com/domains), add and verify a domain for which you have DNS access. This allows you to send emails to addresses beyond your own. [Learn more about resolving this error](/docs/knowledge-base/403-error-resend-dev-domain).

### `validation_error`

* **Status:** 403
* **Message:** The `domain.com` domain is not verified. Please, add and verify your domain.
* **Suggested action:** Make sure the domain in your API request's `from` field matches a domain you've verified in Resend. Update your API request to use your verified domain, or add and verify the domain you're trying to use. [Learn more about resolving this error](/docs/knowledge-base/403-error-domain-mismatch).

### `validation_error`

* **Status:** 403
* **Message:** The `example.com` domain has been registered already.
* **Suggested action:** Verify you are signed in to the correct Resend account and check whether a teammate already added the domain. If you still cannot access it, [contact support](https://resend.com/help). [Learn more about resolving this error](/docs/knowledge-base/domain-already-registered).

### `not_found`

* **Status:** 404
* **Message:** The requested endpoint does not exist.
* **Suggested action:** Change your request URL to match a valid API endpoint.

### `method_not_allowed`

* **Status:** 405
* **Message:** Method is not allowed for the requested path.
* **Suggested action:** Change your API endpoint to use a valid method.

### `invalid_idempotent_request`

* **Status:** 409
* **Message:** Same idempotency key used with a different request payload.
* **Suggested action:** Change your idempotency key or payload.

### `concurrent_idempotent_requests`

* **Status:** 409
* **Message:** Same idempotency key used while original request is still in progress.
* **Suggested action:** Try the request again later.

### `invalid_attachment`

* **Status:** 422
* **Message:** Attachment must have either a `content` or `path`.
* **Suggested action:** Attachments must either have a `content` (strings, Buffer, or Stream contents) or `path` to a remote resource (better for larger attachments).

### `invalid_from_address`

* **Status:** 422
* **Message:** Invalid `from` field.
* **Suggested action:** Make sure the `from` field is valid. The email address needs to follow the `email@example.com` or `Name <email@example.com>` format.

### `invalid_access`

* **Status:** 422
* **Message:** Access must be "full\_access" | "sending\_access".
* **Suggested action:** Make sure the API key has necessary permissions.

### `invalid_parameter`

* **Status:** 422
* **Message:** The `parameter` must be a valid UUID.
* **Suggested action:** Check the value and make sure it's valid.

### `invalid_region`

* **Status:** 422
* **Message:** Region must be "us-east-1" | "eu-west-1" | "sa-east-1".
* **Suggested action:** Make sure the correct region is selected.

### `missing_required_field`

* **Status:** 422
* **Message:** The request body is missing one or more required fields.
* **Suggested action:** Check the error message to see the list of missing fields.

### `monthly_quota_exceeded`

* **Status:** 429
* **Message:** You have reached your monthly email quota.
* **Suggested action:** [Upgrade your plan](https://resend.com/settings/billing) to increase the monthly email quota. Both sent and received emails count towards this quota.

### `daily_quota_exceeded`

* **Status:** 429
* **Message:** You have reached your daily email quota.
* **Suggested action:** [Upgrade your plan](https://resend.com/settings/billing) to remove the daily quota limit or wait until 24 hours have passed. Both sent and received emails count towards this quota.

### `rate_limit_exceeded`

* **Status:** 429
* **Message:** Too many requests. Please limit the number of requests per second. Or [contact support](https://resend.com/contact) to increase rate limit.
* **Suggested action:** Read the [response headers](./introduction#rate-limit) and reduce the rate at which you request the API. This can be done by introducing a queue mechanism or reducing the number of concurrent requests per second. If you have specific requirements, [contact support](https://resend.com/contact) to request a rate increase.

### `security_error`

* **Status:** 451
* **Message:** A possible security issue was found with the request.
* **Suggested action:** The message will contain more details. [Contact support](https://resend.com/contact) for more information.

### `application_error`

* **Status:** 500
* **Message:** An unexpected error occurred.
* **Suggested action:** Try the request again later. If the error does not resolve, check our [status page](https://resend-status.com) for service updates.

### `internal_server_error`

* **Status:** 500
* **Message:** An unexpected error occurred.
* **Suggested action:** Try the request again later. If the error does not resolve, check our [status page](https://resend-status.com) for service updates.


# Introduction
Source: https://resend.com/docs/api-reference/introduction

Understand general concepts, response codes, and authentication strategies.

<Info>
  For most use cases, we recommend using an [official Resend SDK](/docs/sdks) instead
  of calling the API directly. The SDKs handle authentication, required headers,
  and error handling for you. See [Resend API vs SDK](/docs/api-vs-sdk) to decide
  which fits your project.
</Info>

## Base URL

The Resend API is built on **REST** principles. **HTTPS** is enforced in every request to improve data security, integrity, and privacy. The API does not support **HTTP**.

All requests contain the following base URL:

```
https://api.resend.com
```

## Authentication

To authenticate you need to add an *Authorization* header with the contents of the header being `Bearer re_xxxxxxxxx` where `re_xxxxxxxxx` is your [API Key](https://resend.com/api-keys).

```
Authorization: Bearer re_xxxxxxxxx
```

## User-Agent

All API requests must include a `User-Agent` header. Requests without this header will be rejected with a `403` status code. Most HTTP clients, all [Resend SDKs](/docs/sdks), and the [Resend CLI](/docs/cli) include this header automatically, but if you're making direct HTTP requests, make sure to set it:

```
User-Agent: my-app/1.0
```

<Info>
  If you're getting a `403` error with error code `1010` despite having a valid
  API key, a missing `User-Agent` header is likely the cause. See [Error
  1010](/docs/knowledge-base/403-error-1010) for more details.
</Info>

## Response codes

Resend uses standard HTTP codes to indicate the success or failure of your requests.

In general, `2xx` HTTP codes correspond to success, `4xx` codes are for user-related failures, and `5xx` codes are for infrastructure issues.

| Status | Description                             |
| ------ | --------------------------------------- |
| `200`  | Successful request.                     |
| `400`  | Check that the parameters were correct. |
| `401`  | The API key used was missing.           |
| `403`  | The API key used was invalid.           |
| `404`  | The resource was not found.             |
| `429`  | The rate limit was exceeded.            |
| `5xx`  | Indicates an error with Resend servers. |

<Info>
  Check [Error Codes](/docs/api-reference/errors) for a comprehensive breakdown of
  all possible API errors.
</Info>

## Rate limit

The default maximum rate limit is **10 requests per second per team**. This limit applies across all API keys associated with your team. This number can be increased for trusted senders by request. You can view your team's current rate limit on the [Settings Usage page](https://resend.com/settings/usage). After that, you'll hit the rate limit and receive a `429` response error code.

Learn more about our [rate limits](/docs/api-reference/rate-limit).

## FAQ

<AccordionGroup>
  <Accordion title="How does pagination work with the API?">
    Some endpoints support cursor-based pagination to help you browse through
    large datasets efficiently. Check our [pagination
    guide](/docs/api-reference/pagination) for detailed information on how to use
    pagination parameters.
  </Accordion>

  <Accordion title="How do you handle API versioning?">
    Currently, there's no versioning system in place. We plan to add versioning
    via calendar-based headers in the future.
  </Accordion>
</AccordionGroup>


# List Logs
Source: https://resend.com/docs/api-reference/logs/list-logs

GET /logs
Retrieve a list of API request logs.

<QueryParams type="logs" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.logs.list();
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->logs->list();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Logs.list()
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = "re_xxxxxxxxx"

  logs = Resend::Logs.list
  puts logs
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	logs, err := client.Logs.ListWithOptions(ctx, nil)
  	if err != nil {
  		panic(err)
  	}

  	if logs.HasMore {
  		opts := &resend.ListOptions{
  			After: &logs.Data[len(logs.Data)-1].Id,
  		}
  		client.Logs.ListWithOptions(ctx, opts)
  	}
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result, list_opts::ListOptions};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _logs = resend
      .logs
      .list(ListOptions::default())
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          resend.logs().list();
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;
  using System.Linq;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.LogListAsync();
  Console.WriteLine( "Count={0}", resp.Content.Data.Count );

  if ( resp.Content.HasMore )
  {
      var lastId = resp.Content.Data.Last().Id;
      await resend.LogListAsync( new PaginatedQuery()
      {
          After = lastId.ToString(),
      } );
  }
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/logs' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend logs list
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "37e4414c-5e25-4dbc-a071-43552a4bd53b",
        "created_at": "2026-03-30 13:43:54.622865+00",
        "endpoint": "/emails",
        "method": "POST",
        "response_status": 200,
        "user_agent": "resend-node:6.0.3"
      },
      {
        "id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
        "created_at": "2026-03-30 12:15:00.123456+00",
        "endpoint": "/emails/4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
        "method": "GET",
        "response_status": 200,
        "user_agent": "curl/8.7.1"
      }
    ]
  }
  ```
</ResponseExample>


# Retrieve Log
Source: https://resend.com/docs/api-reference/logs/retrieve-log

GET /logs/:log_id
Retrieve a single API request log.

## Path Parameters

<ParamField type="string">
  The Log ID.
</ParamField>

<Info>
  The `request_body` and `response_body` fields vary depending on the original
  API request that was logged.
</Info>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.logs.get(
    '37e4414c-5e25-4dbc-a071-43552a4bd53b',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->logs->get('37e4414c-5e25-4dbc-a071-43552a4bd53b');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Logs.get("37e4414c-5e25-4dbc-a071-43552a4bd53b")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = "re_xxxxxxxxx"

  log = Resend::Logs.get("37e4414c-5e25-4dbc-a071-43552a4bd53b")
  puts log
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Logs.Get("37e4414c-5e25-4dbc-a071-43552a4bd53b")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _logs = resend
      .logs
      .get("37e4414c-5e25-4dbc-a071-43552a4bd53b")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          resend.logs().get("37e4414c-5e25-4dbc-a071-43552a4bd53b");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.LogRetrieveAsync( new Guid( "37e4414c-5e25-4dbc-a071-43552a4bd53b" ) );
  Console.WriteLine( "Endpoint={0}", resp.Content.Endpoint );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/logs/37e4414c-5e25-4dbc-a071-43552a4bd53b' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend logs get 37e4414c-5e25-4dbc-a071-43552a4bd53b
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "log",
    "id": "37e4414c-5e25-4dbc-a071-43552a4bd53b",
    "created_at": "2026-03-30 13:43:54.622865+00",
    "endpoint": "/emails",
    "method": "POST",
    "response_status": 200,
    "user_agent": "resend-node:6.0.3",
    "request_body": {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Hello World"
    },
    "response_body": {
      "id": "4ef9a417-02e9-4d39-ad75-9611e0fcc33c"
    }
  }
  ```
</ResponseExample>


# Authorize
Source: https://resend.com/docs/api-reference/oauth/authorize

GET /oauth/authorize
Start the OAuth authorization code + PKCE flow.

This is a browser redirect endpoint, not a JSON API call. Open this URL in the user's browser. Don't fetch it from a backend or CLI process and follow the redirect yourself, since the user has to see and approve the consent screen.

The flow:

1. The client opens `/oauth/authorize` in the user's browser.
2. Resend redirects (`302`) to the Resend dashboard consent screen, which handles login if needed.
3. The user reviews and approves (or denies) the request.
4. The dashboard redirects the browser back to the client's `redirect_uri` with a `code` and the original `state`.

## Query Parameters

<ParamField type="string">
  The `client_id` from [registration](/docs/api-reference/oauth/register), or the
  HTTPS URL of a [Client ID Metadata Document](#client-id-metadata-documents).
  Resend tells the two apart by the `https://` prefix.
</ParamField>

<ParamField type="string">
  Must be `"code"`.
</ParamField>

<ParamField type="string">
  Must exactly match one of the client's registered redirect URIs. The only
  exception is loopback URIs (`127.0.0.1`, `localhost`, `[::1]`), where the port
  is allowed to differ from what was registered.
</ParamField>

<ParamField type="string">
  Space-delimited list of requested scopes. If omitted, defaults to the client's
  full registered scope set.
</ParamField>

### Scopes

* `emails:send` is enough for send-only routes: `POST /emails`, `POST /email`,
  `POST /emails/sending`, `POST /email/sending`, and `POST
  /broadcasts/:broadcastId/send`.
* `full_access` is required for every other API route. Also satisfies any
  `emails:send`-scoped check.

<ParamField type="string">
  An opaque value round-tripped back on the callback unchanged. Use it to bind
  the callback to the request that started the flow. Recommended, not required
  by the server, but a client that skips it can't detect CSRF on the callback.
  Maximum 1024 characters.
</ParamField>

<ParamField type="string">
  Base64url-encoded SHA-256 hash of a
  [code\_verifier](/docs/api-reference/oauth/token#param-code-verifier) your client
  generates.
</ParamField>

<ParamField type="string">
  Must be `"S256"`. Resend does not support the `plain` method.
</ParamField>

<Info>
  A `resource` parameter (RFC 8707) is accepted but ignored. Resend does not
  support resource indicators yet.
</Info>

### Client ID Metadata Documents

A `client_id` that starts with `https://` is read as the URL of a JSON document describing the client, so the client never registers. This follows the [OAuth Client ID Metadata Document](https://datatracker.ietf.org/doc/draft-ietf-oauth-client-id-metadata-document/) draft.

This is the only endpoint that fetches the document. See [Client ID Metadata Documents](/docs/guides/building-a-resend-oauth-client#client-id-metadata-documents) for the document fields and for how Resend fetches and caches it.

<RequestExample>
  ```bash Browser navigation theme={"theme":{"light":"github-light","dark":"vesper"}}
  GET https://api.resend.com/oauth/authorize?client_id=550e8400-e29b-41d4-a716-446655440000&response_type=code&redirect_uri=http%3A%2F%2F127.0.0.1%3A49152%2Foauth%2Fcallback&scope=emails%3Asend&state=STATE_VALUE&code_challenge=CODE_CHALLENGE_VALUE&code_challenge_method=S256
  ```
</RequestExample>

<ResponseExample>
  ```http Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  HTTP/1.1 302 Found
  Location: https://resend.com/oauth/authorize/3f9c1e2a-...
  ```
</ResponseExample>

## Errors

Before `client_id` and `redirect_uri` are validated (unknown `client_id`, invalid or unregistered `redirect_uri`), Resend returns a JSON error body, since it can't safely redirect to an unvalidated URL.

Once Resend validates `client_id` and `redirect_uri`, errors redirect (`302`) back to `redirect_uri` with `error`, `error_description`, and (if provided) `state` as query parameters only when the `redirect_uri` is trusted: a loopback address, a private-use URI scheme, or a verified client. An unverified `https` callback gets a JSON error body instead, which prevents the endpoint from being used as an open redirect. Handle both.

| `error`               | When                                                                                                       |
| --------------------- | ---------------------------------------------------------------------------------------------------------- |
| `invalid_request`     | `response_type` isn't `code`, or `code_challenge_method` isn't `S256`.                                     |
| `invalid_client`      | Unknown or disabled `client_id`. Also a metadata document that couldn't be fetched or didn't validate.     |
| `unauthorized_client` | The client isn't registered for the `authorization_code` grant.                                            |
| `invalid_scope`       | No scope requested, a scope isn't supported, or a scope isn't in the client's registered `scopes_allowed`. |
| `server_error`        | Resend failed to persist the authorization request.                                                        |


# List Grants
Source: https://resend.com/docs/api-reference/oauth/list-grants

GET /oauth/grants
Retrieve a list of OAuth grants for the authenticated team.

Returns all of the team's OAuth grants, including revoked ones. A grant's
`revoked_at` and `revoked_reason` are `null` while it is active. They are set
once the grant is revoked.

<QueryParams type="OAuth grants" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.oauthGrants.list();
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result, list_opts::ListOptions};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _data = resend.oauth.list(ListOptions::default()).await?;

    Ok(())
  }
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/oauth/grants' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend oauth-grants list
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "650e8400-e29b-41d4-a716-446655440001",
        "client_id": "430eed87-632a-4ea6-90db-0aace67ec228",
        "scopes": ["emails:send"],
        "resource": null,
        "created_at": "2026-04-08 00:11:13.110779+00",
        "revoked_at": null,
        "revoked_reason": null,
        "client": {
          "name": "Resend CLI",
          "logo_uri": "https://example.com/logo.png"
        }
      },
      {
        "id": "650e8400-e29b-41d4-a716-446655440002",
        "client_id": "430eed87-632a-4ea6-90db-0aace67ec228",
        "scopes": ["emails:send", "domains:read"],
        "resource": "https://api.resend.com",
        "created_at": "2026-04-07 00:11:13.110779+00",
        "revoked_at": "2026-04-09 00:11:13.110779+00",
        "revoked_reason": "revoked_from_api",
        "client": {
          "name": "Resend CLI",
          "logo_uri": "https://example.com/logo.png"
        }
      }
    ]
  }
  ```
</ResponseExample>


# Register Client
Source: https://resend.com/docs/api-reference/oauth/register

POST /oauth/register
Dynamically register an OAuth client for the authorization code + PKCE flow (RFC 7591).

Dynamic Client Registration (DCR) lets a client obtain a `client_id` at runtime instead of being pre-registered by Resend. This endpoint is unauthenticated (no API key).

By default it issues a **public** client that authenticates at the token endpoint with PKCE alone. Register with a `client_secret_*` [authentication method](#param-token-endpoint-auth-method) to get a **confidential** client, which is issued a `client_secret` in the response. Confidential clients still complete PKCE on every authorization code exchange. The secret is an additional factor, not a replacement.

<Note>
  Prefer a [Client ID Metadata
  Document](/docs/guides/building-a-resend-oauth-client#client-id-metadata-documents)
  if the client can host a static JSON file. You pass the document's HTTPS URL
  as the `client_id` and skip this endpoint, and the consent screen can name the
  host that published it rather than a name the client picked for itself. DCR
  stays supported for clients that can't publish a document.
</Note>

<Note>
  This endpoint is rate-limited to 20 registrations per hour per IP address.
  Requests over the limit get a `429` with `{"error": "too_many_requests"}`.
</Note>

## Body Parameters

<ParamField type="string">
  A human-readable name for the client. Maximum 200 characters.
</ParamField>

<ParamField type="string[]">
  URIs the authorization server may redirect to after the user approves the
  request. At least one is required, up to 10, each up to 2048 characters. See
  [Allowed redirect URIs](#allowed-redirect-uris) for the rules.
</ParamField>

<ParamField type="string[]">
  Must include `authorization_code`. `refresh_token` is also supported.
</ParamField>

<ParamField type="string[]">
  Only `code` is supported. The value is validated if present but not stored;
  the response always echoes back `["code"]`.
</ParamField>

<ParamField type="string">
  Space-delimited list of scopes to request, e.g. `"emails:send"`. Must be a
  subset of the [supported scopes](/docs/api-reference/oauth/authorize#scopes). If
  omitted, the client is registered with every supported scope.
</ParamField>

<ParamField type="string">
  How the client authenticates at the [token](/docs/api-reference/oauth/token) and
  [revocation](/docs/api-reference/oauth/revoke) endpoints. `none` (the default) is a
  public client that proves itself with PKCE alone. `client_secret_basic` and
  `client_secret_post` are confidential clients that also present a
  `client_secret`, sent in the HTTP `Authorization: Basic` header or as a body
  parameter respectively. A `client_secret_*` method issues a `client_secret` in
  the response. See [Confidential clients](#confidential-clients).
</ParamField>

<ParamField type="string">
  A URL for the client's homepage. Echoed back, not otherwise used.
</ParamField>

<ParamField type="string">
  A URL for the client's logo. Shown on the consent screen.
</ParamField>

### Confidential clients

Registering with `token_endpoint_auth_method` set to `client_secret_basic` or `client_secret_post` returns two extra fields:

<ResponseField name="client_secret" type="string">
  The generated client secret. Returned **only once**, in this response. Resend
  stores a hash and can't show it again, so persist it securely at registration
  time. If it's lost, register a new client.
</ResponseField>

<ResponseField name="client_secret_expires_at" type="number">
  Unix time at which the secret expires. Always `0`, meaning the secret does not
  expire.
</ResponseField>

Only register a confidential client when it has a backend that can keep the secret private, such as a server-side web app. Native, CLI, and other clients that can't protect a secret should stay public (`none`) and rely on PKCE. See [Building an OAuth client](/docs/guides/building-a-resend-oauth-client) for how each client type authenticates.

### Allowed redirect URIs

* `https://` URIs are unrestricted.
* `http://` is only allowed for loopback addresses (`127.0.0.1`, `localhost`,
  `[::1]`), for native/CLI clients that run a local callback server.
* Private-use URI schemes (e.g. `cursor://`, `vscode://`) are allowed, since the
  OS routes them only to the registered native app.
* `file`, `ftp`, `data`, `javascript`, `blob`, `about`, and `vbscript` schemes
  are rejected, and none of the URIs may include a fragment.

<RequestExample>
  ```bash Public client theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/oauth/register' \
       -H 'Content-Type: application/json' \
       -d $'{
    "client_name": "Example OAuth Client",
    "redirect_uris": ["http://127.0.0.1/oauth/callback"],
    "grant_types": ["authorization_code", "refresh_token"],
    "response_types": ["code"],
    "token_endpoint_auth_method": "none",
    "scope": "emails:send"
  }'
  ```

  ```bash Confidential client theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/oauth/register' \
       -H 'Content-Type: application/json' \
       -d $'{
    "client_name": "Example OAuth Client",
    "redirect_uris": ["http://127.0.0.1/oauth/callback"],
    "grant_types": ["authorization_code", "refresh_token"],
    "response_types": ["code"],
    "token_endpoint_auth_method": "client_secret_basic",
    "scope": "emails:send"
  }'
  ```
</RequestExample>

<ResponseExample>
  ```json Public client theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "client_id": "550e8400-e29b-41d4-a716-446655440000",
    "client_id_issued_at": 1750000000,
    "client_name": "Example OAuth Client",
    "redirect_uris": ["http://127.0.0.1/oauth/callback"],
    "grant_types": ["authorization_code", "refresh_token"],
    "response_types": ["code"],
    "token_endpoint_auth_method": "none",
    "scope": "emails:send"
  }
  ```

  ```json Confidential client theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "client_id": "550e8400-e29b-41d4-a716-446655440000",
    "client_id_issued_at": 1750000000,
    "client_name": "Example OAuth Client",
    "redirect_uris": ["http://127.0.0.1/oauth/callback"],
    "grant_types": ["authorization_code", "refresh_token"],
    "response_types": ["code"],
    "token_endpoint_auth_method": "client_secret_basic",
    "scope": "emails:send",
    "client_secret": "3vProAFw7...store-this-now...KpQ",
    "client_secret_expires_at": 0
  }
  ```
</ResponseExample>

## Errors

Errors use the standard OAuth shape (`{"error": "...", "error_description": "..."}`) rather than Resend's usual [error format](/docs/api-reference/errors).

| Status | `error`             | When                                                                     |
| ------ | ------------------- | ------------------------------------------------------------------------ |
| `400`  | `invalid_request`   | A required field is missing, malformed, or a redirect URI is disallowed. |
| `400`  | `invalid_scope`     | `scope` includes a value outside the supported scope set.                |
| `429`  | `too_many_requests` | More than 20 registrations from this IP in the last hour.                |


# Revoke Token
Source: https://resend.com/docs/api-reference/oauth/revoke

POST /oauth/revoke
Disconnect a client by revoking its refresh token.

RFC 7009 token revocation. Revoking a refresh token revokes the entire grant: every access and refresh token issued under it stops working.

Access tokens can't be revoked individually. Revoke the grant's refresh token instead. Per RFC 7009, this endpoint always returns `200` with an empty body.

Confidential clients must authenticate the same way they do at the [token endpoint](/docs/api-reference/oauth/token#client-authentication), using `client_secret_basic` or `client_secret_post`. Public clients (`none`) send only `client_id`.

## Body Parameters

<ParamField type="string">
  The refresh token to revoke.
</ParamField>

<ParamField type="string">
  Required, except with `client_secret_basic`, where the `Authorization` header
  already carries it.
</ParamField>

<ParamField type="string">
  Required for a confidential client using `client_secret_post`. Omit for public
  clients and for `client_secret_basic` (send the secret in the `Authorization`
  header instead).
</ParamField>

<ParamField type="string">
  Optional per RFC 7009. If set to `"access_token"`, the request fails: access
  token revocation isn't supported. Any other value (including
  `"refresh_token"`) is accepted and ignored. Unknown hints don't affect
  behavior.
</ParamField>

<RequestExample>
  ```bash Public client theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/oauth/revoke' \
       -H 'Content-Type: application/x-www-form-urlencoded' \
       -d 'client_id=550e8400-e29b-41d4-a716-446655440000&token=JcL7aYfE7S9h3L4qv0o2e1w8m6n5b3x9RkP2tD4uV6Q&token_type_hint=refresh_token'
  ```

  ```bash Client Secret Basic theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/oauth/revoke' \
       -H 'Content-Type: application/x-www-form-urlencoded' \
       -u '550e8400-e29b-41d4-a716-446655440000:CLIENT_SECRET' \
       -d 'token=JcL7aYfE7S9h3L4qv0o2e1w8m6n5b3x9RkP2tD4uV6Q&token_type_hint=refresh_token'
  ```

  ```bash Client Secret Post theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/oauth/revoke' \
       -H 'Content-Type: application/x-www-form-urlencoded' \
       -d 'client_id=550e8400-e29b-41d4-a716-446655440000&client_secret=CLIENT_SECRET&token=JcL7aYfE7S9h3L4qv0o2e1w8m6n5b3x9RkP2tD4uV6Q&token_type_hint=refresh_token'
  ```
</RequestExample>

<ResponseExample>
  ```http Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  HTTP/1.1 200 OK
  ```
</ResponseExample>

## Errors

| Status | `error`           | When                                                                                                                                  |
| ------ | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | `invalid_request` | `token` or `client_id` is missing, `token_type_hint` is `"access_token"`, or the client sent credentials via more than one mechanism. |
| `401`  | `invalid_client`  | Unknown or disabled `client_id`, or a confidential client failed authentication (missing or wrong `client_secret`).                   |


# Revoke Grant
Source: https://resend.com/docs/api-reference/oauth/revoke-grant

DELETE /oauth/grants/:oauth_grant_id
Revoke an OAuth grant for the authenticated team.

Revoking a grant invalidates every access and refresh token issued under it. Any
team API key can revoke any of the team's grants. Returns `404` if the grant
does not exist or was already revoked.

## Path Parameters

<ResendParamField type="string">
  The OAuth grant ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.oauthGrants.revoke(
    '650e8400-e29b-41d4-a716-446655440001',
  );
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _data = resend
      .oauth
      .revoke("650e8400-e29b-41d4-a716-446655440001")
      .await?;

    Ok(())
  }
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X DELETE 'https://api.resend.com/oauth/grants/650e8400-e29b-41d4-a716-446655440001' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend oauth-grants revoke 650e8400-e29b-41d4-a716-446655440001
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "oauth_grant",
    "id": "650e8400-e29b-41d4-a716-446655440001",
    "revoked_at": "2026-04-08T00:11:13.110Z",
    "revoked_reason": "revoked_from_api"
  }
  ```
</ResponseExample>


# Token
Source: https://resend.com/docs/api-reference/oauth/token

POST /oauth/token
Exchange an authorization code for tokens, or refresh an access token.

Handles two grants, selected by the `grant_type` body field: `authorization_code` (with mandatory PKCE) and `refresh_token` (with rotation and reuse detection). Accepts both `application/json` and `application/x-www-form-urlencoded`. Prefer form encoding, since that's what most OAuth libraries send by default.

Access tokens are JWTs signed with `ES256`, valid for 900 seconds. Refresh tokens are opaque strings, valid for 60 days from whenever they were last issued, and rotate on every use.

## Client authentication

How the client proves its identity depends on the `token_endpoint_auth_method` it [registered](/docs/api-reference/oauth/register#param-token-endpoint-auth-method) with:

* **Public clients (`none`)** don't send a secret. PKCE (`code_verifier`) is the only proof. This is the default and covers native, CLI, and other clients that can't keep a secret.
* **Confidential clients** additionally present their `client_secret`, on top of PKCE:
  * `client_secret_basic`: send `client_id` and `client_secret` in the HTTP `Authorization: Basic` header (each URL-encoded, joined with `:`, base64-encoded). With this method `client_id` can be omitted from the body.
  * `client_secret_post`: send `client_secret` as a body parameter alongside `client_id`.

A client must use exactly one mechanism. Sending both a Basic header and a body `client_secret` fails with `invalid_request`.

## PKCE

Before starting the [authorization request](/docs/api-reference/oauth/authorize), generate:

* `code_verifier`: a high-entropy random string, 43–128 characters, from the
  unreserved character set (`A-Z`, `a-z`, `0-9`, `-`, `.`, `_`, `~`). Keep it
  client-side only.
* `code_challenge`: the base64url-encoded SHA-256 hash of `code_verifier`,
  sent during authorization.

```javascript theme={"theme":{"light":"github-light","dark":"vesper"}}
import { createHash, randomBytes } from 'node:crypto';

function base64url(input) {
  return Buffer.from(input).toString('base64url');
}

const codeVerifier = base64url(randomBytes(64));
const codeChallenge = base64url(
  createHash('sha256').update(codeVerifier).digest(),
);
```

## Authorization code grant

### Body Parameters

<ParamField type="string">
  Must be `"authorization_code"`.
</ParamField>

<ParamField type="string">
  Required, except with `client_secret_basic`, where the `Authorization` header
  already carries it.
</ParamField>

<ParamField type="string">
  Required for a confidential client using `client_secret_post`. Omit for public
  clients and for `client_secret_basic` (send the secret in the `Authorization`
  header instead). See [Client authentication](#client-authentication).
</ParamField>

<ParamField type="string">
  The code from the `/oauth/authorize` callback. Single-use: redeeming it twice
  fails with `invalid_grant`. Expires 10 minutes after it was issued.
</ParamField>

<ParamField type="string">
  Must exactly match the `redirect_uri` used in the authorization request.
</ParamField>

<ParamField type="string">
  The original value that
  [code\_challenge](/docs/api-reference/oauth/authorize#param-code-challenge) was
  derived from.
</ParamField>

<RequestExample>
  ```bash Public client theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/oauth/token' \
       -H 'Content-Type: application/x-www-form-urlencoded' \
       -d 'grant_type=authorization_code&client_id=550e8400-e29b-41d4-a716-446655440000&code=AUTHORIZATION_CODE&redirect_uri=http%3A%2F%2F127.0.0.1%3A49152%2Foauth%2Fcallback&code_verifier=CODE_VERIFIER_VALUE'
  ```

  ```bash Client Secret Basic theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/oauth/token' \
       -H 'Content-Type: application/x-www-form-urlencoded' \
       -u '550e8400-e29b-41d4-a716-446655440000:CLIENT_SECRET' \
       -d 'grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=http%3A%2F%2F127.0.0.1%3A49152%2Foauth%2Fcallback&code_verifier=CODE_VERIFIER_VALUE'
  ```

  ```bash Client Secret Post theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/oauth/token' \
       -H 'Content-Type: application/x-www-form-urlencoded' \
       -d 'grant_type=authorization_code&client_id=550e8400-e29b-41d4-a716-446655440000&client_secret=CLIENT_SECRET&code=AUTHORIZATION_CODE&redirect_uri=http%3A%2F%2F127.0.0.1%3A49152%2Foauth%2Fcallback&code_verifier=CODE_VERIFIER_VALUE'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "access_token": "eyJhbGciOiJFUzI1NiIsImtpZCI6Im9hdXRoX2tleSIsInR5cCI6ImF0K2p3dCJ9...",
    "token_type": "Bearer",
    "expires_in": 900,
    "refresh_token": "JcL7aYfE7S9h3L4qv0o2e1w8m6n5b3x9RkP2tD4uV6Q",
    "scope": "emails:send"
  }
  ```
</ResponseExample>

### Body Parameters

<ParamField type="string">
  Must be `"refresh_token"`.
</ParamField>

<ParamField type="string">
  Required, except with `client_secret_basic`, where the `Authorization` header
  already carries it.
</ParamField>

<ParamField type="string">
  Required for a confidential client using `client_secret_post`. Omit for public
  clients and for `client_secret_basic`. See [Client
  authentication](#client-authentication).
</ParamField>

<ParamField type="string" />

<ParamField type="string">
  Optionally narrow the scope of the new access token. Must be a subset of what
  the grant already has. You can't use this to escalate scope.
</ParamField>

<RequestExample>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/oauth/token' \
       -H 'Content-Type: application/x-www-form-urlencoded' \
       -d 'grant_type=refresh_token&client_id=550e8400-e29b-41d4-a716-446655440000&refresh_token=JcL7aYfE7S9h3L4qv0o2e1w8m6n5b3x9RkP2tD4uV6Q'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "access_token": "eyJhbGciOiJFUzI1NiIsImtpZCI6Im9hdXRoX2tleSIsInR5cCI6ImF0K2p3dCJ9...",
    "token_type": "Bearer",
    "expires_in": 900,
    "refresh_token": "N3wRefreshTokenValue...",
    "scope": "emails:send"
  }
  ```
</ResponseExample>

## Errors

| Status | `error`               | When                                                                                                                                                                                           |
| ------ | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | `invalid_request`     | A required field is missing or malformed, or the client sent credentials via more than one mechanism (both a Basic header and a body `client_secret`).                                         |
| `400`  | `invalid_scope`       | Refresh requests a scope outside what the grant already has.                                                                                                                                   |
| `400`  | `invalid_grant`       | The code/refresh token is invalid, expired, already used, or reused after rotation (which also revokes the grant). Also returned when PKCE verification fails or `redirect_uri` doesn't match. |
| `401`  | `invalid_client`      | Unknown or disabled `client_id`, or a confidential client failed authentication (missing or wrong `client_secret`, or `client_id` in the Basic header doesn't match the request).              |
| `400`  | `unauthorized_client` | The client isn't registered for the grant type it's using.                                                                                                                                     |


# Pagination
Source: https://resend.com/docs/api-reference/pagination

Learn how pagination works in the Resend API.

## Overview

Several Resend API endpoints support **cursor-based pagination** to help you efficiently browse through large datasets. You can safely navigate lists with guaranteed stability, even if new objects are created or deleted while you're still requesting pages.

Paginated endpoints responses include:

* `object`: always set to `list`.
* `has_more`: indicates whether there are more elements available.
* `data`: the list of returned items.

You can navigate through the results using the following parameters:

* `limit`: the number of items to return per page.
* `after`: the cursor to use to get the next page of results.
* `before`: the cursor to use to get the previous page of results.

Use the `id` of objects as the cursor for pagination. The cursor itself is *excluded* from the results. For an example, see [pagination strategies below](#strategies).

## Supported endpoints

Existing list endpoints can optionally return paginated results:

* [List Domains](/docs/api-reference/domains/list-domains)
* [List API Keys](/docs/api-reference/api-keys/list-api-keys)
* [List Broadcasts](/docs/api-reference/broadcasts/list-broadcasts)
* [List Segments](/docs/api-reference/segments/list-segments)
* [List Contacts](/docs/api-reference/contacts/list-contacts)
* [List Receiving Emails](/docs/api-reference/emails/list-received-emails)
* [List Receiving Email Attachments](/docs/api-reference/emails/list-received-email-attachments)

<Info>
  Note that for these endpoints, the `limit` parameter is optional. If you do
  not provide a `limit`, all items will be returned in a single response.
</Info>

Newer list endpoints always return paginated results:

* [List Emails](/docs/api-reference/emails/list-emails)
* [List Templates](/docs/api-reference/templates/list-templates)
* [List Topics](/docs/api-reference/topics/list-topics)

## Parameters

All paginated endpoints support the following query parameters:

<ParamField type="number">
  The number of items to return per page. Default is `20`, maximum is `100`, and
  minimum is `1`.
</ParamField>

<ParamField type="string">
  The cursor after which to start retrieving items. To get the next page, use
  the ID of the last item from the current page. This will return the page that
  **starts after** the object with this ID (excluding the passed ID itself).
</ParamField>

<ParamField type="string">
  The cursor before which to start retrieving items. To get the previous page,
  use the ID of the first item from the current page. This will return the page
  that **ends before** the object with this ID (excluding the passed ID itself).
</ParamField>

<Warning>
  You can only use either `after` or `before`, not both simultaneously.
</Warning>

## Response Format

Paginated endpoints return responses in the following format:

```json Response Format theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "object": "list",
  "has_more": true,
  "data": [/* Array of resources */]
}
```

<ResponseField name="object" type="string">
  Always set to `list` for paginated responses.
</ResponseField>

<ResponseField name="has_more" type="boolean">
  Indicates whether there are more items available beyond the current page.
</ResponseField>

<ResponseField name="data" type="array">
  An array containing the actual resources for the current page.
</ResponseField>

## Strategies

### Forward Pagination

To paginate forward through results (newer to older items), use the `after` parameter with the ID of the **last item** from the current page:

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('re_xxxxxxxxx');

  // First page
  const { data: firstPage } = await resend.contacts.list({ limit: 50 });

  // Second page (if has_more is true)
  if (firstPage.has_more) {
    const lastId = firstPage.data[firstPage.data.length - 1].id;
    const { data: secondPage } = await resend.contacts.list({
      limit: 50,
      after: lastId,
    });
  }
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // First page
  $firstPage = $resend->contacts->list(['limit' => 50]);

  // Second page (if has_more is true)
  if ($firstPage['has_more']) {
      $lastId = end($firstPage['data'])['id'];
      $secondPage = $resend->contacts->list([
          'limit' => 50,
          'after' => $lastId
      ]);
  }
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  # First page
  first_page = resend.Contacts.list(limit=50)

  # Second page (if has_more is true)
  if first_page['has_more']:
      last_id = first_page['data'][-1]['id']
      second_page = resend.Contacts.list(limit=50, after=last_id)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = "re_xxxxxxxxx"

  # First page
  first_page = Resend::Contacts.list(limit: 50)

  # Second page (if has_more is true)
  if first_page['has_more']
    last_id = first_page['data'].last['id']
    second_page = Resend::Contacts.list(limit: 50, after: last_id)
  end
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	// First page
  	firstPage, err := client.Contacts.List(&resend.ListContactsRequest{
  		Limit: 50,
  	})

  	// Second page (if has_more is true)
  	if firstPage.HasMore {
  		lastId := firstPage.Data[len(firstPage.Data)-1].ID
  		client.Contacts.List(&resend.ListContactsRequest{
  			Limit: 50,
  			After: lastId,
  		})
  	}
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result, types::ListContactOptions};

  #[tokio::main]
  async fn main() -> Result<()> {
      let resend = Resend::new("re_xxxxxxxxx");

      // First page
      let list_opts = ListContactOptions::default().with_limit(50);
      let first_page = resend.emails.list(list_opts).await?;

      // Second page (if has_more is true)
      if first_page.has_more {
          let last_id = &first_page.data.last().unwrap().id;
          let list_opts = ListContactOptions::default()
              .with_limit(10)
              .list_after(last_id);
          let second_page = resend.contacts.list(list_opts).await?;
      }

      Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          // First page
          ListEmailsResponse firstPage = resend.emails().list(10);

          // Second page (if has_more is true)
          if (firstPage.getHasMore()) {
              String lastId = firstPage.getData().get(firstPage.getData().size() - 1).getId();
              ListContactsResponse secondPage = resend.contacts().list(50, lastId, null);
          }
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;
  using System.Linq;

  IResend resend = ResendClient.Create("re_xxxxxxxxx");

  // First page
  var firstPage = await resend.EmailListAsync( new PaginatedQuery() {
    Limit = 50,
  });

  // Second page (if has_more is true)
  if (firstPage.Content.HasMore)
  {
      var lastId = firstPage.Content.Data.Last().Id;
      var secondPage = await resend.EmailListAsync( new PaginatedQuery() {
        Limit = 50,
        After = lastId.ToString(),
      });
  }
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  # First page
  curl -X GET 'https://api.resend.com/contacts?limit=50' \
       -H 'Authorization: Bearer re_xxxxxxxxx'

  # Second page
  curl -X GET 'https://api.resend.com/contacts?limit=50&after=LAST_ID_FROM_PREVIOUS_PAGE' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```
</CodeGroup>

### Backward Pagination

To paginate backward through results (older to newer items), use the `before` parameter with the ID of the **first item** from the current page (or the most recent ID you have in your system):

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('re_xxxxxxxxx');

  // Start from a specific point and go backward
  const page = await resend.contacts.list({
    limit: 50,
    before: 'some-contact-id',
  });

  if (page.data.has_more) {
    const firstId = page.data.data[0].id;
    const previousPage = await resend.contacts.list({
      limit: 50,
      before: firstId,
    });
  }
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Start from a specific point and go backward
  $page = $resend->contacts->list([
      'limit' => 50,
      'before' => 'some-contact-id'
  ]);

  if ($page['has_more']) {
      $firstId = $page['data'][0]['id'];
      $previousPage = $resend->contacts->list([
          'limit' => 50,
          'before' => $firstId
      ]);
  }
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  # Start from a specific point and go backward
  page = resend.Contacts.list(limit=50, before="some-contact-id")

  if page["has_more"]:
      first_id = page["data"][0]["id"]
      previous_page = resend.Contacts.list(limit=50, before=first_id)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = "re_xxxxxxxxx"

  # Start from a specific point and go backward
  page = Resend::Contacts.list(limit: 50, before: 'some-contact-id')

  if page['has_more']
    first_id = page['data'].first['id']
    previous_page = Resend::Contacts.list(limit: 50, before: first_id)
  end
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	// Start from a specific point and go backward
  	page, err := client.Contacts.List(&resend.ListContactsRequest{
  		Limit:  resend.Int(50),
  		Before: resend.String("some-contact-id"),
  	})

  	if page.HasMore {
  		firstId := page.Data[0].ID
  		client.Contacts.List(&resend.ListContactsRequest{
  			Limit:  resend.Int(50),
  			Before: resend.String(firstId),
  		})
  	}
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result, types::ListContactOptions};

  #[tokio::main]
  async fn main() -> Result<()> {
      let resend = Resend::new("re_xxxxxxxxx");

      // Start from a specific point and go backward
      let list_opts = ListContactOptions::default()
          .with_limit(50)
          .list_before("some-email-id");
      let page = resend.contacts.list(list_opts).await?;

      if page.has_more {
          let first_id = &page.data.first().unwrap().id;
          let list_opts = ListContactOptions::default()
              .with_limit(10)
              .list_before(first_id);
          let previous_page = resend.contacts.list(list_opts).await?;
      }

      Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          // Start from a specific point and go backward
          ListContactsResponse page = resend.contacts().list(50, null, "some-contact-id");

          if (page.getHasMore()) {
              String firstId = page.getData().get(0).getId();
              ListContactsResponse previousPage = resend.contacts().list(50, null, firstId);
          }
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;
  using System.Linq;

  IResend resend = ResendClient.Create("re_xxxxxxxxx");

  // Start from a specific point and go backward
  var page = await resend.EmailListAsync( new PaginatedQuery() {
    Limit = 50,
    Before = "some-email-id",
  });

  if (page.Content.HasMore)
  {
      var firstId = page.Content.Data.First().Id;
      var prevPage = await resend.EmailListAsync( new PaginatedQuery() {
        Limit = 50,
        Before = firstId.ToString(),
      });
  }
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/contacts?limit=50&before=some-contact-id' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```
</CodeGroup>

## Best Practices

<AccordionGroup>
  <Accordion title="Use appropriate page sizes">
    Choose a `limit` that balances performance and usability. Smaller pages are good for real-time applications, while larger pages
    (hundreds of items) work better for bulk processing.
  </Accordion>

  <Accordion title="Handle pagination gracefully">
    Always check the `has_more` field before attempting to fetch additional pages.
    This prevents unnecessary API calls when you've reached the end of the
    dataset.
  </Accordion>

  <Accordion title="Consider rate limits">
    Be mindful of API rate limits when paginating through large datasets.
    Implement appropriate delays or batching strategies if processing many
    pages.
  </Accordion>
</AccordionGroup>

## Error Handling

Pagination requests may return the following validation errors:

| Error              | Description                                         |
| ------------------ | --------------------------------------------------- |
| `validation_error` | Invalid cursor format or limit out of range (1–100) |
| `validation_error` | Both `before` and `after` parameters provided       |

Example error response:

```json Error Response theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "name": "validation_error",
  "statusCode": 422,
  "message": "The pagination limit must be a number between 1 and 100. See https://resend.com/docs/pagination for more information."
}
```


# Usage Limits
Source: https://resend.com/docs/api-reference/rate-limit

Learn about API rate limits, email sending quotas, and contact quotas.

The Resend API enforces three types of limits: **rate limits** control how many API requests you can make per second, **email quotas** control the total number of emails you can send per day and month, and **contact quotas** control how many marketing contacts you can store.

## Rate Limits

### Response Headers

The response headers describe your current rate limit following every request in conformance with the [sixth IETF standard draft](https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-ratelimit-headers-06):

| Header name           | Description                                                 |
| --------------------- | ----------------------------------------------------------- |
| `ratelimit-limit`     | Maximum number of requests allowed within a window.         |
| `ratelimit-remaining` | How many requests you have left within the current window.  |
| `ratelimit-reset`     | How many seconds until the limits are reset.                |
| `retry-after`         | How many seconds to wait before making a follow-up request. |

The default maximum rate limit is **10 requests per second per team**. This limit applies across all API keys associated with your team. This number can be increased for trusted senders upon request. You can view your team's current rate limit on the [Settings Usage page](https://resend.com/settings/usage).

After that, you'll hit the rate limit and receive a `429` response error code. You can find all 429 responses by filtering for 429 at the [Resend Logs page](https://resend.com/logs?status=429).

To prevent this, reduce the rate at which you request the API. This can be done by introducing a queue mechanism or reducing the number of concurrent requests per second. If you have specific requirements, [contact support](https://resend.com/contact) to request a rate increase.

## Email Quotas

### Response Headers

In addition to rate limits, the API returns headers that track your email sending quotas:

| Header name              | Description                                                        |
| ------------------------ | ------------------------------------------------------------------ |
| `x-resend-daily-quota`   | Your used daily email sending quota. Only sent to free plan users. |
| `x-resend-monthly-quota` | Your used monthly email sending quota.                             |

These headers help you monitor your usage and avoid hitting quota limits.

When you exceed your quota limits, you'll receive a `429` response error code with one of the following error types:

* **`daily_quota_exceeded`** - You have reached your daily email quota. [Upgrade your plan](https://resend.com/settings/billing) to remove the daily quota limit or wait until 24 hours have passed.
* **`monthly_quota_exceeded`** - You have reached your monthly email quota. [Upgrade your plan](https://resend.com/settings/billing) to increase the monthly email quota.

Both sent and received emails count towards these quotas. See the full list of [error codes](/docs/api-reference/errors) for more details.

## Contact Quotas

Contact quotas restrict the number of contacts you can store for marketing emails and broadcasts. You can add more contacts beyond your plan's limit, but you won't be able to send broadcasts until you upgrade your plan.

When you attempt to send a broadcast after reaching your contact limit, you'll receive a `403` response error code with a `validation_error` type and the message: "You have reached your contacts quota. Please upgrade your plan to send more emails."

To increase your contact limit, [upgrade your Marketing plan](https://resend.com/settings/billing).


# Create Segment
Source: https://resend.com/docs/api-reference/segments/create-segment

POST /segments
Create a new segment for contacts to be added to.

## Body Parameters

<ParamField type="string">
  The name of the segment you want to create.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.segments.create({
    name: 'Registered Users',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->segments->create([
    'name' => 'Registered Users',
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  params = {
      "name": "Registered Users",
  }

  segment = resend.Segments.create(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    name: "Registered Users",
  }
  segment = Resend::Segments.create(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.CreateSegmentRequest{
  		Name: "Registered Users",
  	}

  	segment, err := client.Segments.CreateWithContext(ctx, params)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(segment)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _segment = resend.segments.create("Registered Users").await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateSegmentOptions options = CreateSegmentOptions.builder()
              .name("Registered Users")
              .build();

          CreateSegmentResponseSuccess response = resend.segments().create(options);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.SegmentCreateAsync( new SegmentData() {
    Name = "Registered Users",
  } );
  Console.WriteLine( "Segment Id={0}", resp.Content );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/segments' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "name": "Registered Users"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend segments create --name "Registered Users"
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "segment",
    "id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "name": "Registered Users"
  }
  ```
</ResponseExample>


# Delete Segment
Source: https://resend.com/docs/api-reference/segments/delete-segment

DELETE /segments/:segment_id
Remove an existing segment.

## Path Parameters

<ResendParamField type="string">
  The Segment ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.segments.remove(
    '78261eea-8f8b-4381-83c6-79fa7120f1cf',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->segments->remove('78261eea-8f8b-4381-83c6-79fa7120f1cf');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  segment = resend.Segments.remove(id='78261eea-8f8b-4381-83c6-79fa7120f1cf')
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Segments.remove("78261eea-8f8b-4381-83c6-79fa7120f1cf")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	segment, err := client.Segments.RemoveWithContext(ctx, "78261eea-8f8b-4381-83c6-79fa7120f1cf")
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(segment)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _segment = resend
      .segments
      .delete("78261eea-8f8b-4381-83c6-79fa7120f1cf")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          RemoveSegmentResponseSuccess response = resend.segments().remove("78261eea-8f8b-4381-83c6-79fa7120f1cf");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.SegmentDeleteAsync( new Guid( "b6d24b8e-af0b-4c3c-be0c-359bbd97381e" ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X DELETE 'https://api.resend.com/segments/78261eea-8f8b-4381-83c6-79fa7120f1cf' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend segments delete 78261eea-8f8b-4381-83c6-79fa7120f1cf
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "segment",
    "id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "deleted": true
  }
  ```
</ResponseExample>


# Retrieve Segment
Source: https://resend.com/docs/api-reference/segments/get-segment

GET /segments/:segment_id
Retrieve a single segment.

## Path Parameters

<ResendParamField type="string">
  The Segment ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.segments.get(
    '78261eea-8f8b-4381-83c6-79fa7120f1cf',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->segments->get('78261eea-8f8b-4381-83c6-79fa7120f1cf');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  segment = resend.Segments.get('78261eea-8f8b-4381-83c6-79fa7120f1cf')
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  segment = Resend::Segments.get("78261eea-8f8b-4381-83c6-79fa7120f1cf")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	segment, err := client.Segments.GetWithContext(ctx, "78261eea-8f8b-4381-83c6-79fa7120f1cf")
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(segment)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _segment = resend
      .segments
      .get("78261eea-8f8b-4381-83c6-79fa7120f1cf")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          GetSegmentResponseSuccess response = resend.segments().get("78261eea-8f8b-4381-83c6-79fa7120f1cf");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.SegmentRetrieveAsync( new Guid( "b6d24b8e-af0b-4c3c-be0c-359bbd97381e" ) );
  Console.WriteLine( "Segment Id={0}", resp.Content.Id );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/segments/78261eea-8f8b-4381-83c6-79fa7120f1cf' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend segments get 78261eea-8f8b-4381-83c6-79fa7120f1cf
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "segment",
    "id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "name": "Registered Users",
    "created_at": "2026-10-06 22:59:55.977+00"
  }
  ```
</ResponseExample>


# Retrieve Metrics
Source: https://resend.com/docs/api-reference/segments/get-segment-metrics

GET /segments/metrics
Retrieve segment metrics.

<Warning>
  Segment metrics are currently in private beta and only available to a limited
  number of users. The response shape might change before GA. [Get in
  touch](https://resend.com/contact) if you're interested in testing this
  feature.

  <span />

  Once you have access, upgrade your Resend SDK to use the methods on this
  page:

  <CodeGroup>
    ```bash Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
    npm install resend@6.19.0-preview-headless-dashboard.7
    ```
  </CodeGroup>
</Warning>

Live contact counts for your account, optionally broken down by segment.
Works across your whole account by default, or scoped to specific segments
via `segment_id`.

<Info>
  `totals` is always the live, current count for your account, or for the
  segments in `segment_id`, if provided.
</Info>

<Info>
  Responses are cached for up to 15 minutes, so requesting the same range again
  may return slightly stale data within that window.
</Info>

## Query Parameters

<ResendParamField type="string[]">
  Comma-separated list of metrics to include in `totals` and `data`. Defaults to
  all of the following: `all_contacts`, `subscribers`, `unsubscribers`.
</ResendParamField>

<ResendParamField type="string[]">
  Comma-separated list of dimensions to break `data` down by. Defaults to
  `[]`, returning only `totals` with no `data`.

  Possible values:

  * `segment`: one row per segment, using its current contact counts.
</ResendParamField>

<ResendParamField type="string[]">
  Comma-separated list of segment IDs. Narrows `totals` (and `data`, when
  requested) to just these segments, without double-counting contacts that
  belong to more than one.
</ResendParamField>

<Info>
  When `dimensions` includes `segment`, `data` is ordered by each segment's
  creation date, newest first.
</Info>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.segments.metrics({
    dimensions: ['segment'],
    metrics: ['all_contacts'],
  });
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/segments/metrics?dimensions=segment&metrics=all_contacts' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "metrics",
    "metrics": ["all_contacts"],
    "dimensions": ["segment"],
    "totals": {
      "all_contacts": 12450
    },
    "data": [
      {
        "id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
        "name": "Registered Users",
        "all_contacts": 4300
      }
    ]
  }
  ```
</ResponseExample>


# List Segment Contacts
Source: https://resend.com/docs/api-reference/segments/list-segment-contacts

GET /segments/:segment_id/contacts
Retrieve a list of contacts in a segment.

## Path Parameters

<ResendParamField type="string">
  The Segment ID.
</ResendParamField>

<QueryParams type="contacts" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.contacts.list({
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->contacts->list([
    'segment_id' => '78261eea-8f8b-4381-83c6-79fa7120f1cf',
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  contacts = resend.Contacts.list('78261eea-8f8b-4381-83c6-79fa7120f1cf')
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _contacts = resend
      .contacts
      .list("78261eea-8f8b-4381-83c6-79fa7120f1cf", ListOptions::default())
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          ListContactsResponseSuccess response = resend.contacts().list("78261eea-8f8b-4381-83c6-79fa7120f1cf");
      }
  }
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/segments/78261eea-8f8b-4381-83c6-79fa7120f1cf/contacts' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend segments contacts 78261eea-8f8b-4381-83c6-79fa7120f1cf
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
        "email": "steve.wozniak@gmail.com",
        "first_name": "Steve",
        "last_name": "Wozniak",
        "created_at": "2026-10-06 23:47:56.678+00",
        "unsubscribed": false
      }
    ]
  }
  ```
</ResponseExample>


# List Segments
Source: https://resend.com/docs/api-reference/segments/list-segments

GET /segments
Retrieve a list of segments.

<QueryParams type="segments" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.segments.list();
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->segments->list();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  segments = resend.Segments.list()
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  segments = Resend::Segments.list
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	segments, err := client.Segments.ListWithContext(ctx)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(segments)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{list_opts::ListOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _segments = resend.segments.list(ListOptions::default()).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          ListSegmentsResponseSuccess response = resend.segments().list();
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.SegmentListAsync();
  Console.WriteLine( "Nr Segments={0}", resp.Content.Data.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/segments' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend segments list
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
        "name": "Registered Users",
        "created_at": "2026-10-06 22:59:55.977+00"
      }
    ]
  }
  ```
</ResponseExample>


# Add Batch Suppressions
Source: https://resend.com/docs/api-reference/suppressions/add-batch-suppressions

POST /suppressions/batch/add
Add up to 100 email addresses to the suppression list at once.

## Body Parameters

<ParamField type="array">
  The email addresses to suppress. Must contain between 1 and 100 email
  addresses.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.suppressions.batch.add({
    emails: ['steve.wozniak@example.com', 'susan.kare@example.com'],
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->suppressions->batch->add([
    'emails' => ['steve.wozniak@example.com', 'susan.kare@example.com'],
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Suppressions.Batch.AddParams = {
    "emails": ["steve.wozniak@example.com", "susan.kare@example.com"],
  }

  resend.Suppressions.Batch.add(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Suppressions::Batch.add(
    emails: ["steve.wozniak@example.com", "susan.kare@example.com"]
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.BatchAddSuppressionsRequest{
  		Emails: []string{"steve.wozniak@example.com", "susan.kare@example.com"},
  	}

  	client.Suppressions.Batch.Add(params)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::BatchAddSuppressionOptions;
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let opts =
      BatchAddSuppressionOptions::from(vec!["steve.wozniak@example.com", "susan.kare@example.com"]);
    let _data = resend.suppressions.batch_add(opts).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;
  import com.resend.services.suppressions.model.AddSuppressionsOptions;
  import java.util.List;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          AddSuppressionsOptions options = AddSuppressionsOptions.builder()
                  .emails(List.of("steve.wozniak@example.com", "susan.kare@example.com"))
                  .build();

          resend.suppressions().batch().add(options);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

  var resp = await resend.SuppressionBatchAddAsync( new[]
  {
      "steve.wozniak@example.com",
      "susan.kare@example.com",
  } );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/suppressions/batch/add' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "emails": ["steve.wozniak@example.com", "susan.kare@example.com"]
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend suppressions batch add --file suppressions.json
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "data": [
      {
        "object": "suppression",
        "id": "e169aa45-1ecf-4183-9955-b1499d5701d3"
      },
      {
        "object": "suppression",
        "id": "520784e2-887d-4c25-b53c-4ad46ad38100"
      }
    ]
  }
  ```
</ResponseExample>


# Add Suppression
Source: https://resend.com/docs/api-reference/suppressions/add-suppression

POST /suppressions
Add an email address to the suppression list.

## Body Parameters

<ParamField type="string">
  The email address to suppress.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.suppressions.add({
    email: 'steve.wozniak@example.com',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->suppressions->add([
    'email' => 'steve.wozniak@example.com',
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Suppressions.AddParams = {
    "email": "steve.wozniak@example.com",
  }

  resend.Suppressions.add(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Suppressions.add(email: "steve.wozniak@example.com")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.AddSuppressionRequest{
  		Email: "steve.wozniak@example.com",
  	}

  	client.Suppressions.Add(params)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::AddSuppressionOptions;
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let opts = AddSuppressionOptions::new().with_email("steve.wozniak@example.com");
    let _data = resend.suppressions.add(opts).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;
  import com.resend.services.suppressions.model.AddSuppressionOptions;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          AddSuppressionOptions options = AddSuppressionOptions.builder()
                  .email("steve.wozniak@example.com")
                  .build();

          resend.suppressions().add(options);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

  var resp = await resend.SuppressionAddAsync( "steve.wozniak@example.com" );
  Console.WriteLine( "Suppression Id={0}", resp.Content );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/suppressions' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "email": "steve.wozniak@example.com"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend suppressions add steve.wozniak@example.com
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "suppression",
    "id": "e169aa45-1ecf-4183-9955-b1499d5701d3"
  }
  ```
</ResponseExample>


# Retrieve Suppression
Source: https://resend.com/docs/api-reference/suppressions/get-suppression

GET /suppressions/:suppression
Retrieve a single suppression by ID or email.

A suppression can be retrieved either by its ID or by the suppressed email
address.

## Path Parameters

<ParamField type="email | id">
  The Suppression ID or email address.
</ParamField>

The `source_id` in the response references the email that triggered the
suppression. For suppressions with a `manual` origin, `source_id` is `null`.

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Retrieve by suppression id
  const { data, error } = await resend.suppressions.get(
    'e169aa45-1ecf-4183-9955-b1499d5701d3',
  );

  // Retrieve by email
  const { data, error } = await resend.suppressions.get(
    'steve.wozniak@example.com',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Retrieve by suppression id
  $resend->suppressions->get(
    'e169aa45-1ecf-4183-9955-b1499d5701d3'
  );

  // Retrieve by email
  $resend->suppressions->get(
    'steve.wozniak@example.com'
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  # Retrieve by suppression id
  resend.Suppressions.get("e169aa45-1ecf-4183-9955-b1499d5701d3")

  # Retrieve by email
  resend.Suppressions.get("steve.wozniak@example.com")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  # Retrieve by suppression id
  Resend::Suppressions.get("e169aa45-1ecf-4183-9955-b1499d5701d3")

  # Retrieve by email
  Resend::Suppressions.get("steve.wozniak@example.com")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	// Retrieve by suppression id
  	client.Suppressions.Get("e169aa45-1ecf-4183-9955-b1499d5701d3")

  	// Retrieve by email
  	client.Suppressions.Get("steve.wozniak@example.com")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _data = resend
      .suppressions
      .get("e169aa45-1ecf-4183-9955-b1499d5701d3")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          // Retrieve by suppression id
          resend.suppressions().get("e169aa45-1ecf-4183-9955-b1499d5701d3");

          // Retrieve by email
          resend.suppressions().get("steve.wozniak@example.com");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

  // Retrieve by suppression id
  await resend.SuppressionRetrieveAsync( "e169aa45-1ecf-4183-9955-b1499d5701d3" );

  // Retrieve by email
  await resend.SuppressionRetrieveAsync( "steve.wozniak@example.com" );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Retrieve by suppression id
  curl -X GET 'https://api.resend.com/suppressions/e169aa45-1ecf-4183-9955-b1499d5701d3' \
       -H 'Authorization: Bearer re_xxxxxxxxx'

  # Retrieve by email
  curl -X GET 'https://api.resend.com/suppressions/steve.wozniak@example.com' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Retrieve by suppression id
  resend suppressions get e169aa45-1ecf-4183-9955-b1499d5701d3

  # Retrieve by email
  resend suppressions get steve.wozniak@example.com
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "suppression",
    "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
    "email": "steve.wozniak@example.com",
    "origin": "bounce",
    "source_id": "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
    "created_at": "2026-10-06 23:47:56.678+00"
  }
  ```
</ResponseExample>


# List Suppressions
Source: https://resend.com/docs/api-reference/suppressions/list-suppressions

GET /suppressions
Show all suppressions.

<QueryParams type="suppressions" />

<ParamField type="bounce | complaint | manual">
  Filter suppressions by origin.

  Possible values:

  * `bounce`: emails suppressed automatically after a bounce
  * `complaint`: emails suppressed due to a user complaint
  * `manual`: emails suppressed by your team manually
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.suppressions.list();
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->suppressions->list();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Suppressions.list()
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Suppressions.list
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Suppressions.List(&resend.ListSuppressionsOptions{})
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result, list_opts::ListOptions};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _data = resend.suppressions.list(ListOptions::default()).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          resend.suppressions().list();
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

  await resend.SuppressionListAsync();
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/suppressions' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend suppressions list
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
        "email": "steve.wozniak@example.com",
        "origin": "manual",
        "source_id": null,
        "created_at": "2026-10-06 23:47:56.678+00"
      },
      {
        "id": "520784e2-887d-4c25-b53c-4ad46ad38100",
        "email": "susan.kare@example.com",
        "origin": "bounce",
        "source_id": "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
        "created_at": "2026-10-07 08:12:03.412+00"
      }
    ]
  }

  // The `source_id` in the response references the email that triggered the suppression. For suppressions with a `manual` origin, `source_id` is `null`.
  ```
</ResponseExample>


# Remove Batch Suppressions
Source: https://resend.com/docs/api-reference/suppressions/remove-batch-suppressions

POST /suppressions/batch/remove
Remove up to 100 suppressions from the suppression list at once.

## Body Parameters

Provide either `emails` or `ids`, but not both.

<ParamField type="array">
  The email addresses to remove from the suppression list. Must contain between
  1 and 100 email addresses.
</ParamField>

<ParamField type="array">
  The suppression IDs to remove from the suppression list. Must contain between
  1 and 100 IDs.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Remove by suppression ids
  const { data, error } = await resend.suppressions.batch.remove({
    ids: ['e169aa45-1ecf-4183-9955-b1499d5701d3'],
  });

  // Remove by emails
  const { data, error } = await resend.suppressions.batch.remove({
    emails: ['steve.wozniak@example.com', 'susan.kare@example.com'],
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Remove by suppression ids
  $resend->suppressions->batch->remove([
    'ids' => ['e169aa45-1ecf-4183-9955-b1499d5701d3'],
  ]);

  // Remove by emails
  $resend->suppressions->batch->remove([
    'emails' => ['steve.wozniak@example.com', 'susan.kare@example.com'],
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  # Remove by suppression ids
  ids_params: resend.Suppressions.Batch.RemoveParams = {
    "ids": ["e169aa45-1ecf-4183-9955-b1499d5701d3"],
  }

  resend.Suppressions.Batch.remove(ids_params)

  # Remove by emails
  emails_params: resend.Suppressions.Batch.RemoveParams = {
    "emails": ["steve.wozniak@example.com", "susan.kare@example.com"],
  }

  resend.Suppressions.Batch.remove(emails_params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  # Remove by suppression ids
  Resend::Suppressions::Batch.remove(
    ids: ["e169aa45-1ecf-4183-9955-b1499d5701d3"]
  )

  # Remove by emails
  Resend::Suppressions::Batch.remove(
    emails: ["steve.wozniak@example.com", "susan.kare@example.com"]
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	// Remove by suppression ids
  	client.Suppressions.Batch.Remove(&resend.BatchRemoveSuppressionsRequest{
  		Ids: []string{"e169aa45-1ecf-4183-9955-b1499d5701d3"},
  	})

  	// Remove by emails
  	client.Suppressions.Batch.Remove(&resend.BatchRemoveSuppressionsRequest{
  		Emails: []string{"steve.wozniak@example.com", "susan.kare@example.com"},
  	})
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result, types::BatchRemoveSuppressionOptions};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    // Remove by email
    let opt_emails = BatchRemoveSuppressionOptions::new()
      .add_emails(vec!["steve.wozniak@example.com", "susan.kare@example.com"]);
    let _data = resend.suppressions.batch_remove(opt_emails).await?;

    // Remove by id
    let opt_ids =
      BatchRemoveSuppressionOptions::new().add_ids(vec!["e169aa45-1ecf-4183-9955-b1499d5701d3"]);

    let _data = resend.suppressions.batch_remove(opt_ids).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;
  import com.resend.services.suppressions.model.RemoveSuppressionsOptions;
  import java.util.List;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          // Remove by suppression ids
          RemoveSuppressionsOptions byIds = RemoveSuppressionsOptions.builder()
                  .ids(List.of("e169aa45-1ecf-4183-9955-b1499d5701d3"))
                  .build();

          resend.suppressions().batch().remove(byIds);

          // Remove by emails
          RemoveSuppressionsOptions byEmails = RemoveSuppressionsOptions.builder()
                  .emails(List.of("steve.wozniak@example.com", "susan.kare@example.com"))
                  .build();

          resend.suppressions().batch().remove(byEmails);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

  // Remove by suppression ids
  await resend.SuppressionBatchRemoveAsync( new[]
  {
      new Guid( "e169aa45-1ecf-4183-9955-b1499d5701d3" ),
  } );

  // Remove by emails
  await resend.SuppressionBatchRemoveAsync( new[]
  {
      "steve.wozniak@example.com",
      "susan.kare@example.com",
  } );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Remove by suppression ids
  curl -X POST 'https://api.resend.com/suppressions/batch/remove' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "ids": ["e169aa45-1ecf-4183-9955-b1499d5701d3"]
  }'

  # Remove by emails
  curl -X POST 'https://api.resend.com/suppressions/batch/remove' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "emails": ["steve.wozniak@example.com", "susan.kare@example.com"]
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Remove by email
  resend suppressions batch remove --file suppressions.json

  # Remove by id
  resend suppressions batch remove --file suppression-ids.json --ids
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "data": [
      {
        "object": "suppression",
        "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
        "deleted": true
      }
    ]
  }
  ```
</ResponseExample>


# Remove Suppression
Source: https://resend.com/docs/api-reference/suppressions/remove-suppression

DELETE /suppressions/:suppression
Remove a single suppression by ID or email.

## Path Parameters

<ParamField type="email | id">
  The Suppression ID or email address.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Remove by suppression id
  const { data, error } = await resend.suppressions.remove(
    'e169aa45-1ecf-4183-9955-b1499d5701d3',
  );

  // Remove by email
  const { data, error } = await resend.suppressions.remove(
    'steve.wozniak@example.com',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Remove by suppression id
  $resend->suppressions->remove(
    'e169aa45-1ecf-4183-9955-b1499d5701d3'
  );

  // Remove by email
  $resend->suppressions->remove(
    'steve.wozniak@example.com'
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  # Remove by suppression id
  resend.Suppressions.remove("e169aa45-1ecf-4183-9955-b1499d5701d3")

  # Remove by email
  resend.Suppressions.remove("steve.wozniak@example.com")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  # Remove by suppression id
  Resend::Suppressions.remove("e169aa45-1ecf-4183-9955-b1499d5701d3")

  # Remove by email
  Resend::Suppressions.remove("steve.wozniak@example.com")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	// Remove by suppression id
  	client.Suppressions.Remove("e169aa45-1ecf-4183-9955-b1499d5701d3")

  	// Remove by email
  	client.Suppressions.Remove("steve.wozniak@example.com")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    // Remove by suppression id
    let _data = resend
      .suppressions
      .remove("e169aa45-1ecf-4183-9955-b1499d5701d3")
      .await?;

    // Remove by email
    let _data = resend
      .suppressions
      .remove("steve.wozniak@example.com")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          // Remove by suppression id
          resend.suppressions().remove("e169aa45-1ecf-4183-9955-b1499d5701d3");

          // Remove by email
          resend.suppressions().remove("steve.wozniak@example.com");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

  // Remove by suppression id
  await resend.SuppressionRemoveAsync( "e169aa45-1ecf-4183-9955-b1499d5701d3" );

  // Remove by email
  await resend.SuppressionRemoveAsync( "steve.wozniak@example.com" );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Remove by suppression id
  curl -X DELETE 'https://api.resend.com/suppressions/e169aa45-1ecf-4183-9955-b1499d5701d3' \
       -H 'Authorization: Bearer re_xxxxxxxxx'

  # Remove by email
  curl -X DELETE 'https://api.resend.com/suppressions/steve.wozniak@example.com' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Remove by suppression id
  resend suppressions delete e169aa45-1ecf-4183-9955-b1499d5701d3

  # Remove by email
  resend suppressions delete steve.wozniak@example.com
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "suppression",
    "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
    "deleted": true
  }
  ```
</ResponseExample>


# Create Template
Source: https://resend.com/docs/api-reference/templates/create-template

POST /templates
Create a new template with optional variables.

## Body Parameters

<ParamField type="string">
  The name of the template.
</ParamField>

<ParamField type="string">
  The HTML version of the template.
</ParamField>

<ParamField type="string">
  The alias of the template.
</ParamField>

<ParamField type="string">
  Sender email address.

  To include a friendly name, use the format `"Your Name <sender@domain.com>"`.

  If provided, this value can be overridden when sending an email using the template.
</ParamField>

<ParamField type="string">
  Default email subject.

  This value can be overridden when sending an email using the template.
</ParamField>

<ResendParamField type="string | string[]">
  Default Reply-to email address. For multiple addresses, send as an array of strings.

  This value can be overridden when sending an email using the template.
</ResendParamField>

<ParamField type="string">
  The plain text version of the message.

  <Info>
    If not provided, the HTML will be used to generate a plain text version. You can opt out of this behavior by setting value to an empty string.
  </Info>
</ParamField>

<ParamField type="React.ReactNode">
  The React component used to write the template. *Only available in the Node.js
  SDK.*
</ParamField>

<ParamField type="array">
  The array of variables used in the template. Each template may contain up to 50 variables.

  Each variable is an object with the following properties:

  <Expandable title="properties">
    <ParamField type="string">
      The key of the variable. We recommend capitalizing the key (e.g. `PRODUCT_NAME`). The following variable names are reserved and cannot be used:
      `FIRST_NAME`, `LAST_NAME`, `EMAIL`, `RESEND_UNSUBSCRIBE_URL`, `contact`, and `this`.
    </ParamField>

    <ParamField type="'string' | 'number'">
      The type of the variable.

      Can be `'string'` or `'number'`
    </ParamField>

    <ResendParamField type="string | number">
      The fallback value of the variable. The value must match the type of the variable.

      If no fallback value is provided, you must provide a value for the variable when sending an email using the template.
    </ResendParamField>
  </Expandable>

  <Info>
    Before you can use a template, you must publish it first. To publish a
    template, use the [Templates dashboard](https://resend.com/templates) or
    [publish template API](/docs/api-reference/templates/publish-template).

    [Learn more about Templates](/docs/dashboard/templates/introduction).
  </Info>
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.templates.create({
    name: 'order-confirmation',
    html: '<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>',
    variables: [
      {
        key: 'PRODUCT',
        type: 'string',
        fallbackValue: 'item',
      },
      {
        key: 'PRICE',
        type: 'number',
        fallbackValue: 25,
      }
    ],
  });

  // Or create and publish a template in one step
  await resend.templates.create({ ... }).publish();
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->templates->create([
    'name' => 'order-confirmation',
    'html' => '<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>',
    'variables' => [
      [
        'key' => 'PRODUCT',
        'type' => 'string',
        'fallback_value' => 'item',
      ],
      [
        'key' => 'PRICE',
        'type' => 'number',
        'fallback_value' => 25,
      ]
    ],
  ]);
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Templates.create({
      "name": "order-confirmation",
      "html": "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
      "variables": [
          {
              "key": "PRODUCT",
              "type": "string",
              "fallback_value": "item",
          },
          {
              "key": "PRICE",
              "type": "number",
              "fallback_value": 25,
          }
      ],
  })
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Templates.create(
    name: "order-confirmation",
    html: "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
    variables: [
      {
        key: "PRODUCT",
        type: "string",
        fallback_value: "item"
      },
      {
        key: "PRICE",
        type: "number",
        fallback_value: 25
      }
    ]
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Templates.CreateWithContext(context.TODO(), &resend.CreateTemplateRequest{
  		Name: "order-confirmation",
  		Html: "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
  		Variables: []*resend.TemplateVariable{
  			{
  				Key:           "PRODUCT",
  				Type:          resend.VariableTypeString,
  				FallbackValue: "item",
  			},
  			{
  				Key:           "PRICE",
  				Type:          resend.VariableTypeNumber,
  				FallbackValue: 25,
  			},
  		},
  	})
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{
    types::{CreateTemplateOptions, Variable, VariableType},
    Resend, Result,
  };

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let name = "order-confirmation";
    let html = "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>";

    let variables = [
      Variable::new("PRODUCT", VariableType::String).with_fallback("item"),
      Variable::new("PRICE", VariableType::Number).with_fallback(25)
    ];

    let opts = CreateTemplateOptions::new(name, html).with_variables(&variables);
    let template = resend.templates.create(opts).await?;

    let _published = resend.templates.publish(&template.id).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateTemplateOptions params = CreateTemplateOptions.builder()
                  .name("order-confirmation")
                  .html("<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>")
                  .addVariable(new Variable("PRODUCT", VariableType.STRING, "item"))
                  .addVariable(new Variable("PRICE", VariableType.NUMBER, 25))
                  .build();

          CreateTemplateResponseSuccess data = resend.templates().create(params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create("re_xxxxxxxxx");

  var variables = new List<TemplateVariable>()
  {
    new TemplateVariable() {
      Key = "PRODUCT",
      Type = TemplateVariableType.String,
      Default = "item",
    },
    new TemplateVariable() {
      Key = "PRICE",
      Type = TemplateVariableType.Number,
      Default = 25,
    }
  };

  var resp = await resend.TemplateCreateAsync(
    new TemplateData()
    {
      Name = "welcome-email",
      HtmlBody = "<strong>Hey, {{{PRODUCT}}}, you are {{{PRICE}}} years old.</strong>",
      Variables = variables,
    }
  );

  Console.WriteLine($"Template Id={resp.Content}");
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/templates' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "name": "order-confirmation",
    "html": "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
    "variables": [
      {
        "key": "PRODUCT",
        "type": "string",
        "fallback_value": "item"
      },
      {
        "key": "PRICE",
        "type": "number",
        "fallback_value": 25
      }
    ]
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend templates create \
    --name order-confirmation \
    --html "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>" \
    --var PRODUCT:string:item \
    --var PRICE:number:25
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
    "object": "template"
  }
  ```
</ResponseExample>


# Delete Template
Source: https://resend.com/docs/api-reference/templates/delete-template

DELETE /templates/:template_id
Delete a template.

## Path Parameters

<ParamField type="string">
  The ID or alias of the template to delete.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.templates.remove(
    '34a080c9-b17d-4187-ad80-5af20266e535',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->templates->remove('34a080c9-b17d-4187-ad80-5af20266e535');
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Templates.remove("34a080c9-b17d-4187-ad80-5af20266e535")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Templates.remove("34a080c9-b17d-4187-ad80-5af20266e535")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Templates.RemoveWithContext(
  		context.TODO(),
  		"34a080c9-b17d-4187-ad80-5af20266e535",
  	)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _deleted = resend
      .templates
      .delete("34a080c9-b17d-4187-ad80-5af20266e535")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          DeleteTemplateResponseSuccess data = resend.templates().remove("34a080c9-b17d-4187-ad80-5af20266e535");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.TemplateDeleteAsync( new Guid( "34a080c9-b17d-4187-ad80-5af20266e535" ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X DELETE 'https://api.resend.com/templates/34a080c9-b17d-4187-ad80-5af20266e535' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend templates delete 34a080c9-b17d-4187-ad80-5af20266e535
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "template",
    "id": "34a080c9-b17d-4187-ad80-5af20266e535",
    "deleted": true
  }
  ```
</ResponseExample>


# Duplicate Template
Source: https://resend.com/docs/api-reference/templates/duplicate-template

POST /templates/:template_id/duplicate
Duplicate a template.

## Path Parameters

<ParamField type="string">
  The ID or alias of the template to duplicate.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.templates.duplicate(
    '34a080c9-b17d-4187-ad80-5af20266e535',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->templates->duplicate('34a080c9-b17d-4187-ad80-5af20266e535');
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Templates.duplicate("34a080c9-b17d-4187-ad80-5af20266e535")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Templates.duplicate("34a080c9-b17d-4187-ad80-5af20266e535")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Templates.DuplicateWithContext(
  		context.TODO(),
  		"34a080c9-b17d-4187-ad80-5af20266e535",
  	)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _duplicated = resend
      .templates
      .duplicate("34a080c9-b17d-4187-ad80-5af20266e535")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          DuplicateTemplateResponseSuccess data = resend.templates().duplicate("34a080c9-b17d-4187-ad80-5af20266e535");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.TemplateDuplicateAsync( new Guid( "34a080c9-b17d-4187-ad80-5af20266e535" ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/templates/34a080c9-b17d-4187-ad80-5af20266e535/duplicate' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend templates duplicate 34a080c9-b17d-4187-ad80-5af20266e535
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "template",
    "id": "e169aa45-1ecf-4183-9955-b1499d5701d3"
  }
  ```
</ResponseExample>


# Get Template
Source: https://resend.com/docs/api-reference/templates/get-template

GET /templates/:template_id
Get a template by ID.

## Path Parameters

<ParamField type="string">
  The ID or alias of the template to get.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.templates.get(
    '34a080c9-b17d-4187-ad80-5af20266e535',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->templates->get('34a080c9-b17d-4187-ad80-5af20266e535');
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Templates.get("34a080c9-b17d-4187-ad80-5af20266e535")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Templates.get("34a080c9-b17d-4187-ad80-5af20266e535")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Templates.GetWithContext(
  		context.TODO(),
  		"34a080c9-b17d-4187-ad80-5af20266e535",
  	)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _template = resend
      .templates
      .get("34a080c9-b17d-4187-ad80-5af20266e535")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          GetTemplateResponseSuccess data = resend.templates().get("34a080c9-b17d-4187-ad80-5af20266e535");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var res = await resend.TemplateRetrieveAsync( new Guid( "34a080c9-b17d-4187-ad80-5af20266e535" ) );
  Console.WriteLine( "Template Name={0}", res.Content.Name );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/templates/34a080c9-b17d-4187-ad80-5af20266e535' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend templates get 34a080c9-b17d-4187-ad80-5af20266e535
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "template",
    "id": "34a080c9-b17d-4187-ad80-5af20266e535",
    "current_version_id": "b2693018-7abb-4b4b-b4cb-aadf72dc06bd",
    "alias": "reset-password",
    "name": "reset-password",
    "created_at": "2026-10-06 23:47:56.678+00",
    "updated_at": "2026-10-06 23:47:56.678+00",
    "status": "published",
    "published_at": "2026-10-06 23:47:56.678+00",
    "from": "John Doe <john.doe@example.com>",
    "subject": "Hello, world!",
    "reply_to": null,
    "html": "<h1>Hello, world!</h1>",
    "text": "Hello, world!",
    "variables": [
      {
        "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
        "key": "user_name",
        "type": "string",
        "fallback_value": "John Doe",
        "created_at": "2026-10-06 23:47:56.678+00",
        "updated_at": "2026-10-06 23:47:56.678+00"
      }
    ],
    "has_unpublished_versions": true
  }
  ```
</ResponseExample>


# List Templates
Source: https://resend.com/docs/api-reference/templates/list-templates

GET /templates
List all templates.

By default, the API will return the most recent 20 templates. You can optionally use the `limit` parameter to return a different number of templates or control the pagination of the results with the `after` or `before` parameters.

<QueryParams type="templates" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.templates.list({
    limit: 2,
    after: '34a080c9-b17d-4187-ad80-5af20266e535',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->templates->list([
    'limit' => 2,
    'after' => '34a080c9-b17d-4187-ad80-5af20266e535'
  ]);
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Templates.list({
      "limit": 2,
      "after": "34a080c9-b17d-4187-ad80-5af20266e535",
  })
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Templates.list(
    limit: 2,
    after: "34a080c9-b17d-4187-ad80-5af20266e535"
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Templates.ListWithContext(context.TODO(), &resend.ListOptions{
  		Limit: 2,
  		After: "34a080c9-b17d-4187-ad80-5af20266e535",
  	})
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{list_opts::ListOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let list_opts = ListOptions::default()
      .with_limit(2)
      .list_after("34a080c9-b17d-4187-ad80-5af20266e535");

    let _list = resend.templates.list(list_opts).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          ListParams params = ListParams.builder()
              .limit(2)
              .after("34a080c9-b17d-4187-ad80-5af20266e535")
              .build();

          ListTemplatesResponseSuccess data = resend.templates().list(params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.TemplateListAsync();
  Console.WriteLine( "Nr Templates={0}", resp.Content.Data.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/templates?limit=2&after=34a080c9-b17d-4187-ad80-5af20266e535' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend templates list
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "data": [
      {
        "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
        "name": "reset-password",
        "status": "draft",
        "published_at": null,
        "created_at": "2026-10-06 23:47:56.678+00",
        "updated_at": "2026-10-06 23:47:56.678+00",
        "alias": "reset-password"
      },
      {
        "id": "b7f9c2e1-1234-4abc-9def-567890abcdef",
        "name": "welcome-message",
        "status": "published",
        "published_at": "2026-10-06 23:47:56.678+00",
        "created_at": "2026-10-06 23:47:56.678+00",
        "updated_at": "2026-10-06 23:47:56.678+00",
        "alias": "welcome-message"
      }
    ],
    "has_more": false
  }
  ```
</ResponseExample>


# Publish Template
Source: https://resend.com/docs/api-reference/templates/publish-template

POST /templates/:template_id/publish
Publish a template.

## Path Parameters

<ParamField type="string">
  The ID or alias of the template to publish.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.templates.publish(
    '34a080c9-b17d-4187-ad80-5af20266e535',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->templates->publish('34a080c9-b17d-4187-ad80-5af20266e535');
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Templates.publish("34a080c9-b17d-4187-ad80-5af20266e535")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Templates.publish("34a080c9-b17d-4187-ad80-5af20266e535")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Templates.PublishWithContext(
  		context.TODO(),
  		"34a080c9-b17d-4187-ad80-5af20266e535",
  	)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _published = resend
      .templates
      .publish("34a080c9-b17d-4187-ad80-5af20266e535")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          PublishTemplateResponseSuccess data = resend.templates().publish("34a080c9-b17d-4187-ad80-5af20266e535");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.TemplatePublishAsync( new Guid( "34a080c9-b17d-4187-ad80-5af20266e535" ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/templates/34a080c9-b17d-4187-ad80-5af20266e535/publish' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend templates publish 34a080c9-b17d-4187-ad80-5af20266e535
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "template",
    "id": "34a080c9-b17d-4187-ad80-5af20266e535"
  }
  ```
</ResponseExample>


# Update Template
Source: https://resend.com/docs/api-reference/templates/update-template

PATCH /templates/:template_id
Update a template.

## Path Parameters

<ParamField type="string">
  The ID or alias of the template to duplicate.
</ParamField>

## Body Parameters

<ParamField type="string">
  The name of the template.
</ParamField>

<ParamField type="string">
  The HTML version of the template.
</ParamField>

<ParamField type="string">
  The alias of the template.
</ParamField>

<ParamField type="string">
  Sender email address.

  To include a friendly name, use the format `"Your Name <sender@domain.com>"`.

  If provided, this value can be overridden when sending an email using the template.
</ParamField>

<ParamField type="string">
  Default email subject.

  This value can be overridden when sending an email using the template.
</ParamField>

<ResendParamField type="string | string[]">
  Default Reply-to email address. For multiple addresses, send as an array of strings.

  This value can be overridden when sending an email using the template.
</ResendParamField>

<ParamField type="string">
  The plain text version of the message.

  <Info>
    If not provided, the HTML will be used to generate a plain text version. You can opt out of this behavior by setting value to an empty string.
  </Info>
</ParamField>

<ParamField type="React.ReactNode">
  The React component used to write the template. *Only available in the Node.js
  SDK.*
</ParamField>

<ParamField type="array">
  The array of variables used in the template. Each template may contain up to 50 variables.

  Each variable is an object with the following properties:

  <Expandable title="properties">
    <ParamField type="string">
      The key of the variable. We recommend capitalizing the key (e.g. `PRODUCT_NAME`). The following variable names are reserved and cannot be used:
      `FIRST_NAME`, `LAST_NAME`, `EMAIL`, `RESEND_UNSUBSCRIBE_URL`, `contact`, and `this`.
    </ParamField>

    <ParamField type="'string' | 'number'">
      The type of the variable.

      Can be `'string'` or `'number'`
    </ParamField>

    <ResendParamField type="string | number">
      The fallback value of the variable. The value must match the type of the variable.

      If no fallback value is provided, you must provide a value for the variable when sending an email using the template.
    </ResendParamField>
  </Expandable>

  <Info>
    Before you can use a template, you must publish it first. To publish a
    template, use the [Templates dashboard](https://resend.com/templates) or
    [publish template API](/docs/api-reference/templates/publish-template).

    [Learn more about Templates](/docs/dashboard/templates/introduction).
  </Info>
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.templates.update(
    '34a080c9-b17d-4187-ad80-5af20266e535',
    {
      name: 'order-confirmation',
      html: '<p>Total: {{{PRICE}}}</p><p>Name: {{{PRODUCT}}}</p>',
    },
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->templates->update('34a080c9-b17d-4187-ad80-5af20266e535', [
    'name' => 'order-confirmation',
    'html' => '<p>Total: {{{PRICE}}}</p><p>Name: {{{PRODUCT}}}</p>',
  ]);
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Templates.update({
      "id": "34a080c9-b17d-4187-ad80-5af20266e535",
      "name": "order-confirmation",
      "html": "<p>Total: {{{PRICE}}}</p><p>Name: {{{PRODUCT}}}</p>",
  })
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Templates.update("34a080c9-b17d-4187-ad80-5af20266e535", {
    name: "order-confirmation",
    html: "<p>Total: {{{PRICE}}}</p><p>Name: {{{PRODUCT}}}</p>"
  })
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Templates.UpdateWithContext(context.TODO(), "34a080c9-b17d-4187-ad80-5af20266e535", &resend.UpdateTemplateRequest{
  		Name: "order-confirmation",
  		Html: "<p>Total: {{{PRICE}}}</p><p>Name: {{{PRODUCT}}}</p>",
  	})
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{
    types::UpdateTemplateOptions,
    Resend, Result,
  };

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let name = "order-confirmation";
    let html = "<p>Total: {{{PRICE}}}</p><p>Name: {{{PRODUCT}}}</p>";

    let update = UpdateTemplateOptions::new(name, html);

    let _template = resend
      .templates
      .update("34a080c9-b17d-4187-ad80-5af20266e535", update)
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          UpdateTemplateOptions params = UpdateTemplateOptions.builder()
                  .name("order-confirmation")
                  .html("<p>Total: {{{PRICE}}}</p><p>Name: {{{PRODUCT}}}</p>")
                  .build();

          UpdateTemplateResponseSuccess data = resend.templates().update("34a080c9-b17d-4187-ad80-5af20266e535", params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.TemplateUpdateAsync(
      templateId: new Guid( "e169aa45-1ecf-4183-9955-b1499d5701d3" ),
      new TemplateData()
      {
          HtmlBody = "<p>Total: {{{PRICE}}}</p><p>Name: {{{PRODUCT}}}</p>",
      }
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X PATCH 'https://api.resend.com/templates/34a080c9-b17d-4187-ad80-5af20266e535' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "name": "order-confirmation",
    "html": "<p>Total: {{{PRICE}}}</p><p>Name: {{{PRODUCT}}}</p>"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend templates update 34a080c9-b17d-4187-ad80-5af20266e535 \
    --name order-confirmation \
    --html "<p>Total: {{{PRICE}}}</p><p>Name: {{{PRODUCT}}}</p>"
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "template",
    "id": "34a080c9-b17d-4187-ad80-5af20266e535"
  }
  ```
</ResponseExample>


# Create Topic
Source: https://resend.com/docs/api-reference/topics/create-topic

POST /topics
Create and email topics to segment your audience.

## Body Parameters

<ParamField type="string">
  The topic name. Max length is `50` characters.
</ParamField>

<ResendParamField type="string">
  The default subscription preference for new contacts. Possible values:
  `opt_in` or `opt_out`.

  <Note>
    This value cannot be changed later.
  </Note>
</ResendParamField>

<ParamField type="string">
  The topic description. Max length is `200` characters.
</ParamField>

<ResendParamField type="string">
  The visibility of the topic on the unsubscribe page. Possible values: `public` or `private`.

  * `private`: only contacts who are opted in to the topic can see it on the unsubscribe page.
  * `public`: all contacts can see the topic on the unsubscribe page.

  If not specified, defaults to `private`.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.topics.create({
    name: 'Weekly Newsletter',
    defaultSubscription: 'opt_in',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->topics->create([
    'name' => 'Weekly Newsletter',
    'default_subscription' => 'opt_in',
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Topics.create({
      "name": "Weekly Newsletter",
      "default_subscription": "opt_in",
      "description": "Subscribe to our weekly newsletter for updates",
  })
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Topics.create(
    name: "Weekly Newsletter",
    default_subscription: "opt_in"
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Topics.CreateWithContext(context.TODO(), &resend.CreateTopicRequest{
  		Name:                "Weekly Newsletter",
  		DefaultSubscription: resend.DefaultSubscriptionOptIn,
  	})
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{
    types::{CreateTopicOptions, SubscriptionType},
    Resend, Result,
  };

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let opts = CreateTopicOptions::new("Weekly Newsletter", SubscriptionType::OptIn);
    let _topic = resend.topics.create(opts).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      CreateTopicOptions createTopicOptions = CreateTopicOptions.builder()
        .name("Weekly Newsletter")
        .defaultSubscription("opt_in")
        .build();

      CreateTopicResponseSuccess response = resend.topics().create(createTopicOptions);
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.TopicCreateAsync( new TopicData() {
    Name = "Weekly Newsletter",
    Description = "Weekly newsletter for our subscribers",
    SubscriptionDefault = SubscriptionType.OptIn,
  } );
  Console.WriteLine( "Topic Id={0}", resp.Content );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/topics' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "name": "Weekly Newsletter",
    "default_subscription": "opt_in"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend topics create --name "Weekly Newsletter" --default-subscription opt_in
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "topic",
    "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e"
  }
  ```
</ResponseExample>


# Delete Topic
Source: https://resend.com/docs/api-reference/topics/delete-topic

DELETE /topics/:topic_id
Remove an existing topic.

## Path Parameters

<ResendParamField type="string">
  The topic ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.topics.remove(
    'b6d24b8e-af0b-4c3c-be0c-359bbd97381e',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->topics->remove('b6d24b8e-af0b-4c3c-be0c-359bbd97381e');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Topics.remove(id="b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Topics.remove("b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Topics.RemoveWithContext(
  		context.TODO(),
  		"b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
  	)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _deleted = resend.topics.delete("delete").await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      RemoveTopicResponseSuccess response = resend.topics().remove("b6d24b8e-af0b-4c3c-be0c-359bbd97381e");
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.TopicDeleteAsync( new Guid( "b6d24b8e-af0b-4c3c-be0c-359bbd97381e" ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X DELETE 'https://api.resend.com/topics/b6d24b8e-af0b-4c3c-be0c-359bbd97381e' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend topics delete b6d24b8e-af0b-4c3c-be0c-359bbd97381e
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "topic",
    "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
    "deleted": true
  }
  ```
</ResponseExample>


# Retrieve Topic
Source: https://resend.com/docs/api-reference/topics/get-topic

GET /topics/:topic_id
Retrieve a topic by its ID.

## Path Parameters

<ResendParamField type="string">
  The Topic ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.topics.get(
    'b6d24b8e-af0b-4c3c-be0c-359bbd97381e',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->topics->get('b6d24b8e-af0b-4c3c-be0c-359bbd97381e');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Topics.get("b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Topics.get("b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Topics.GetWithContext(
  		context.TODO(),
  		"b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
  	)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _topic = resend
      .topics
      .get("b6d24b8e-af0b-4c3c-be0c-359bbd97381e")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      GetTopicResponseSuccess topic = resend.topics().get("b6d24b8e-af0b-4c3c-be0c-359bbd97381e");
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.TopicRetrieveAsync( new Guid( "b6d24b8e-af0b-4c3c-be0c-359bbd97381e" ) );
  Console.WriteLine( "Topic Id={0}", resp.Content.Id );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/topics/b6d24b8e-af0b-4c3c-be0c-359bbd97381e' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend topics get b6d24b8e-af0b-4c3c-be0c-359bbd97381e
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "topic",
    "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
    "name": "Weekly Newsletter",
    "description": "Weekly newsletter for our subscribers",
    "default_subscription": "opt_in",
    "visibility": "public",
    "created_at": "2026-04-08 00:11:13.110779+00"
  }
  ```
</ResponseExample>


# List Topics
Source: https://resend.com/docs/api-reference/topics/list-topics

GET /topics
Retrieve a list of topics for the authenticated user.

<QueryParams type="topics" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.topics.list();
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->topics->list();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Topics.list()
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Topics.list()
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Topics.ListWithContext(context.TODO(), nil)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{list_opts::ListOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _list = resend.topics.list(ListOptions::default()).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      ListTopicsResponseSuccess response = resend.topics().list();
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.TopicListAsync();
  Console.WriteLine( "Nr Topics={0}", resp.Content.Data.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/topics' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend topics list
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
        "name": "Weekly Newsletter",
        "description": "Weekly newsletter for our subscribers",
        "default_subscription": "opt_in",
        "visibility": "public",
        "created_at": "2026-04-08 00:11:13.110779+00"
      }
    ]
  }
  ```
</ResponseExample>


# Update Topic
Source: https://resend.com/docs/api-reference/topics/update-topic

PATCH /topics/:topic_id
Update an existing topic.

## Path Parameters

<ResendParamField type="string">
  The Topic ID.
</ResendParamField>

## Body Parameters

<ParamField type="string">
  The topic name. Max length is `50` characters.
</ParamField>

<ParamField type="string">
  The topic description. Max length is `200` characters.
</ParamField>

<ResendParamField type="string">
  The visibility of the topic on the unsubscribe page. Possible values: `public` or `private`.

  * `private`: only contacts who are opted in to the topic can see it on the unsubscribe page.
  * `public`: all contacts can see the topic on the unsubscribe page.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.topics.update(
    'b6d24b8e-af0b-4c3c-be0c-359bbd97381e',
    {
      name: 'Weekly Newsletter',
      description: 'Weekly newsletter for our subscribers',
    },
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->topics->update('b6d24b8e-af0b-4c3c-be0c-359bbd97381e', [
    'name' => 'Weekly Newsletter',
    'description' => 'Weekly newsletter for our subscribers',
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Topics.update(
      id="b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
      params={
          "name": "Monthly Newsletter",
          "description": "Subscribe to our monthly newsletter for updates",
      }
  )
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Topics.update(
    topic_id: "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
    name: "Weekly Newsletter",
    description: "Weekly newsletter for our subscribers"
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Topics.UpdateWithContext(context.TODO(), "b6d24b8e-af0b-4c3c-be0c-359bbd97381e", &resend.UpdateTopicRequest{
  		Name:        "Weekly Newsletter",
  		Description: "Weekly newsletter for our subscribers",
  	})
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::UpdateTopicOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let update = UpdateTopicOptions::new()
      .with_name("Weekly Newsletter")
      .with_description("Weekly newsletter for our subscribers");

    let _topic = resend
      .topics
      .update("b6d24b8e-af0b-4c3c-be0c-359bbd97381e", update)
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      UpdateTopicOptions updateTopicOptions = UpdateTopicOptions.builder()
        .name("Weekly Newsletter")
        .description("Weekly newsletter for our subscribers")
        .build();

      UpdateTopicResponseSuccess response = resend.topics().update(
        "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
        updateTopicOptions
      );
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.TopicUpdateAsync(
    new Guid( "b6d24b8e-af0b-4c3c-be0c-359bbd97381e" ),
    new TopicData() {
      Name = "Weekly Newsletter",
      Description = "Weekly newsletter for our subscribers",
      SubscriptionDefault = SubscriptionType.OptIn,
    }
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X PATCH 'https://api.resend.com/topics/b6d24b8e-af0b-4c3c-be0c-359bbd97381e' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "name": "Weekly Newsletter",
    "default_subscription": "opt_in"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend topics update b6d24b8e-af0b-4c3c-be0c-359bbd97381e \
    --name "Weekly Newsletter" \
    --description "Weekly newsletter for our subscribers"
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "topic",
    "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e"
  }
  ```
</ResponseExample>


# Create Webhook
Source: https://resend.com/docs/api-reference/webhooks/create-webhook

POST /webhooks
Create a webhook to receive real-time notifications about email events.

## Body Parameters

<ParamField type="string">
  The URL where webhook events will be sent.
</ParamField>

<ParamField type="string[]">
  Array of event types to subscribe to.

  <span />

  See [event types](/docs/webhooks/event-types) for available options.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.webhooks.create({
    endpoint: 'https://example.com/handler',
    events: ['email.sent'],
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->webhooks->create([
    'endpoint' => 'https://example.com/handler',
    'events' => ['email.sent'],
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  params: resend.Webhooks.CreateParams = {
      "endpoint": "https://example.com/handler",
      "events": ["email.sent"],
  }

  webhook = resend.Webhooks.create(params=params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require 'resend'

  Resend.api_key = 're_xxxxxxxxx'

  params = {
    endpoint: 'https://example.com/handler',
    events: ['email.sent']
  }

  webhook = Resend::Webhooks.create(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.CreateWebhookRequest{
  		Endpoint: "https://example.com/handler",
  		Events:   []string{"email.sent"},
  	}

  	client.Webhooks.Create(params)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{
    events::EmailEventType::{EmailSent},
    types::CreateWebhookOptions,
    Resend, Result,
  };

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let events = [EmailSent];
    let opts = CreateWebhookOptions::new("https://example.com/handler", events);
    let _webhook = resend.webhooks.create(opts).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;
  import static com.resend.services.webhooks.model.WebhookEvent.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateWebhookOptions options = CreateWebhookOptions.builder()
                .endpoint("https://example.com/handler")
                .events(EMAIL_SENT)
                .build();

          CreateWebhookResponseSuccess response = resend.webhooks().create(options);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var data = new WebhookData()
  {
      EndpointUrl = "https://example.com/handler",
      Events = [ WebhookEventType.EmailSent ],
      Status = WebhookStatus.Disabled,
  };

  var resp = await resend.WebhookCreateAsync( data );
  Console.WriteLine( "Webhook Id={0}", resp.Content.Id );
  Console.WriteLine( "Signing secret={0}", resp.Content.SigningSecret );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/webhooks' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d '{
    "endpoint": "https://example.com/handler",
    "events": ["email.sent"]
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend webhooks create \
    --endpoint https://example.com/handler \
    --events email.sent
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "webhook",
    "id": "4dd369bc-aa82-4ff3-97de-514ae3000ee0",
    "signing_secret": "whsec_xxxxxxxxxx"
  }
  ```
</ResponseExample>


# Delete Webhook
Source: https://resend.com/docs/api-reference/webhooks/delete-webhook

DELETE /webhooks/:webhook_id
Remove an existing webhook.

## Path Parameters

<ResendParamField type="string">
  The Webhook ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.webhooks.remove(
    '4dd369bc-aa82-4ff3-97de-514ae3000ee0',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->webhooks->remove('4dd369bc-aa82-4ff3-97de-514ae3000ee0');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  webhook = resend.Webhooks.remove(webhook_id='4dd369bc-aa82-4ff3-97de-514ae3000ee0')
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require 'resend'

  Resend.api_key = 're_xxxxxxxxx'

  webhook = Resend::Webhooks.remove('4dd369bc-aa82-4ff3-97de-514ae3000ee0')
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Webhooks.Remove("4dd369bc-aa82-4ff3-97de-514ae3000ee0")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _deleted = resend
      .webhooks
      .delete("4dd369bc-aa82-4ff3-97de-514ae3000ee0")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          RemoveWebhookResponseSuccess response = resend.webhooks().remove("4dd369bc-aa82-4ff3-97de-514ae3000ee0");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.WebhookDeleteAsync( new Guid( "d91cd9bd-1176-453e-8fc1-35364d380206" ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X DELETE 'https://api.resend.com/webhooks/4dd369bc-aa82-4ff3-97de-514ae3000ee0' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend webhooks delete 4dd369bc-aa82-4ff3-97de-514ae3000ee0
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "webhook",
    "id": "4dd369bc-aa82-4ff3-97de-514ae3000ee0",
    "deleted": true
  }
  ```
</ResponseExample>


# Retrieve Event
Source: https://resend.com/docs/api-reference/webhooks/get-event

GET /webhooks/:webhook_id/events/:event_id
Retrieve the details of a single event delivered to a webhook.

<Warning>
  Webhook events and delivery attempts are currently in private beta and only
  available to a limited number of users. APIs might change before it is
  generally available. [Get in touch](https://resend.com/contact) if you're
  interested in testing this feature.

  <span />

  Once you have access, upgrade your Resend SDK to use the methods on this
  page:

  <CodeGroup>
    ```bash Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
    npm install resend@6.19.0-preview-headless-dashboard.7
    ```
  </CodeGroup>
</Warning>

## Path Parameters

<ParamField type="string">
  The Webhook ID.
</ParamField>

<ParamField type="string">
  The Webhook Event ID.
</ParamField>

## Response Fields

<ParamField type="string">
  Always `webhook_event`.
</ParamField>

<ParamField type="string">
  The event ID.
</ParamField>

<ParamField type="string">
  The event type, for example `email.sent`.
</ParamField>

<ParamField type="string">
  When the event was created.
</ParamField>

<ParamField type="string">
  Delivery status of the event to this webhook: `success`, `failed`,
  `attempting`, or `pending`.
</ParamField>

<ParamField type="string | null">
  When the next delivery attempt is scheduled. `null` once the event reaches
  `success` or `failed`.
</ParamField>

<ParamField type="object">
  The event payload that was sent to your endpoint.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.webhooks.events.get({
    eventId: 'msg_1srOrx2ZWZBpBUvZwXKQmoEYga2',
    webhookId: '4dd369bc-aa82-4ff3-97de-514ae3000ee0',
  });
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/webhooks/4dd369bc-aa82-4ff3-97de-514ae3000ee0/events/msg_1srOrx2ZWZBpBUvZwXKQmoEYga2' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "webhook_event",
    "id": "msg_1srOrx2ZWZBpBUvZwXKQmoEYga2",
    "type": "email.sent",
    "created_at": "2026-08-22T15:28:00.000Z",
    "status": "attempting",
    "next_attempt_at": "2026-08-22T15:33:00.000Z",
    "payload": {
      "type": "email.sent",
      "created_at": "2026-08-22T15:28:00.000Z",
      "data": {
        "email_id": "571f1f42-1c2d-4b1f-8f8e-8b3b5b3b5b3b",
        "from": "onboarding@resend.dev",
        "to": ["delivered@resend.dev"],
        "subject": "Welcome",
        "created_at": "2026-08-22T15:27:59.000Z"
      }
    }
  }
  ```
</ResponseExample>


# Retrieve Webhook
Source: https://resend.com/docs/api-reference/webhooks/get-webhook

GET /webhooks/:webhook_id
Retrieve a single webhook for the authenticated user.

## Path Parameters

<ResendParamField type="string">
  The Webhook ID.
</ResendParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.webhooks.get(
    '4dd369bc-aa82-4ff3-97de-514ae3000ee0',
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->webhooks->get('4dd369bc-aa82-4ff3-97de-514ae3000ee0');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  webhook = resend.Webhooks.get(webhook_id='4dd369bc-aa82-4ff3-97de-514ae3000ee0')
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require 'resend'

  Resend.api_key = 're_xxxxxxxxx'

  webhook = Resend::Webhooks.get('4dd369bc-aa82-4ff3-97de-514ae3000ee0')
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Webhooks.Get("4dd369bc-aa82-4ff3-97de-514ae3000ee0")
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _webhook = resend
      .webhooks
      .get("4dd369bc-aa82-4ff3-97de-514ae3000ee0")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          GetWebhookResponseSuccess webhook = resend.webhooks().get("4dd369bc-aa82-4ff3-97de-514ae3000ee0");
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.WebhookRetrieveAsync( new Guid( "559ac32e-9ef5-46fb-82a1-b76b840c0f7b" ) );
  Console.WriteLine( "Endpoint={0}", resp.Content.EndpointUrl );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/webhooks/4dd369bc-aa82-4ff3-97de-514ae3000ee0' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend webhooks get 4dd369bc-aa82-4ff3-97de-514ae3000ee0
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "webhook",
    "id": "4dd369bc-aa82-4ff3-97de-514ae3000ee0",
    "created_at": "2026-08-22 15:28:00.000+00",
    "status": "enabled",
    "endpoint": "https://example.com/handler",
    "events": ["email.sent"],
    "signing_secret": "whsec_xxxxxxxxxx"
  }
  ```
</ResponseExample>


# List Attempts
Source: https://resend.com/docs/api-reference/webhooks/list-event-attempts

GET /webhooks/:webhook_id/events/:event_id/attempts
Retrieve the delivery attempts for a single webhook event.

<Warning>
  Webhook events and delivery attempts are currently in private beta and only
  available to a limited number of users. APIs might change before it is
  generally available. [Get in touch](https://resend.com/contact) if you're
  interested in testing this feature.

  <span />

  Once you have access, upgrade your Resend SDK to use the methods on this
  page:

  <CodeGroup>
    ```bash Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
    npm install resend@6.19.0-preview-headless-dashboard.7
    ```
  </CodeGroup>
</Warning>

## Path Parameters

<ParamField type="string">
  The Webhook ID.
</ParamField>

<ParamField type="string">
  The Webhook Event ID.
</ParamField>

## Query Parameters

<ParamField type="number">
  Number of attempts to return. Between `1` and `100`. Defaults to `20`.
</ParamField>

<ParamField type="string">
  The attempt ID to fetch the next page after.

  The `before` parameter is not supported for this endpoint.
</ParamField>

## Response Fields

<ParamField type="string">
  Always `list`.
</ParamField>

<ParamField type="boolean">
  Whether more attempts exist beyond this page.
</ParamField>

<ParamField type="array">
  The delivery attempts for this event, most recent first.

  <Expandable title="properties">
    <ParamField type="string">
      The attempt ID.
    </ParamField>

    <ParamField type="number">
      The HTTP status code your endpoint returned for this attempt.
    </ParamField>

    <ParamField type="string">
      The response body your endpoint returned for this attempt.
    </ParamField>

    <ParamField type="string">
      When this attempt was sent.
    </ParamField>
  </Expandable>
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.webhooks.events.attempts.list({
    eventId: 'msg_1srOrx2ZWZBpBUvZwXKQmoEYga2',
    webhookId: '4dd369bc-aa82-4ff3-97de-514ae3000ee0',
  });
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/webhooks/4dd369bc-aa82-4ff3-97de-514ae3000ee0/events/msg_1srOrx2ZWZBpBUvZwXKQmoEYga2/attempts' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "atmpt_1srOrx2ZWZBpBUvZwXKQmoEYga2",
        "http_status_code": 200,
        "response": "{\"ok\":true}",
        "sent_at": "2026-08-22T15:33:12.000Z"
      },
      {
        "id": "atmpt_2ZbUCwvGmIT4mLIN6d3Yz0Ainbd",
        "http_status_code": 500,
        "response": "Internal Server Error",
        "sent_at": "2026-08-22T15:28:05.000Z"
      }
    ]
  }
  ```
</ResponseExample>


# List Events
Source: https://resend.com/docs/api-reference/webhooks/list-events

GET /webhooks/:webhook_id/events
Retrieve a list of events delivered to a webhook.

<Warning>
  Webhook events and delivery attempts are currently in private beta and only
  available to a limited number of users. APIs might change before it is
  generally available. [Get in touch](https://resend.com/contact) if you're
  interested in testing this feature.

  <span />

  Once you have access, upgrade your Resend SDK to use the methods on this
  page:

  <CodeGroup>
    ```bash Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
    npm install resend@6.19.0-preview-headless-dashboard.7
    ```
  </CodeGroup>
</Warning>

## Path Parameters

<ParamField type="string">
  The Webhook ID.
</ParamField>

## Query Parameters

<ParamField type="number">
  Number of events to return. Between `1` and `100`. Defaults to `20`.
</ParamField>

<ParamField type="string">
  The event ID to fetch the next page after.

  The `before` parameter is not supported for this endpoint.
</ParamField>

## Response Fields

<ParamField type="string">
  Always `list`.
</ParamField>

<ParamField type="boolean">
  Whether more events exist beyond this page.
</ParamField>

<ParamField type="array">
  The events delivered to this webhook, most recent first.

  <Expandable title="properties">
    <ParamField type="string">
      The event ID. Use this to [retrieve its details](/docs/api-reference/webhooks/get-event)
      or [list its attempts](/docs/api-reference/webhooks/list-event-attempts).
    </ParamField>

    <ParamField type="string">
      The event type, for example `email.sent`.
    </ParamField>

    <ParamField type="string">
      When the event was created.
    </ParamField>

    <ParamField type="string">
      Delivery status of the event to this webhook: `success`, `failed`,
      `attempting`, or `pending`.
    </ParamField>
  </Expandable>
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.webhooks.events.list({
    webhookId: '4dd369bc-aa82-4ff3-97de-514ae3000ee0',
  });
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/webhooks/4dd369bc-aa82-4ff3-97de-514ae3000ee0/events' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "msg_1srOrx2ZWZBpBUvZwXKQmoEYga2",
        "type": "email.sent",
        "created_at": "2026-08-22T15:28:00.000Z",
        "status": "success"
      },
      {
        "id": "msg_1srOsB4mXhCqCVwAxYRNnpFZhb3",
        "type": "email.delivered",
        "created_at": "2026-08-22T15:27:42.000Z",
        "status": "failed"
      }
    ]
  }
  ```
</ResponseExample>


# List Webhooks
Source: https://resend.com/docs/api-reference/webhooks/list-webhooks

GET /webhooks
Retrieve a list of webhooks for the authenticated user.

<QueryParams type="webhooks" />

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.webhooks.list();
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->webhooks->list();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  webhooks = resend.Webhooks.list()
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require 'resend'

  Resend.api_key = 're_xxxxxxxxx'

  webhooks = Resend::Webhooks.list
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Webhooks.List()
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{list_opts::ListOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _webhooks = resend.webhooks.list(ListOptions::default()).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          ListWebhooksResponseSuccess response = resend.webhooks().list();
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.WebhookListAsync();
  Console.WriteLine( "Nr Webhooks={0}", resp.Content.Data.Count );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X GET 'https://api.resend.com/webhooks' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend webhooks list
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "list",
    "has_more": false,
    "data": [
      {
        "id": "7ab123cd-ef45-6789-abcd-ef0123456789",
        "created_at": "2026-09-10 10:15:30.000+00",
        "status": "disabled",
        "endpoint": "https://first-webhook.example.com/handler",
        "events": ["email.sent"]
      },
      {
        "id": "4dd369bc-aa82-4ff3-97de-514ae3000ee0",
        "created_at": "2026-08-22 15:28:00.000+00",
        "status": "enabled",
        "endpoint": "https://second-webhook.example.com/receive",
        "events": ["email.received"]
      }
    ]
  }
  ```
</ResponseExample>


# Update Webhook
Source: https://resend.com/docs/api-reference/webhooks/update-webhook

PATCH /webhooks/:webhook_id
Update an existing webhook configuration.

## Path Parameters

<ResendParamField type="string">
  The Webhook ID.
</ResendParamField>

## Body Parameters

<ParamField type="string">
  The URL where webhook events will be sent.
</ParamField>

<ParamField type="string[]">
  Array of event types to subscribe to.

  <span />

  See [event types](/docs/webhooks/event-types) for available options.
</ParamField>

<ParamField type="string">
  The webhook status. Can be either `enabled` or `disabled`.
</ParamField>

<RequestExample>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.webhooks.update(
    '430eed87-632a-4ea6-90db-0aace67ec228',
    {
      endpoint: 'https://new-webhook.example.com/handler',
      events: ['email.sent', 'email.delivered'],
      status: 'enabled',
    },
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->webhooks->update('430eed87-632a-4ea6-90db-0aace67ec228', [
    'endpoint' => 'https://new-webhook.example.com/handler',
    'events' => ['email.sent', 'email.delivered'],
    'status' => 'enabled',
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  params: resend.Webhooks.UpdateParams = {
      "webhook_id": "430eed87-632a-4ea6-90db-0aace67ec228",
      "endpoint": "https://new-webhook.example.com/handler",
      "events": ["email.sent", "email.delivered"],
      "status": "enabled",
  }

  webhook = resend.Webhooks.update(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require 'resend'

  Resend.api_key = 're_xxxxxxxxx'

  params = {
    webhook_id: '430eed87-632a-4ea6-90db-0aace67ec228',
    endpoint: 'https://new-webhook.example.com/handler',
    events: ['email.sent', 'email.delivered'],
    status: 'enabled'
  }

  webhook = Resend::Webhooks.update(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	endpoint := "https://new-webhook.example.com/handler"
  	status := "enabled"
  	params := &resend.UpdateWebhookRequest{
  		Endpoint: &endpoint,
  		Events:   []string{"email.sent", "email.delivered"},
  		Status:   &status,
  	}

  	client.Webhooks.Update("430eed87-632a-4ea6-90db-0aace67ec228", params)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{
    events::EmailEventType::{EmailDelivered, EmailSent},
    types::{UpdateWebhookOptions, WebhookStatus},
    Resend, Result,
  };

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let events = [EmailSent, EmailDelivered];
    let opts = UpdateWebhookOptions::default()
      .with_endpoint("https://new-webhook.example.com/handler")
      .with_events(events)
      .with_status(WebhookStatus::Enabled);

    let _webhook = resend
      .webhooks
      .update("430eed87-632a-4ea6-90db-0aace67ec228", opts)
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;
  import static com.resend.services.webhooks.model.WebhookEvent.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          UpdateWebhookOptions options = UpdateWebhookOptions.builder()
              .endpoint("https://new-webhook.example.com/handler")
              .events(EMAIL_SENT, EMAIL_DELIVERED)
              .status(WebhookStatus.ENABLED)
              .build();

          UpdateWebhookResponseSuccess response = resend.webhooks()
              .update("430eed87-632a-4ea6-90db-0aace67ec228", options);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.WebhookUpdateAsync(
      new Guid( "430eed87-632a-4ea6-90db-0aace67ec228" ),
      new WebhookData()
      {
        EndpointUrl = "https://new-webhook.example.com/handler",
        Events = [ WebhookEventType.EmailSent ],
        Status = WebhookStatus.Disabled,
      }
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X PATCH 'https://api.resend.com/webhooks/430eed87-632a-4ea6-90db-0aace67ec228' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d '{
    "endpoint": "https://new-webhook.example.com/handler",
    "events": ["email.sent", "email.delivered"],
    "status": "enabled"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend webhooks update 430eed87-632a-4ea6-90db-0aace67ec228 \
    --endpoint https://new-webhook.example.com/handler \
    --events email.sent email.delivered \
    --status enabled
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "object": "webhook",
    "id": "430eed87-632a-4ea6-90db-0aace67ec228"
  }
  ```
</ResponseExample>


# Resend API vs SDK
Source: https://resend.com/docs/api-vs-sdk

For most use cases, the Resend SDK offers a better developer experience.

For most use cases, **the Resend SDK offers a better developer experience** than
calling the raw HTTP API directly. Resend maintains official, open source SDKs
for Node.js, PHP, Python, Ruby, Go, Rust, Java, and .NET.

<Info>
  **Recommendation:** Use a [Resend SDK](/docs/sdks) for your language. Call the [raw
  API](/docs/api-reference/introduction) directly only when no SDK exists for your
  stack.
</Info>

## Choosing between the SDK and API

Reach for the SDK unless you have a specific reason not to. It handles
authentication, the required `User-Agent` header, request serialization, typed
responses, and error handling for you. That leaves less boilerplate to get
wrong.

|                      | Resend SDK (recommended) | Raw HTTP API                                  |
| -------------------- | ------------------------ | --------------------------------------------- |
| Auth & headers       | Handled automatically    | Set `Authorization` and `User-Agent` manually |
| Types & autocomplete | Built in                 | None                                          |
| Errors               | Structured error objects | Parse status codes and JSON yourself          |
| Maintained by        | Resend                   | You                                           |

## When to use the raw API directly

Calling the API directly is a good fit when:

* There's **no official SDK** for your language or runtime.
* You're making a one-off request and don't want to add a dependency.
* You're building your own integration or wrapper.

If you do call the API directly, remember to set the required
[`User-Agent` header](/docs/api-reference/introduction#user-agent).

## Next steps

<CardGroup>
  <Card title="Official SDKs" icon="cube" href="/sdks">
    Install the SDK for your language.
  </Card>

  <Card title="Quickstart" icon="rocket" href="/introduction">
    Send your first email in minutes.
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/introduction">
    Full HTTP API documentation.
  </Card>

  <Card title="MCP Server" icon="robot" href="/mcp-server">
    Give your AI agent access to Resend.
  </Card>
</CardGroup>


# Send emails with Appwrite and Resend
Source: https://resend.com/docs/appwrite-integration

Learn how to send emails through Resend using Appwrite Messaging.

[Appwrite](https://appwrite.io) is an open-source development platform for building and scaling applications faster, offering Auth, Databases, Storage, Functions, Messaging, Realtime, and web hosting, all in one place.

Appwrite Messaging includes a native Resend provider, so you can send emails to your app's users through Resend without writing any delivery code.

## Prerequisites

To get the most out of this guide, you'll need to:

* [Create an API key](https://resend.com/api-keys)
* [Verify your domain](https://resend.com/domains)

You'll also need an [Appwrite project](https://cloud.appwrite.io) with at least one user.

## 1. Add Resend as an email provider

In the Appwrite Console, navigate to **Messaging** > **Providers** > **Add provider** > **Email**. Give your provider a name, choose **Resend**, and click **Save and continue**.

<Note>
  The provider will be saved to your project, but not enabled until you complete
  its configuration.
</Note>

In the **Configure** step, you will need to provide details from your Resend dashboard to connect your Appwrite project:

| Field          | Description                                                                                                                                                   |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| API key        | Head to API Keys > Create API Key. You can also follow [Resend's instructions](/docs/dashboard/api-keys/introduction) to create an API key.                        |
| Sender email   | The provider sends emails from this sender email. The sender email needs to be an email under a [verified domain](/docs/dashboard/domains/introduction) in Resend. |
| Sender name    | The sender name that appears in the emails sent from this provider.                                                                                           |
| Reply-to email | The reply-to email that appears in the emails sent from this provider.                                                                                        |
| Reply-to name  | The reply-to name that appears in the emails sent from this provider.                                                                                         |

After adding these details, click **Save and continue** to enable the provider.

## 2. Add recipients

Appwrite Messaging delivers messages to **targets**, the different ways a user can be reached: their email addresses, phone numbers, and devices with your app installed. Targets can subscribe to **topics**, so when a message is published to a topic, all subscribed targets receive it.

Users with verified emails who signed up with [email password](https://appwrite.io/docs/products/auth/email-password), [magic URL](https://appwrite.io/docs/products/auth/magic-url), [email OTP](https://appwrite.io/docs/products/auth/email-otp), or [OAuth2](https://appwrite.io/docs/products/auth/oauth2) login already have an email target. You can also add targets to existing users by navigating to **Authentication** > **Users** > select a user > **Targets**.

To message groups of users, navigate to **Messaging** > **Topics** > **Create topic** and subscribe their targets to the topic.

Learn more about [topics](https://appwrite.io/docs/products/messaging/topics) and [targets](https://appwrite.io/docs/products/messaging/targets) in the Appwrite documentation.

## 3. Send your first email

To send a test email from the Appwrite Console, navigate to **Messaging** > **Messages** > **Create message** > **Email**. Add your message and in the targets step, select one of your test targets. Set the schedule to **Now** and click **Send**.

Verify that you can receive the message in your inbox. If not, check for logs in the Appwrite Console or in your [Resend dashboard](https://resend.com/emails).

To send emails programmatically, use an [Appwrite Server SDK](https://appwrite.io/docs/sdks#server):

```js theme={"theme":{"light":"github-light","dark":"vesper"}}
import { Client, Messaging, ID } from 'node-appwrite';

const client = new Client()
  .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API endpoint
  .setProject('<PROJECT_ID>') // Your project ID
  .setKey('<API_KEY>'); // Your secret API key

const messaging = new Messaging(client);

const message = await messaging.createEmail({
  messageId: ID.unique(),
  subject: 'Welcome aboard!',
  content: 'Thanks for signing up. We are happy to have you.',
  topics: ['<TOPIC_ID>'],
});
```

Emails can be sent immediately or scheduled for a later time.


# Send emails with Base44 and Resend
Source: https://resend.com/docs/base44-integration

Learn how to add the Resend integration to your Base44 project.

[Base44](https://base44.com/) is a platform for building apps with AI. You can add Resend in a Base44 project by asking the chat to add email sending with Resend.

<Info>
  This integration requires backend functions, a feature available only on
  Builder tier and above. Learn more about [Base44
  pricing](https://base44.com/pricing).
</Info>

## Guide

<Steps>
  <Step title="Add the Resend integration in Base44">
    **If starting a new app:**

    1. Click **Integration** in the top nav.
    2. Search for **Resend**, select it, and choose **Use This Integration**.

    <img alt="Resend Integration page" />

    **If adding Resend to an existing app:**

    1. Enable backend functions.
    2. Ask the chat: "Add the Resend email integration to my app. Prompt me to provide the API key and send a welcome email to new users."

    <Note>
      See the [Base44
      documenation](https://docs.base44.com/Integrations/Resend-integration) for
      more information.
    </Note>
  </Step>

  <Step title="Add your Resend API key">
    However you add Resend to your project, you'll need to add a Resend API key, which you can create in the [Resend Dashboard](https://resend.com/api-keys). Do not share your API key with others or expose it in the browser or other client-side code.

    Copy the API key and paste it into the **RESEND\_API\_KEY** field in Base44.

    <img alt="Adding your Resend API key to Base44" />
  </Step>

  <Step title="Add a custom domain to your Resend account">
    By default, you can only send emails to your own email address.

    To send emails to other email addresses:

    1. Add a [custom domain to your Resend account](/docs/add-a-domain).
    2. Add the custom domain to the `from` field in the `resend` function in the Base44 backend function (or ask the chat to update these fields).

    Get more help adding a custom domain in [Resend's documentation](/docs/dashboard/domains/introduction).
  </Step>
</Steps>


# Send emails with Bolt.new and Resend
Source: https://resend.com/docs/bolt-new-integration

Learn how to add the Resend integration to your Bolt.new project.

[Bolt.new](https://bolt.new) is a platform for building full-stack web and mobile apps via chat. You can add Resend in a Bolt.new project by asking the chat to add email sending with Resend.

<img alt="adding the Resend integration to a Bolt.new chat" />

## Guide

<Steps>
  <Step title="Add your Resend API key">
    To use Resend with Bolt.new, you'll need to add a Resend API key, which you can create in the [Resend Dashboard](https://resend.com/api-keys). Do not share your API key with others or expose it in the browser or other client-side code.

    <Note>
      To safely store your Resend API key, use a `.env` file. You may need to
      include this instruction in your prompt to bolt.new. Learn more about
      [handling API keys](/docs/knowledge-base/how-to-handle-api-keys).
    </Note>
  </Step>

  <Step title="Add a custom domain to your Resend account">
    By default, you can only send emails to your own email address.

    To send emails to other email addresses:

    1. Add a [custom domain to your Resend account](/docs/add-a-domain).
    2. Add the custom domain to the `from` field in the `resend` function in Bolt.new (or ask the chat to update these fields).

    Get more help adding a custom domain in [Resend's documentation](/docs/dashboard/domains/introduction).
  </Step>
</Steps>


# Chat SDK
Source: https://resend.com/docs/chat-sdk

Build conversational email experiences using the Vercel Chat SDK and Resend.

<Prompt description="Use this pre-built prompt with your AI agent to build with the Resend Chat SDK adapter." icon="comments">
  # Resend Chat SDK Adapter

  **Purpose:** Instructions for building bidirectional email bots using the `@resend/chat-sdk-adapter` package with the Vercel Chat SDK.

  ***

  ## Setup

  ### Prerequisites

  * Resend API key stored in `RESEND_API_KEY` env var
  * Verified domain at [https://resend.com/domains](https://resend.com/domains)
  * Webhook configured for `email.received` events (see [https://resend.com/docs/webhooks/introduction](https://resend.com/docs/webhooks/introduction))
  * Inbound email receiving enabled (see [https://resend.com/docs/dashboard/receiving/introduction](https://resend.com/docs/dashboard/receiving/introduction))

  ### Install

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install @resend/chat-sdk-adapter chat @chat-adapter/state-memory
  # or: yarn add / pnpm add / bun add
  ```

  ### Initialize

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { createResendAdapter } from '@resend/chat-sdk-adapter';
  import { MemoryStateAdapter } from '@chat-adapter/state-memory';
  import { Chat } from 'chat';

  const resend = createResendAdapter({
    fromAddress: 'bot@example.com',
    fromName: 'My Bot', // optional
    // apiKey: "re_...",       // or set RESEND_API_KEY env var
    // webhookSecret: "whsec_..." // or set RESEND_WEBHOOK_SECRET env var
  });

  const chat = new Chat({
    userName: 'email-bot',
    adapters: { resend },
    state: new MemoryStateAdapter(),
  });
  ```

  ### Handle Inbound Emails

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  // New email (new thread)
  chat.onNewMention(async (thread, message) => {
    await thread.subscribe();
    await thread.post(`Got your email: ${message.text}`);
  });

  // Follow-up email in a subscribed thread
  chat.onSubscribedMessage(async (thread, message) => {
    await thread.post(`Reply: ${message.text}`);
  });
  ```

  ### Forward Webhooks

  Point Resend webhooks to your server's `/webhook` endpoint. The adapter handles verification and parsing.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  // Inside your HTTP server handler for POST /webhook
  const result = await chat.webhooks.resend(request);
  ```

  `request` must be a Web `Request` object. If you're using Node.js `http`, convert `IncomingMessage` to a `Request` first.

  ***

  ## Configuration

  | Parameter       | Type     | Required | Description                                                           |
  | --------------- | -------- | -------- | --------------------------------------------------------------------- |
  | `fromAddress`   | `string` | Yes      | Sender email address                                                  |
  | `fromName`      | `string` | No       | Display name for the From header                                      |
  | `apiKey`        | `string` | No       | Resend API key. Falls back to `RESEND_API_KEY` env var                |
  | `webhookSecret` | `string` | No       | Webhook signing secret. Falls back to `RESEND_WEBHOOK_SECRET` env var |

  ***

  ## Threading

  Threads are resolved automatically using `Message-ID`, `In-Reply-To`, and `References` headers. Reply chains are grouped into Chat SDK threads with no extra configuration.

  ***

  ## Card Emails

  Send rich HTML emails using Card elements:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  await thread.post({
    card: {
      type: 'card',
      title: 'Order Confirmed',
      children: [
        { type: 'text', content: 'Your order #1234 has been shipped.' },
        { type: 'divider' },
        {
          type: 'link-button',
          label: 'Track Order',
          url: 'https://example.com/track/1234',
        },
      ],
    },
    fallbackText: 'Order #1234 confirmed',
  });
  ```

  Cards render to HTML via `@react-email/components`. Always include `fallbackText` for plain-text clients.

  ***

  ## Proactive Outreach

  Start a new email thread without waiting for inbound:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const threadId = await chat.adapters.resend.openDM('user@example.com');
  const thread = await chat.thread('resend', threadId);
  await thread.post('Hello from the bot!');
  ```

  ***

  ## Attachments

  Inbound email attachments are available on `message.raw.attachments`:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  chat.onNewMention(async (thread, message) => {
    const attachments = message.raw?.attachments ?? [];
    for (const file of attachments) {
      console.log(file.filename, file.contentType, file.url);
    }
  });
  ```

  ***

  ## Unsupported Operations

  Email is immutable. These operations throw `NotImplementedError`:

  * `editMessage` / `deleteMessage`
  * `addReaction` / `removeReaction`
  * `startTyping`

  ***

  ## AI Model Instructions

  1. **Always** use `createResendAdapter` from `@resend/chat-sdk-adapter`
  2. **Always** store API keys in env vars, never hardcode
  3. **Always** call `thread.subscribe()` in `onNewMention` if you want to receive follow-ups
  4. **Always** include `fallbackText` when sending card emails
  5. **Never** attempt `editMessage`, `deleteMessage`, `addReaction`, `removeReaction`, or `startTyping` — email does not support these
  6. The webhook handler expects a Web `Request` object — convert Node.js `IncomingMessage` if needed
  7. The adapter name in Chat config must be `"resend"` for thread routing to work

  For the full Resend docs: [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

The `@resend/chat-sdk-adapter` package is a [Vercel Chat SDK](https://github.com/nichochar/chat) adapter that turns email into a two-way communication channel via Resend. Receive inbound emails through webhooks, reply through the Resend API, and let the adapter handle threading automatically.

The adapter is open source and [available on GitHub](https://github.com/resend/resend-chat-sdk).

## Prerequisites

To get started, you'll need to:

* [Create an API key](https://resend.com/api-keys)
* [Verify your domain](https://resend.com/domains)
* [Set up webhooks](/docs/webhooks/introduction) for `email.received` events
* [Enable receiving](/docs/dashboard/receiving/introduction) on your domain

## Guide

<Steps>
  <Step title="Install">
    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install @resend/chat-sdk-adapter chat @chat-adapter/state-memory
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add @resend/chat-sdk-adapter chat @chat-adapter/state-memory
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add @resend/chat-sdk-adapter chat @chat-adapter/state-memory
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add @resend/chat-sdk-adapter chat @chat-adapter/state-memory
      ```
    </CodeGroup>
  </Step>

  <Step title="Configure the adapter">
    Create a Resend adapter and pass it with [adapter configuration options](#configuration-options) to the Chat SDK.

    ```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { createResendAdapter } from '@resend/chat-sdk-adapter';
    import { MemoryStateAdapter } from '@chat-adapter/state-memory';
    import { Chat } from 'chat';

    const resend = createResendAdapter({
      fromAddress: 'bot@example.com',
      fromName: 'My Bot',
    });

    const chat = new Chat({
      userName: 'email-bot',
      adapters: { resend },
      state: new MemoryStateAdapter(),
    });
    ```

    <Info>
      Set `RESEND_API_KEY` and `RESEND_WEBHOOK_SECRET` as environment variables. You can also pass `apiKey` and `webhookSecret` directly in the config — explicit values take precedence over env vars.
    </Info>
  </Step>

  <Step title="Handle inbound emails">
    Register handlers for incoming emails. `onNewMention` fires when a new thread starts, and `onSubscribedMessage` fires for follow-up emails in threads you've subscribed to.

    ```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    chat.onNewMention(async (thread, message) => {
      console.log(`New email from ${message.author.userId}: ${message.text}`);
      await thread.subscribe();
      await thread.post(`Got your email: ${message.text}`);
    });

    chat.onSubscribedMessage(async (thread, message) => {
      await thread.post(`Reply: ${message.text}`);
    });
    ```
  </Step>

  <Step title="Forward webhooks">
    Point your Resend webhooks to your server's `/webhook` endpoint. The adapter verifies the signature and parses the payload.

    ```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    if (req.method === 'POST' && req.url === '/webhook') {
      const result = await chat.webhooks.resend(request);
      res.writeHead(result.status);
      res.end();
    }
    ```

    The handler expects a Web `Request` object. If you're using Node.js `http`, convert `IncomingMessage` to a `Request` first. See the [basic example](https://github.com/resend/resend-chat-sdk/tree/main/examples/basic) for a full working server.

    For webhook setup details, see [Managing Webhooks](/docs/webhooks/introduction) and [Verify Webhook Requests](/docs/webhooks/verify-webhooks-requests).
  </Step>
</Steps>

## How threading works

The adapter resolves threads using standard `Message-ID`, `In-Reply-To`, and `References` email headers. Reply chains are automatically grouped into Chat SDK threads, with no extra configuration needed.

<Warning>
  Email is immutable. The following operations throw `NotImplementedError`: `editMessage`, `deleteMessage`, `addReaction`, `removeReaction`, and `startTyping`.
</Warning>

## Configuration options

| Parameter       | Type     | Required | Description                                                           |
| --------------- | -------- | -------- | --------------------------------------------------------------------- |
| `fromAddress`   | `string` | Yes      | Sender email address                                                  |
| `fromName`      | `string` | No       | Display name for the From header                                      |
| `apiKey`        | `string` | No       | Resend API key. Falls back to `RESEND_API_KEY` env var                |
| `webhookSecret` | `string` | No       | Webhook signing secret. Falls back to `RESEND_WEBHOOK_SECRET` env var |

## Features

<CardGroup>
  <Card title="Card Emails" icon="palette" href="/chat-sdk-card-emails">
    Send rich HTML emails with structured card elements.
  </Card>

  <Card title="Attachments" icon="paperclip" href="/chat-sdk-attachments">
    Handle inbound email attachments.
  </Card>

  <Card title="Proactive Outreach" icon="paper-plane" href="/chat-sdk-proactive-outreach">
    Start new email threads without waiting for inbound.
  </Card>
</CardGroup>

## Examples

<CardGroup>
  <Card title="Basic" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-chat-sdk/tree/main/examples/basic">
    Echo bot that replies to every email
  </Card>

  <Card title="Welcome Cards" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-chat-sdk/tree/main/examples/welcome-cards">
    Styled card email on first contact
  </Card>

  <Card title="Notifications" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-chat-sdk/tree/main/examples/notifications">
    Proactive outbound via openDM and HTTP POST
  </Card>

  <Card title="Support Bot" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-chat-sdk/tree/main/examples/support-bot">
    Multi-turn conversations with subscribe/unsubscribe
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-chat-sdk/tree/main/examples/attachments">
    Detect attachments and reply with a summary
  </Card>
</CardGroup>


# Chat SDK Attachments
Source: https://resend.com/docs/chat-sdk-attachments

Handle inbound email attachments with the Chat SDK adapter.

When someone sends an email with file attachments, the adapter makes them available on `message.raw.attachments`. Each attachment includes the filename, MIME type, and a URL to download the content.

## Attachment shape

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
interface ResendAttachment {
  filename: string;
  contentType: string;
  url?: string;
}
```

| Field         | Type     | Description                                      |
| ------------- | -------- | ------------------------------------------------ |
| `filename`    | `string` | Original filename (e.g., `invoice.pdf`)          |
| `contentType` | `string` | MIME type (e.g., `application/pdf`)              |
| `url`         | `string` | Optional download URL for the attachment content |

## Detecting and processing attachments

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
chat.onNewMention(async (thread, message) => {
  const attachments = message.raw?.attachments ?? [];

  if (attachments.length === 0) {
    await thread.subscribe();
    await thread.post('Got your email — no attachments found.');
    return;
  }

  const summary = attachments
    .map((a) => `${a.filename} (${a.contentType})`)
    .join(', ');

  await thread.subscribe();
  await thread.post(`Received ${attachments.length} attachment(s): ${summary}`);
});
```

For more on receiving email attachments outside the Chat SDK, see [Receiving Attachments](/docs/dashboard/receiving/attachments).

## Try it yourself

<Card title="Attachments Example" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-chat-sdk/tree/main/examples/attachments">
  Detects attachments and replies with a summary
</Card>


# Chat SDK Card Emails
Source: https://resend.com/docs/chat-sdk-card-emails

Send rich HTML card emails using the Chat SDK and React Email.

The Chat SDK adapter renders Card elements into styled HTML emails using `@react-email/components`. This lets you send structured, branded messages without writing raw HTML.

## Card structure

A card has a `type`, `title`, optional `subtitle`, and `children` array. Children can be text blocks, dividers, link buttons, or action groups.

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import type { CardElement } from 'chat';

const card: CardElement = {
  type: 'card',
  title: 'Order Confirmed',
  subtitle: 'Order #1234',
  children: [
    { type: 'text', content: 'Your order has been shipped.' },
    { type: 'divider' },
    {
      type: 'actions',
      children: [
        {
          type: 'link-button',
          label: 'Track Order',
          url: 'https://example.com/track/1234',
        },
      ],
    },
  ],
};
```

### Child element types

| Type          | Fields         | Description                       |
| ------------- | -------------- | --------------------------------- |
| `text`        | `content`      | Plain text paragraph              |
| `divider`     | `n/a`          | Horizontal rule                   |
| `link-button` | `label`, `url` | Clickable button that opens a URL |
| `actions`     | `children`     | Container for link buttons        |

## Sending a card

Pass the card object and a `fallbackText` string to `thread.post()`. The fallback is used by email clients that don't render HTML.

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
chat.onNewMention(async (thread, message) => {
  await thread.subscribe();
  await thread.post({
    card: {
      type: 'card',
      title: 'Welcome!',
      subtitle: 'Thanks for reaching out',
      children: [
        {
          type: 'text',
          content: "Hi! Thanks for emailing us. We'll get back to you shortly.",
        },
        { type: 'divider' },
        {
          type: 'actions',
          children: [
            {
              type: 'link-button',
              label: 'Visit our website',
              url: 'https://resend.com',
            },
          ],
        },
      ],
    },
    fallbackText: 'Welcome! Thanks for reaching out.',
  });
});
```

<Info>
  Always include `fallbackText`. Some email clients strip HTML entirely, and the fallback text is what recipients will see in that case.
</Info>

## Try it yourself

<Card title="Welcome Cards Example" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-chat-sdk/tree/main/examples/welcome-cards">
  Full working example that sends a styled card on first contact
</Card>


# Chat SDK Proactive Outreach
Source: https://resend.com/docs/chat-sdk-proactive-outreach

Start new email conversations proactively with the Chat SDK adapter.

By default, the Chat SDK adapter responds to inbound emails. With `openDM`, you can go the other way and start a new email thread with any address, without waiting for them to email you first.

## Sending a proactive email

Call `openDM` on the adapter to create a new thread, then post a message to it.

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
const threadId = await chat.adapters.resend.openDM('user@example.com');
const thread = await chat.thread('resend', threadId);
await thread.post('Hello from the bot!');
```

You can also send card emails in proactive threads. The same card structure from [Card Emails](/docs/chat-sdk-card-emails) works here.

## Triggering via HTTP

A common pattern is exposing an HTTP endpoint that triggers outbound emails. This lets external systems (cron jobs, webhooks from other services, admin dashboards) send emails through your bot.

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
async function handleNotify(req, res) {
  const { to, message } = JSON.parse(await readBody(req));

  const threadId = await chat.adapters.resend.openDM(to);
  const thread = await chat.thread('resend', threadId);
  await thread.post(message);

  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ ok: true, threadId }));
}
```

Then call it:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X POST http://localhost:3000/notify \
  -H "Content-Type: application/json" \
  -d '{"to": "user@example.com", "message": "Your order has shipped!"}'
```

## When to use this

* Welcome emails when a user signs up
* Order confirmations and shipping updates
* Alert notifications (monitoring, billing, security)
* Scheduled digests or reminders

If the recipient replies, the response arrives through the normal `onNewMention` or `onSubscribedMessage` handlers, and the threading is handled automatically.

## Try it yourself

<Card title="Notifications Example" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-chat-sdk/tree/main/examples/notifications">
  Proactive outbound emails via openDM and an HTTP POST endpoint
</Card>


# Resend CLI
Source: https://resend.com/docs/cli

The official command-line tool for Resend. Send emails, manage your account, and develop locally from the terminal.

The [Resend CLI](https://github.com/resend/resend-cli) is the official command-line interface for Resend. It covers the full API surface and is built for humans, AI agents, and CI/CD pipelines.

## Installation

<Tabs>
  <Tab title="cURL">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    curl -fsSL https://resend.com/install.sh | bash
    ```
  </Tab>

  <Tab title="npm">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    npm install -g resend-cli
    ```
  </Tab>

  <Tab title="Homebrew">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    brew install resend/cli/resend
    ```
  </Tab>

  <Tab title="PowerShell (Windows)">
    ```powershell theme={"theme":{"light":"github-light","dark":"vesper"}}
    irm https://resend.com/install.ps1 | iex
    ```
  </Tab>
</Tabs>

## Authentication

The CLI resolves your API key using the following priority chain:

| Priority    | Source                   | How to set                                |
| ----------- | ------------------------ | ----------------------------------------- |
| 1 (highest) | `--api-key` flag         | `resend --api-key re_xxx emails send ...` |
| 2           | `RESEND_API_KEY` env var | `export RESEND_API_KEY=re_xxx`            |
| 3 (lowest)  | Saved credentials        | `resend login`                            |

If no key is found from any source, the CLI errors with code `auth_error`.

**`resend login`**

Authenticate by storing your API key locally. The key is validated against the Resend API before being saved.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend login
```

In a terminal, the command prompts for your key via masked input. In non-interactive environments (CI, pipes), use the `--key` flag:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend login --key re_xxxxxxxxxxxxx
```

Credentials are saved to your system's secure credential storage (macOS Keychain, Windows Credential Manager, or Linux secret service).

| Flag          | Description                                         |
| ------------- | --------------------------------------------------- |
| `--key <key>` | API key to store (required in non-interactive mode) |

**`resend logout`**

Remove your saved API key.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend logout
```

**Switch between profiles**

If you work across multiple Resend teams or accounts, switch between profiles without logging in and out:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend auth switch
```

Use the global `--profile` flag on any command to run it with a specific profile:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend domains list --profile production
```

Other profile management commands:

| Command                          | Description                        |
| -------------------------------- | ---------------------------------- |
| `resend auth list`               | List all profiles                  |
| `resend auth switch [name]`      | Switch the active profile          |
| `resend auth rename [old] [new]` | Rename a profile                   |
| `resend auth remove [name]`      | Remove a profile                   |
| `resend whoami`                  | Show current authentication status |

## Emails

Send, retrieve, cancel, and manage email delivery.

**`resend emails send`**

Send an email. Provide all options via flags for scripting, or let the CLI prompt interactively for missing fields.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend emails send \
  --from "Acme <onboarding@resend.dev>" \
  --to delivered@resend.dev \
  --subject "Hello World" \
  --text "It works!"
```

| Flag                        | Required         | Description                                                |
| --------------------------- | ---------------- | ---------------------------------------------------------- |
| `--from <address>`          | Yes \*           | Sender email address (must be from a verified domain)      |
| `--to <addresses...>`       | Yes              | One or more recipient email addresses (space-separated)    |
| `--subject <subject>`       | Yes \*           | Email subject line                                         |
| `--text <text>`             | One of text/html | Plain text body                                            |
| `--text-file <path>`        | One of text/html | Path to a plain text file (use `-` for stdin)              |
| `--html <html>`             | One of text/html | HTML body as a string                                      |
| `--html-file <path>`        | One of text/html | Path to an HTML file (use `-` for stdin)                   |
| `--react-email <path>`      | One of text/html | Path to a React Email template (`.tsx`) to render and send |
| `--cc <addresses...>`       | No               | CC recipients                                              |
| `--bcc <addresses...>`      | No               | BCC recipients                                             |
| `--reply-to <address>`      | No               | Reply-to email address                                     |
| `--scheduled-at <datetime>` | No               | Schedule for later (ISO 8601 or natural language)          |
| `--attachment <paths...>`   | No               | File path(s) to attach                                     |
| `--headers <key=value...>`  | No               | Custom headers as key=value pairs                          |
| `--tags <name=value...>`    | No               | Email tags as name=value pairs                             |
| `--idempotency-key <key>`   | No               | Deduplicate this send request                              |
| `--template <id>`           | No               | Template ID to use                                         |
| `--var <key=value...>`      | No               | Template variables as key=value pairs                      |

\* Not required when using `--template`, which provides them.

**Examples:**

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
# HTML from a file
resend emails send \
  --from "Acme <onboarding@resend.dev>" \
  --to delivered@resend.dev \
  --subject "Hello World" \
  --html-file ./welcome.html

# Multiple recipients with CC, BCC, and reply-to
resend emails send \
  --from "Acme <onboarding@resend.dev>" \
  --to delivered@resend.dev \
  --subject "Hello World" \
  --text "It works!" \
  --cc manager@example.com \
  --bcc archive@example.com \
  --reply-to noreply@example.com

# Send a React Email template
resend emails send \
  --from "Acme <onboarding@resend.dev>" \
  --to delivered@resend.dev \
  --subject "Hello World" \
  --react-email ./emails/welcome.tsx

# Send with a template
resend emails send \
  --from "Acme <onboarding@resend.dev>" \
  --to delivered@resend.dev \
  --template tmpl_xxxxx \
  --var "name=Alice" --var "company=Acme"
```

**`resend emails batch`**

Send up to 100 emails in a single API request from a JSON file.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend emails batch --file ./emails.json
```

| Flag                        | Required | Description                                                                                |
| --------------------------- | -------- | ------------------------------------------------------------------------------------------ |
| `--file <path>`             | Yes      | Path to JSON file containing array of email objects (use `-` for stdin)                    |
| `--react-email <path>`      | No       | Path to a React Email template (`.tsx`). Rendered HTML applies to every email in the batch |
| `--idempotency-key <key>`   | No       | Deduplicate this batch request                                                             |
| `--batch-validation <mode>` | No       | `strict` (default, entire batch fails on any error) or `permissive`                        |

Each email in the JSON array supports the same fields as `resend emails send`, including per-email `scheduled_at` (natural language or ISO 8601) and `tags`. The `attachments` field is not supported in batch sends.

```json emails.json theme={"theme":{"light":"github-light","dark":"vesper"}}
[
  {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["foo@gmail.com"],
    "subject": "hello world",
    "html": "<h1>it works!</h1>",
    "scheduled_at": "in 1 min",
    "tags": [{ "name": "category", "value": "welcome" }]
  },
  {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["bar@outlook.com"],
    "subject": "world hello",
    "html": "<p>it works!</p>",
    "scheduled_at": "in 5 min"
  }
]
```

**Other email commands**

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend emails list                # List sent emails
resend emails get <id>            # Retrieve a sent email by ID
resend emails cancel <id>         # Cancel a scheduled email
resend emails update <id>         # Update a scheduled email's send time
```

## Receiving

Process inbound emails, download attachments, and stream incoming messages.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend emails receiving list              # List received (inbound) emails
resend emails receiving get <id>          # Retrieve a received email with full details
resend emails receiving listen            # Poll for new inbound emails as they arrive
resend emails receiving forward <id>      # Forward a received email
resend emails receiving attachments <id>  # List attachments for a received email
resend emails receiving attachment <id> <attachment-id>  # Download a specific attachment
```

## Domains

Manage your sending and receiving domains.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend domains create --name example.com --region us-east-1
resend domains list               # List all domains
resend domains get <id>           # Retrieve domain with DNS records
resend domains verify <id>        # Trigger DNS verification
resend domains update <id>        # Update TLS, tracking, or receiving settings
resend domains delete <id>        # Delete a domain
```

## API Keys

Create, list, and revoke API keys for programmatic access.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend api-keys create --name "Production" --permission full_access
resend api-keys list              # List all API keys
resend api-keys delete <id>       # Delete an API key
```

## Broadcasts

Create and send broadcast emails to segments.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend broadcasts create \
  --from "Acme <onboarding@resend.dev>" \
  --subject "Product update" \
  --segment-id seg_xxxxx \
  --html-file ./broadcast.html \
  --send
resend broadcasts list            # List all broadcasts
resend broadcasts get <id>        # Retrieve broadcast details
resend broadcasts send <id>       # Send a draft broadcast
resend broadcasts update <id>     # Update a draft broadcast
resend broadcasts delete <id>     # Delete a broadcast
resend broadcasts open [id]       # Open a broadcast in the dashboard
```

## Contacts

Manage contacts, segment membership, and topic subscriptions.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend contacts create --email steve.wozniak@gmail.com --first-name Steve
resend contacts list              # List all contacts
resend contacts get <id>          # Retrieve a contact by ID or email
resend contacts update <id>       # Update contact properties
resend contacts delete <id>       # Delete a contact
resend contacts segments <id>     # List segments a contact belongs to
resend contacts add-segment <id>  # Add a contact to a segment
resend contacts remove-segment <id> <segment-id>  # Remove from a segment
resend contacts topics <id>       # List topic subscriptions
resend contacts update-topics <id>  # Update topic subscriptions
resend contacts imports create --file ./contacts.csv  # Import contacts from CSV
resend contacts imports get <id>   # Retrieve import status and counts
resend contacts imports list       # List past contact imports
```

**`resend contacts imports create`**

Start an asynchronous CSV import. The command uploads the file and returns a
contact import ID immediately. Use `resend contacts imports get <id>` to check
processing status.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend contacts imports create \
  --file ./contacts.csv \
  --column-map '{"email":"Email","firstName":"First Name","lastName":"Last Name"}' \
  --on-conflict upsert
```

| Flag                   | Required | Description                                                                    |
| ---------------------- | -------- | ------------------------------------------------------------------------------ |
| `--file <path>`        | Yes      | Path to the CSV file to import. Maximum file size is 200MB                     |
| `--column-map <json>`  | No       | JSON object mapping CSV headers to contact fields                              |
| `--on-conflict <mode>` | No       | `upsert` to update existing contacts or `skip` to leave them unchanged         |
| `--segment-id <id...>` | No       | Segment IDs to add imported contacts to. Repeat the flag for multiple segments |
| `--topics <json>`      | No       | JSON array of topic subscriptions with `id` and `subscription` fields          |

Without `--column-map`, CSV headers must match the lowercase contact field
names exactly: `email`, `first_name`, and `last_name`. Use `--column-map` when
your CSV uses headers like `Email` or `First Name`.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
# Import contacts and add them to a segment
resend contacts imports create \
  --file ./contacts.csv \
  --segment-id 78261eea-8f8b-4381-83c6-79fa7120f1cf

# Map custom properties and topic subscriptions
resend contacts imports create \
  --file ./contacts.csv \
  --column-map '{"email":"Email","properties":{"plan":{"column":"Plan","type":"string"}}}' \
  --topics '[{"id":"b6d24b8e-af0b-4c3c-be0c-359bbd97381e","subscription":"opt_in"}]'
```

**`resend contacts imports get`**

Retrieve a contact import by ID, including status and row counts.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend contacts imports get 479e3145-dd38-476b-932c-529ceb705947
```

**`resend contacts imports list`**

List contact imports. The default limit is `10`.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend contacts imports list --status completed
```

| Flag                | Required | Description                                                        |
| ------------------- | -------- | ------------------------------------------------------------------ |
| `--limit <n>`       | No       | Maximum number of imports to return. Must be between `1` and `100` |
| `--after <cursor>`  | No       | Return imports after this contact import ID                        |
| `--before <cursor>` | No       | Return imports before this contact import ID                       |
| `--status <status>` | No       | Filter by `queued`, `in_progress`, `completed`, or `failed`        |

## Contact Properties

Define custom properties to store additional data on contacts.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend contact-properties create --key "company" --type string
resend contact-properties list | get | update | delete
```

## Segments

Group contacts into targetable segments for broadcasts.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend segments create --name "VIPs"
resend segments list              # List all segments
resend segments get <id>          # Retrieve a segment by ID
resend segments contacts <id>     # List contacts in a segment
resend segments delete <id>       # Delete a segment
```

## Topics

Manage subscription topics that contacts can opt in or out of.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend topics create --name "Product updates"
resend topics list | get | update | delete
```

## Suppressions

Manage the suppression list.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend suppressions list                              # List suppressed addresses (alias: ls)
resend suppressions list --origin bounce              # Filter by origin: bounce | complaint | manual
resend suppressions add spam@example.com              # Suppress a single address
resend suppressions get spam@example.com              # Retrieve by ID or email
resend suppressions delete spam@example.com --yes     # Remove by ID or email (alias: rm)
resend suppressions batch add --file ./emails.json    # Suppress up to 100 from a JSON array of emails
resend suppressions batch remove --file ./emails.json # Remove up to 100 (add --ids to treat entries as IDs)
```

## Templates

Create and manage email templates.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend templates create --name "Welcome" --subject "Welcome to Acme" --react-email ./emails/welcome.tsx
resend templates list             # List all templates
resend templates get <id>         # Retrieve a template by ID or alias
resend templates update <id>      # Update a template
resend templates publish <id>     # Publish a draft template
resend templates duplicate <id>   # Duplicate a template
resend templates delete <id>      # Delete a template
resend templates open [id]        # Open a template in the dashboard
```

## Logs

View API request logs.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend logs list              # List API request logs
resend logs get <id>          # Retrieve a log with full request/response bodies
resend logs open [id]         # Open logs in the dashboard
```

## Webhooks

Register endpoints and listen for email event notifications.

**`resend webhooks create`**

Register a webhook endpoint.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend webhooks create \
  --endpoint https://example.com/webhook \
  --events email.sent email.delivered
```

| Flag                  | Required | Description                                            |
| --------------------- | -------- | ------------------------------------------------------ |
| `--endpoint <url>`    | Yes      | HTTPS URL to receive events                            |
| `--events <types...>` | Yes      | Event types to subscribe to (use `all` for all events) |

**`resend webhooks listen`**

Listen for webhook events locally during development. Starts a server, registers a temporary webhook, streams events, and cleans up on exit.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend webhooks listen \
  --url https://hostname.tailnet-name.ts.net \
  --events email.received
```

| Flag                  | Required | Description                                                       |
| --------------------- | -------- | ----------------------------------------------------------------- |
| `--url <url>`         | Yes      | Your public URL (e.g., Tailscale Funnel URL)                      |
| `--events <types...>` | No       | Event types to listen for (default: `all`)                        |
| `--forward-to <url>`  | No       | Forward payloads to a local server (passes original Svix headers) |
| `--port <port>`       | No       | Local server port (default: 4318)                                 |

<Info>
  See the [webhook events documentation](/docs/webhooks/event-types) for the full
  list of available event types. For agent-specific webhook patterns, see [CLI
  for AI Agents](/docs/cli-agents#closing-the-loop-with-webhooks).
</Info>

**Other webhook commands**

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend webhooks list              # List all webhook endpoints
resend webhooks get <id>          # Retrieve a webhook configuration
resend webhooks update <id>       # Update endpoint URL, events, or status
resend webhooks delete <id>       # Delete a webhook endpoint
```

<Tip>
  Run `resend <command> --help` for the full list of flags and options on any command.
</Tip>

## Automations

Create, manage, and monitor event-driven automation workflows.

**`resend automations create`**

Create a new automation from a JSON file describing the workflow graph.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend automations create --file ./automation.json
```

| Flag                   | Required | Description                                                        |
| ---------------------- | -------- | ------------------------------------------------------------------ |
| `--name <name>`        | Yes \*   | Automation name                                                    |
| `--status <status>`    | No       | Initial status: `enabled` or `disabled` (default: `disabled`)      |
| `--steps <json>`       | Yes \*   | Steps array as JSON string                                         |
| `--connections <json>` | Yes \*   | Connections array as JSON string                                   |
| `--file <path>`        | Yes \*   | Path to JSON file with full automation payload (use `-` for stdin) |

\* Provide `--file`, or `--name` with `--steps` and `--connections`. When using `--file`, other flags override file values.

**Other automation commands**

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend automations list              # List all automations
resend automations get <id>          # Retrieve an automation with steps and connections
resend automations update <id>       # Update an automation's status (enable or disable)
resend automations stop <id>         # Stop an enabled automation
resend automations delete <id>       # Delete an automation
resend automations open [id]         # Open an automation in the dashboard
```

**Automation runs**

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend automations runs list <automation-id>                    # List runs for an automation
resend automations runs list <automation-id> --status running   # Filter by status
resend automations runs get --automation-id <id> --run-id <id>  # Retrieve a specific run
```

| Flag                | Required | Description                                                                       |
| ------------------- | -------- | --------------------------------------------------------------------------------- |
| `--status <status>` | No       | Filter by status: `running`, `completed`, `failed`, `cancelled` (comma-separated) |

## Events

Define and send events that trigger automations.

**`resend events send`**

Send an event to trigger matching automations for a contact.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend events send \
  --event user.created \
  --email steve.wozniak@gmail.com \
  --payload '{"plan":"pro"}'
```

| Flag                | Required       | Description                                            |
| ------------------- | -------------- | ------------------------------------------------------ |
| `--event <name>`    | Yes            | Event name (e.g. `user.created`)                       |
| `--contact-id <id>` | One of contact | Contact ID (mutually exclusive with `--email`)         |
| `--email <email>`   | One of contact | Contact email (mutually exclusive with `--contact-id`) |
| `--payload <json>`  | No             | Event payload as JSON string                           |

**Other event commands**

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend events create --name user.created --schema '{"plan":"string"}'
resend events list                   # List all event definitions
resend events get <id>               # Retrieve an event by ID or name
resend events update <id>            # Update an event's schema
resend events delete <id>            # Delete an event definition
resend events open                   # Open events in the dashboard
```

## Utility

Diagnose your setup, manage authentication, and configure shell completions.

**`resend doctor`**

Run environment diagnostics. Verifies your CLI version, API key, credential storage, and domain status.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend doctor
```

| Check                  | Pass                                  | Warn                                         | Fail            |
| ---------------------- | ------------------------------------- | -------------------------------------------- | --------------- |
| **CLI Version**        | Running latest                        | Update available                             | N/A             |
| **API Key**            | Key found (shows masked key + source) | N/A                                          | No key found    |
| **Credential Storage** | Secure backend (e.g., macOS Keychain) | Plaintext file fallback                      | N/A             |
| **API Validation**     | Verified domains exist                | Sending-only key, no domains, or all pending | API key invalid |

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
# JSON output
resend doctor --json
```

```json theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "ok": true,
  "checks": [
    { "name": "CLI Version", "status": "pass", "message": "v1.7.0 (latest)" },
    {
      "name": "API Key",
      "status": "pass",
      "message": "re_...xxxx (source: env)"
    },
    {
      "name": "Credential Storage",
      "status": "pass",
      "message": "macOS Keychain"
    },
    { "name": "Domains", "status": "pass", "message": "2 verified, 0 pending" }
  ]
}
```

Exits `0` when all checks pass or warn. Exits `1` if any check fails.

**Other utility commands**

| Command                       | Description                                                     |
| ----------------------------- | --------------------------------------------------------------- |
| `resend whoami`               | Show current authentication status                              |
| `resend open`                 | Open the Resend dashboard in your browser                       |
| `resend update`               | Check for available CLI updates                                 |
| `resend completion [shell]`   | Generate shell completion scripts (bash, zsh, fish, powershell) |
| `resend completion --install` | Auto-install completions into your shell profile                |

## Global options

These flags work on every command:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend [global options] <command> [command options]
```

| Flag                   | Description                                            |
| ---------------------- | ------------------------------------------------------ |
| `--api-key <key>`      | Override API key for this invocation                   |
| `-p, --profile <name>` | Profile to use (overrides `RESEND_PROFILE` env var)    |
| `--json`               | Force JSON output even in interactive terminals        |
| `-q, --quiet`          | Suppress spinners and status output (implies `--json`) |
| `--insecure-storage`   | Save API key as plaintext instead of secure storage    |
| `--version`            | Print version and exit                                 |
| `--help`               | Show help text                                         |

## Output behavior

The CLI has two output modes that switch automatically:

| Mode            | When                   | Stdout         | Stderr            |
| --------------- | ---------------------- | -------------- | ----------------- |
| **Interactive** | Terminal (TTY)         | Formatted text | Spinners, prompts |
| **Machine**     | Piped, CI, or `--json` | JSON           | Nothing           |

Pipe to another command and JSON output activates:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend doctor | jq '.checks[].name'
resend emails send \
  --from "Acme <onboarding@resend.dev>" \
  --to delivered@resend.dev \
  --subject "Hello World" \
  --text "It works!" | jq '.id'
```

Errors always exit with code `1` and output structured JSON:

```json theme={"theme":{"light":"github-light","dark":"vesper"}}
{ "error": { "message": "No API key found", "code": "auth_error" } }
```

## CI/CD

Set `RESEND_API_KEY` as an environment variable, with no `resend login` needed:

```yaml theme={"theme":{"light":"github-light","dark":"vesper"}}
# GitHub Actions
env:
  RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }}
steps:
  - run: |
      resend emails send \
        --from "Acme <onboarding@resend.dev>" \
        --to delivered@resend.dev \
        --subject "Deploy complete" \
        --text "Version ${{ github.sha }} deployed."
```

## Configuration

| Item              | Path                  | Notes                                                               |
| ----------------- | --------------------- | ------------------------------------------------------------------- |
| Config directory  | `~/.config/resend/`   | Respects `$XDG_CONFIG_HOME` on Linux, `%APPDATA%` on Windows        |
| Credentials       | System secure storage | macOS Keychain, Windows Credential Manager, or Linux secret service |
| Install directory | `~/.resend/bin/`      | Respects `$RESEND_INSTALL`                                          |

<Card title="Using the CLI with AI Agents" icon="microchip-ai" href="/cli-agents">
  Learn about Agent Skills, non-interactive mode, and local webhook development
  for AI agents.
</Card>


# Resend CLI for AI Agents
Source: https://resend.com/docs/cli-agents

How to use the Resend CLI in AI agent workflows.

The [Resend CLI](/docs/cli) works out of the box for AI agents and CI/CD pipelines. This page covers agent-specific behavior. See the [CLI reference](/docs/cli) for installation, commands, and full documentation.

## Agent Skills

The Resend CLI includes built-in Agent Skills that help AI agents understand how to use the CLI effectively.

Install the skill using the following command:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
npx skills add resend/resend-cli
```

## Non-interactive mode

When the CLI detects a non-TTY environment (piped output, CI runner, or the `--json` flag), it automatically switches to machine-readable mode:

* **Output:** JSON to stdout, no progress indicators
* **Exit codes:** `0` for success, `1` for errors
* **Errors:** Always include `message` and `code` fields

```json theme={"theme":{"light":"github-light","dark":"vesper"}}
{ "error": { "message": "No API key found", "code": "auth_error" } }
```

All required flags must be provided. Interactive prompts are disabled. Missing flags cause an error listing what's needed.

## Piping from stdin

Agents generate content on the fly. Pass `-` to read from stdin instead of writing temp files:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
echo "Your order has shipped." | resend emails send \
  --from "Acme <onboarding@resend.dev>" \
  --to delivered@resend.dev \
  --subject "Order update" \
  --text-file -
```

This works with `--html-file -` on send and `--file -` on [batch commands](/docs/cli#emails).

## Batch sending

Send up to 100 emails in a single request by piping a JSON array into `emails batch`:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
cat emails.json | resend emails batch --file -
```

## Safe retries

Add `--idempotency-key` to prevent duplicates when your agent retries a failed request:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend emails send \
  --from "Acme <onboarding@resend.dev>" \
  --to delivered@resend.dev \
  --subject "Welcome" \
  --text "Hello!" \
  --idempotency-key "welcome-user-123"
```

This flag is available on both `emails send` and `emails batch`.

## Scheduling

The `--scheduled-at` flag accepts ISO 8601 timestamps and natural language:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend emails send \
  --from "Acme <onboarding@resend.dev>" \
  --to delivered@resend.dev \
  --subject "Your trial ends soon" \
  --text "Your free trial expires in 3 days." \
  --scheduled-at "tomorrow at 9am ET"
```

Cancel or reschedule with `resend emails cancel <id>` and `resend emails update <id> --scheduled-at <datetime>`.

## Reading inbound emails

Agents can process incoming email as an input source. Stream inbound emails as NDJSON with `emails receiving listen`:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend emails receiving listen --json
```

Or fetch a specific email with full content and attachments:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend emails receiving get <email-id>
```

This requires a [verified domain](/docs/dashboard/domains/introduction) with receiving enabled.

## Closing the loop with webhooks

When an agent sends an email, it often needs to know what happened next: was it delivered, did it bounce, did the recipient reply? The `webhooks listen` command gives your agent a real-time feedback loop by streaming [webhook events](/docs/webhooks/event-types) directly to the terminal.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend webhooks listen \
  --url https://hostname.tailnet-name.ts.net \
  --events email.delivered email.bounced email.received
```

The CLI registers a temporary webhook, streams matching events as JSON to stdout, and deletes the webhook when you exit (`Ctrl+C`). Use `--forward-to` to pipe payloads to a local server for processing:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
resend webhooks listen \
  --url https://hostname.tailnet-name.ts.net \
  --forward-to http://localhost:4321/api/webhook
```

The `--url` flag takes any public URL that points to the local server port (`4318` by default). Use any tunnel, such as [Tailscale Funnel](https://tailscale.com/kb/1223/funnel), [ngrok](https://ngrok.com/), or [localtunnel](https://theboringtech.io/).

<Tip>
  For a permanent setup, deploy a webhook handler and register it via `resend
      webhooks create` pointing to your production URL.
</Tip>


# Send emails with Resend CLI
Source: https://resend.com/docs/cli-quickstart

Learn how to send your first email using the Resend CLI.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    <Tabs>
      <Tab title="cURL">
        ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
        curl -fsSL https://resend.com/install.sh | bash
        ```
      </Tab>

      <Tab title="npm">
        ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
        npm install -g resend-cli
        ```
      </Tab>

      <Tab title="Homebrew">
        ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
        brew install resend/cli/resend
        ```
      </Tab>

      <Tab title="PowerShell (Windows)">
        ```powershell theme={"theme":{"light":"github-light","dark":"vesper"}}
        irm https://resend.com/install.ps1 | iex
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Authenticate">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    resend login
    ```
  </Step>

  <Step title="Send email">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    resend emails send \
      --from "Acme <onboarding@resend.dev>" \
      --to delivered@resend.dev \
      --subject "Hello World" \
      --text "Sent from my terminal."
    ```
  </Step>
</Steps>

## Next steps

<Card title="CLI Reference" icon="terminal" href="/cli">
  Explore the full command reference, authentication options, and CI/CD
  examples.
</Card>


# Create an API key
Source: https://resend.com/docs/create-an-api-key

Get started sending emails by creating an API key

## Resend API keys

API Keys are secret tokens used to authenticate your requests. They are unique to your account and must be kept confidential.

You must create at least one API key to use the Resend platform through code (e.g., SDKs, API, command-line interface (CLI), or AI tools).

## Create an API Key

You can create API keys in four ways:

* in the [**API keys** Dashboard page](/docs/dashboard/api-keys/introduction)
* using the [Resend API](/docs/api-reference/api-keys/create-api-key)
* with a [Resend CLI command](/docs/cli#api-keys)
* with the [Resend MCP server](/docs/mcp-server)

To create a new API Key from the Resend Dashboard:

<Steps>
  <Step title="In your Resend Dashboard, navigate to the API keys page." />

  <Step title="Click the Create API Key button." />

  <Step title="Provide a name for your API Key.">
    Choose a name (maximum 50 characters) to identify your key.
  </Step>

  <Step title="Select a permission for your API key.">
    Choose **"Sending access"** to grant access to only sending emails unless your key needs full access to Resend’s API to create, delete, get, and update any resource.

    This [API key permission](/docs/api-reference/api-keys/create-api-key#param-permission) can be updated at any time.
  </Step>

  <Step title="(Optional) Restrict sending to a specific domain">
    If you selected **"Sending access"**, you can further choose the domain you want to restrict access to.
  </Step>
</Steps>

<img alt="Add API Key modal in the Resend Dashboard" />

<Note>
  For security reasons, you can only view the API Key once. Learn more about
  [API key best practices](/docs/knowledge-base/how-to-handle-api-keys).
</Note>

## Use the API key in your code

Authenticate your requests by adding your Resend API key to your project as an environment variable.

You can check the [quickstart guides](/docs/introduction) or [AI builder guides](/docs/ai-onboarding#ai-builder-guides) for specific examples of passing your API key to your project.

<Steps>
  <Step title="Create and store an environment variable">
    Store your API key as an environment variable in your project. This is commonly done inside a special file or configuration panel and will depend on your language, framework, or development platform.

    For example, Node.js projects commonly store both public and secret variables in a `.env` file at the root of your project:

    ```sh .env theme={"theme":{"light":"github-light","dark":"vesper"}}
    RESEND_API_KEY=re_xxxxxxxxx
    ```

    <Tip>
      If you are storing your secrets in a project file, you may need to add this file to your `.gitignore` file to prevent it from being committed to version control.

      Many frameworks add `.env` to the `.gitignore` file by default, so this may already exist.

      ```ts .gitignore theme={"theme":{"light":"github-light","dark":"vesper"}}
      .env
      ```
    </Tip>
  </Step>

  <Step title="Pass the environment variable to your code">
    Your project environment variables are not automatically available to Resend. You must explicitly pass your API key value to your Resend code.

    For example, whenever you create a new Resend instance in a Node.js project, you must pass the environment variable on `process.env`:

    ```ts app.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    const resend = new Resend(process.env.RESEND_API_KEY);
    ```

    <Note>
      On Node.js `v20` and later, you can pass your `.env` file's variables to your script using the `--env-file=.env` flag. Alternatively, you can use the `dotenv` package to load the variables.
    </Note>
  </Step>
</Steps>

## Learn more

<CardGroup>
  <Card title="Manage API keys" icon="tools" href="/dashboard/api-keys/introduction">
    View, create, edit, delete, and manage your API keys.
  </Card>

  <Card title="API key best practices" icon="thumbs-up" href="/knowledge-base/how-to-handle-api-keys">
    Learn about best practices for managing your API keys.
  </Card>
</CardGroup>

## Next steps

<CardGroup>
  <Card title="Add a domain" icon="globe" href="/add-a-domain">
    Add and verify a domain you own to start sending emails.
  </Card>

  <Card title="Quickstart tutorials" icon="stopwatch" href="/introduction">
    Send your first transactional email with a quick tutorial for your language
    or framework.
  </Card>
</CardGroup>


# Manage API keys
Source: https://resend.com/docs/dashboard/api-keys/introduction

Learn how to view, edit, and delete your API keys in Resend.

## API keys

API keys are secret tokens used to authenticate your requests. They are unique to your account and must be kept confidential.

You can use multiple keys to isolate different application actions to different API keys. This allows you to [view logs per key](#view-api-key-logs), detect possible abuse, and control any damage that may be done accidentally or maliciously.

## API key management

You can view and manage your API keys from the [**API keys** Dashboard page](https://resend.com/api-keys). You can also create, list, or delete your API keys using the [API](/docs/api-reference/api-keys/create-api-key), or the [Resend CLI](/docs/cli#api-keys).

## View all API keys

The [API Dashboard](https://resend.com/api-keys) shows you all the API keys you have created along with their details, including the **last time you used** an API key.

Different color indicators let you quickly scan and detect which API keys are being used and which are not.

<img alt="View All API keys" />

## Edit API key details

After [creating an API key](/docs/create-an-api-key), you can edit the following details:

* [Name](/docs/api-reference/api-keys/create-api-key#param-name)
* [Permission](/docs/api-reference/api-keys/create-api-key#param-permission)
* [Domain](/docs/api-reference/api-keys/create-api-key#domain-id)

<Info>You cannot view or edit an API key value after it has been created.</Info>

To edit an API key in the Resend Dashboard, click the **More options** <Icon icon="ellipsis" /> button and then **Edit API key**.

<img alt="View Inactive API key" />

## Delete inactive API keys

If an API key **hasn't been used in the last 30 days**, consider deleting it to keep your account secure.

<img alt="View Inactive API key" />

You can delete an API key by clicking the **More options** <Icon icon="ellipsis" /> button and then **Remove API key**.

<img alt="Delete API key" />

<Tip>
  See more [API key security practices](/docs/knowledge-base/how-to-handle-api-keys).
</Tip>

## View API key logs

When visualizing an active API key, you can see the **total number of requests** made to the key. For more detailed logging information, select the underlined number of requests to view all logs for that API key.

<img alt="View Active API key" />

## Export your data

Admins can download your data in CSV format for the following resources:

* Emails
* Broadcasts
* Contacts
* Segments
* Domains
* Logs
* API keys

<Info>Currently, exports are limited to admin users of your team.</Info>

To start, apply filters to your data and click on the "Export" button. Confirm your filters before exporting your data.

<video />

If your exported data includes 1,000 items or less, the export will download immediately. For larger exports, you'll receive an email with a link to download your data.

All admins on your team can securely access the export for 7 days. Unavailable exports are marked as "Expired."

<Note>
  All exports your team creates are listed in the
  [Exports](https://resend.com/exports) page under **Settings** > **Team** >
  **Exports**. Select any export to view its details page. All members of your
  team can view your exports, but only admins can download the data.
</Note>


# Managing Contacts
Source: https://resend.com/docs/dashboard/audiences/contacts

Learn how to work with Contacts with Resend.

Contacts in Resend are global entities linked to a specific email address. After adding Contacts, send [Broadcasts](/docs/dashboard/broadcasts/introduction) to groups of Contacts.

<Tip>
  If you previously used our Audience model, learn how to [migrate to the new
  Contacts model](/docs/dashboard/segments/migrating-from-audiences-to-segments).
</Tip>

## Add Contacts

You can add Contacts one at a time via API or manually, or add many at once by [bulk uploading a CSV](#bulk-upload-by-csv).

### Add Contacts programmatically via API

You can add contacts programmatically using the [contacts](/docs/api-reference/contacts/create-contact) endpoint.

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  resend.contacts.create({
    email: 'steve.wozniak@gmail.com',
    firstName: 'Steve',
    lastName: 'Wozniak',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->contacts->create(
    parameters: [
      'email' => 'steve.wozniak@gmail.com',
      'first_name' => 'Steve',
      'last_name' => 'Wozniak',
    ]
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Contacts.CreateParams = {
    "email": "steve.wozniak@gmail.com",
    "first_name": "Steve",
    "last_name": "Wozniak",
  }

  resend.Contacts.create(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    "email": "steve.wozniak@gmail.com",
    "first_name": "Steve",
    "last_name": "Wozniak",
  }

  Resend::Contacts.create(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.CreateContactRequest{
  		Email:        "steve.wozniak@gmail.com",
  		FirstName:    "Steve",
  		LastName:     "Wozniak",
  		Unsubscribed: false,
  	}

  	client.Contacts.Create(params)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::ContactData, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let contact = ContactData::new("steve.wozniak@gmail.com")
      .with_first_name("Steve")
      .with_last_name("Wozniak");

    let _contact = resend
      .contacts
      .create(contact)
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateContactOptions params = CreateContactOptions.builder()
                  .email("steve.wozniak@gmail.com")
                  .firstName("Steve")
                  .lastName("Wozniak")
                  .build();

          CreateContactResponseSuccess data = resend.contacts().create(params);
      }
  }
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/contacts' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "email": "steve.wozniak@gmail.com",
    "first_name": "Steve",
    "last_name": "Wozniak"
  }'
  ```
</CodeGroup>

When creating a Contact, you can optionally set the following properties:

* `first_name`: The first name of the contact.
* `last_name`: The last name of the contact.
* `unsubscribed`: Whether the contact is unsubscribed from all Broadcasts.
* `properties`: A map of custom property keys and values to create (learn more about [custom properties](/docs/dashboard/audiences/properties)).

Once a Contact is created, you can update it using the [update contact](/docs/api-reference/contacts/update-contact) endpoint or [add the contact to a Segment](/docs/api-reference/contacts/add-contact-to-segment).

### Add Contacts by uploading a .csv

You can also add Contacts by uploading a .csv file. This is a convenient way to add multiple Contacts at once.

1. Go to the [Contacts](https://resend.com/audience) page, and select **Add Contacts**.
2. Select **Import CSV**.
3. Upload your CSV file from your computer.
4. Map the fields you want to use. You can map the fields to: `email`, `first_name`, `last_name`, and `unsubscribed`, or any Contact properties you've already created.
5. Optionally add the contacts to an existing Segment.
6. Select **Continue**, review the contacts, and finish the upload.

<Note>
  If a contact with the same email address already exists, the CSV upload will
  update the existing contact with the new data.
</Note>

### Add Contacts manually

1. Go to the [Contacts](https://resend.com/audience) page, and select **Add Contacts**.
2. Select **Add Manually**.
3. Add the email address of the contact in the text field (separated by commas or new lines for multiple contacts).
4. Optionally add the contact to an existing Segment.
5. Confirm and click **Add**.

<Note>
  Contacts are also created automatically when an
  [Automation](/docs/dashboard/automations/introduction) runs for an email address
  that doesn't yet exist in your Audience.
</Note>

## Bulk upload by CSV

You can add many Contacts at once by uploading a CSV file (up to 200MB), either from the dashboard or programmatically.

### From the dashboard

1. Go to the [Contacts](https://resend.com/audience) page, and select **Add Contacts**.
2. Select **Import CSV**.
3. Drag and drop or click to upload your CSV file from your computer.
4. Resend uses AI to read your column headers and suggest field mappings. Review and adjust the mappings to `email`, `first_name`, `last_name`, and `unsubscribed`, or to any existing Contact properties. You can also map a column to a new custom property and Resend will create it for you. Use the checkboxes to include or exclude individual columns. The `email` column is always included.
5. Optionally add the contacts to an existing Segment.
6. Select **Continue**, review the contacts, and finish the upload.

<Note>
  If a Contact with the same email address already exists, the import updates
  the existing Contact with the new data.
</Note>

### Using the API, CLI, or MCP

You can also create and track imports programmatically with the [Contacts Import API](/docs/api-reference/contacts/create-contact-import) and SDKs, the [CLI](/docs/cli#contacts), or the [MCP server](/docs/mcp-server). These support the same column mapping and let you set `on_conflict` to `upsert` (update existing Contacts) or `skip` (leave them untouched).

## Contact Properties

Contact Properties can be used to store additional information about your Contacts and then personalize your Broadcasts.

<img alt="Properties" />

Resend includes a few default properties:

* `first_name`: The first name of the contact.
* `last_name`: The last name of the contact.
* `unsubscribed`: Whether the contact is unsubscribed from all Broadcasts.
* `email`: The email address of the contact.

You can create additional custom Contact Properties for your Contacts to store additional information. These properties can be used to personalize your Broadcasts across all Segments.

Learn more about [Contact Properties](/docs/dashboard/audiences/properties).

## View Contacts

You can view your Contacts in the [Contacts](https://resend.com/audience) page.

1. Go to the [Contacts](https://resend.com/audience) page.
2. Click on the Contact you want to view.
3. View the Contact details.

Each Contact includes the metadata associated with the contact, as well as a full history of all marketing interactions with the Contact.

<img alt="View Contact" />

You can also retrieve a [single Contact](/docs/api-reference/contacts/get-contact) or [list all Contacts](/docs/api-reference/contacts/list-contacts) via the API or SDKs.

## Edit Contacts

1. Go to the [Contacts](https://resend.com/audience) page.
2. Click on the **More options** <Icon icon="ellipsis" /> button and then **Edit Contact**.
3. Edit the Contact details and choose **Save**.

You can edit any Contact property (excluding the email address), assign
the Contact to a [Segment](/docs/dashboard/segments/introduction) or [Topic](/docs/dashboard/topics/introduction), or unsubscribe the Contact from all Broadcasts.

You can also [update a Contact](/docs/api-reference/contacts/update-contact) via the API or SDKs using the `id` or `email` of the Contact.

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Update by contact id
  const { data, error } = await resend.contacts.update({
    id: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    unsubscribed: true,
  });

  // Update by contact email
  const { data, error } = await resend.contacts.update({
    email: 'acme@example.com',
    unsubscribed: true,
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Update by contact id
  $resend->contacts->update(
    id: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    parameters: [
      'unsubscribed' => true
    ]
  );

  // Update by contact email
  $resend->contacts->update(
    email: 'acme@example.com',
    parameters: [
      'unsubscribed' => true
    ]
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  # Update by contact id
  params: resend.Contacts.UpdateParams = {
    "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
    "unsubscribed": True,
  }

  resend.Contacts.update(params)

  # Update by contact email
  params: resend.Contacts.UpdateParams = {
    "email": "acme@example.com",
    "unsubscribed": True,
  }

  resend.Contacts.update(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  # Update by contact id
  params = {
    "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
    "unsubscribed": true,
  }

  Resend::Contacts.update(params)

  # Update by contact email
  params = {
    "email": "acme@example.com",
    "unsubscribed": true,
  }

  Resend::Contacts.update(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import "github.com/resend/resend-go/v3"

  client := resend.NewClient("re_xxxxxxxxx")

  // Update by contact id
  params := &resend.UpdateContactRequest{
    Id:           "e169aa45-1ecf-4183-9955-b1499d5701d3",
    Unsubscribed: true,
  }
  params.SetUnsubscribed(true)

  contact, err := client.Contacts.Update(params)

  // Update by contact email
  params = &resend.UpdateContactRequest{
    Email:        "acme@example.com",
    Unsubscribed: true,
  }
  params.SetUnsubscribed(true)

  contact, err := client.Contacts.Update(params)
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::ContactChanges, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let changes = ContactChanges::new().with_unsubscribed(true);

    // Update by contact id
    let _contact = resend
      .contacts
      .update("e169aa45-1ecf-4183-9955-b1499d5701d3", changes.clone())
      .await?;

    // Update by contact email
    let _contact = resend
      .contacts
      .update("acme@example.com", changes)
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          // Update by contact id
          UpdateContactOptions params = UpdateContactOptions.builder()
                  .id("e169aa45-1ecf-4183-9955-b1499d5701d3")
                  .unsubscribed(true)
                  .build();

          // Update by contact email
          UpdateContactOptions params = UpdateContactOptions.builder()
                  .email("acme@example.com")
                  .unsubscribed(true)
                  .build();

          UpdateContactResponseSuccess data = resend.contacts().update(params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  // By Id
  await resend.ContactUpdateAsync(
      contactId: new Guid( "e169aa45-1ecf-4183-9955-b1499d5701d3" ),
      new ContactData()
      {
          FirstName = "Stevie",
          LastName = "Wozniaks",
          IsUnsubscribed = true,
      }
  );

  // By Email
  await resend.ContactUpdateByEmailAsync(
      "acme@example.com",
      new ContactData()
      {
          FirstName = "Stevie",
          LastName = "Wozniaks",
          IsUnsubscribed = true,
      }
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Update by contact id
  curl -X PATCH 'https://api.resend.com/contacts/520784e2-887d-4c25-b53c-4ad46ad38100' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "unsubscribed": true
  }'

  # Update by contact email
  curl -X PATCH 'https://api.resend.com/contacts/acme@example.com' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "unsubscribed": true
  }'
  ```
</CodeGroup>

## Bulk Actions

You can perform actions on multiple Contacts at once by selecting them from the [Contacts](https://resend.com/audience) page.

1. Go to the [Contacts](https://resend.com/audience) page.
2. Select multiple Contacts by clicking the checkbox next to each Contact.
3. Click the **Edit** button in the bulk actions bar.
4. Choose an action:
   * **Add to segments**: Add the selected Contacts to one or more Segments.
   * **Subscribe to topics**: Subscribe the selected Contacts to one or more Topics.

You can also delete multiple Contacts at once by clicking the **Delete** button in the bulk actions bar.

## Delete Contacts

1. Go to the [Contacts](https://resend.com/audience) page.
2. Click on the **More options** <Icon icon="ellipsis" /> button and then **Delete Contact**.
3. Confirm the deletion.

You can also [delete a Contact](/docs/api-reference/contacts/delete-contact) via the API or SDKs.

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Delete by contact id
  const { data, error } = await resend.contacts.remove({
    id: '520784e2-887d-4c25-b53c-4ad46ad38100',
  });

  // Delete by contact email
  const { data, error } = await resend.contacts.remove({
    email: 'acme@example.com',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Delete by contact id
  $resend->contacts->remove(
    id: '520784e2-887d-4c25-b53c-4ad46ad38100'
  );

  // Delete by contact email
  $resend->contacts->remove(
    email: 'acme@example.com'
  );
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  # Delete by contact id
  resend.Contacts.remove(
    id="520784e2-887d-4c25-b53c-4ad46ad38100"
  )

  # Delete by contact email
  resend.Contacts.remove(
    email="acme@example.com"
  )
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  # Delete by contact id
  Resend::Contacts.remove(
    "520784e2-887d-4c25-b53c-4ad46ad38100"
  )

  # Delete by contact email
  Resend::Contacts.remove(
    email: "acme@example.com",
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import "github.com/resend/resend-go/v3"

  client := resend.NewClient("re_xxxxxxxxx")

  // Delete by contact id
  removed, err := client.Contacts.Remove(
    "520784e2-887d-4c25-b53c-4ad46ad38100"
  )

  // Delete by contact email
  removed, err := client.Contacts.Remove(
    "acme@example.com"
  )
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    // Delete by contact id
    let _deleted = resend
      .contacts
      .delete("520784e2-887d-4c25-b53c-4ad46ad38100")
      .await?;

    // Delete by contact email
    let _deleted = resend
      .contacts
      .delete("acme@example.com")
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          // Delete by contact id
          resend.contacts().remove(ContactRequestOptions.builder()
                          .id("520784e2-887d-4c25-b53c-4ad46ad38100")
                          .build());

          // Delete by contact email
          resend.contacts().remove(ContactRequestOptions.builder()
                          .email("acme@example.com")
                          .build());
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  // By Id
  await resend.ContactDeleteAsync(
      contactId: new Guid( "520784e2-887d-4c25-b53c-4ad46ad38100" )
  );

  // By Email
  await resend.ContactDeleteByEmailAsync(
      "acme@example.com"
  );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Delete by contact id
  curl -X DELETE 'https://api.resend.com/contacts/520784e2-887d-4c25-b53c-4ad46ad38100' \
       -H 'Authorization: Bearer re_xxxxxxxxx'

  # Deleted by contact email
  curl -X DELETE 'https://api.resend.com/contacts/acme@example.com' \
       -H 'Authorization: Bearer re_xxxxxxxxx'
  ```
</CodeGroup>


# Your Resend Audience
Source: https://resend.com/docs/dashboard/audiences/introduction

Learn how to manage your Contacts and send personalized Broadcasts to them.

The [Audience Page](https://resend.com/audience) is for your marketing Broadcasts and provides tools for managing your Contacts and sending personalized Broadcasts to them. [Broadcasts](/docs/dashboard/broadcasts/introduction) also handle all your unsubscribe flows for you automatically.

The Audience page includes four areas:

* [Contacts](#contacts): individual email addresses
* [Properties](#properties): custom properties for your Contacts
* [Segments](#segments): groups of Contacts for your organization
* [Topics](#topics): user-facing tools for managing email preferences

<img alt="Contacts" />

## Contacts

Contacts in Resend are global entities linked to a specific email address.

<img alt="Properties" />

Each Contact:

* is associated with a single email address
* can have custom properties
* can be in zero, one or multiple Segments
* can be opted in or out of Topics

Each Contact shows a history of all marketing interactions with the Contact.

You can import Contacts in bulk from a CSV (up to 200MB) using either the [dashboard](/docs/dashboard/audiences/contacts) or the [Contacts Import API](/docs/api-reference/contacts/create-contact-import) and SDKs. Both map CSV columns to Contact Properties (the dashboard uses AI to suggest matches and create new properties for you). API and SDK imports let you choose whether to `upsert` or `skip` existing Contacts.

Learn more about [Contacts](/docs/dashboard/audiences/contacts).

## Properties

Contact Properties can be used to store additional information about your Contacts and then personalize your Broadcasts.

<img alt="Properties" />

Resend includes a few default properties:

* `first_name`: The first name of the contact.
* `last_name`: The last name of the contact.
* `unsubscribed`: Whether the contact is unsubscribed from all Broadcasts.
* `email`: The email address of the contact.

You can create additional custom Contact Properties for your Contacts to store additional information. These properties can be used to personalize your Broadcasts across all Segments.

Learn more about [Contact Properties](/docs/dashboard/audiences/properties).

## Segments

Segments are groups of Contacts for your organization. You can use Segments to send emails to a specific group of Contacts using [Broadcasts](/docs/dashboard/broadcasts/introduction).

<img alt="Segment" />

Learn more about [Segments](/docs/dashboard/segments/introduction).

## Topics

Topics are user-facing tools for managing email preferences. You can use them to manage your Contacts' email preferences.

<img alt="Topics" />

When you send [Broadcasts](/docs/dashboard/broadcasts/introduction), you can optionally scope sending to a particular Topic. Not only does scoping your sending help you send more precisely, but it also allows your users to manage their preferences with more control.

<Tip>
  New to Topics? Learn [why and when to use
  them](/docs/knowledge-base/why-use-topics), including how they improve
  deliverability and differ from Segments.
</Tip>


# Managing Unsubscribed Contacts
Source: https://resend.com/docs/dashboard/audiences/managing-unsubscribe-list

Learn how to check and remove recipients who have unsubscribed to your marketing emails.

It's essential to update your Contact list when someone unsubscribes to maintain a good sender reputation.

Benefits of managing your unsubscribe list:

* reduces the likelihood of your emails being marked as spam
* improves deliverability for any other marketing or transactional emails you send

When you include an [unsubscribe link in your Broadcasts or Automations](/docs/dashboard/segments/introduction#automatic-unsubscribes), Resend will automatically handle the unsubscribe flow for you.

## Unsubscribe Statuses

The Contacts page shows the global unsubscribe status of each Contact.

<img alt="Unsubscribe Statuses" />

* **Unsubscribed**: the Contact has unsubscribed from all emails from your account.
* **Subscribed**: the Contact is subscribed to at least one Topic.

To filter by Status, click on the **All Statuses** filter next to the search bar, then select a value.

## Topic Subscription Statuses

You can view the subscription status of each Topic for a given Contact by clicking on the Contact's row.

<img alt="Topic Subscription Statuses" />

* **Subscribed**: the global subscription status for the Contact.
* **Topics**: the list of Topics the Contact is subscribed to.

You can also check a Contact's Topic subscription status [via the API or SDKs](/docs/api-reference/contacts/get-contact-topics).

## Updating a Topic Subscription for a Contact

You can update a Topic subscription for a Contact by clicking the **Edit** button in the Topic's row.

<img alt="Add Contact to Topic" />

You can also update a Topic subscription for a Contact [via the API or SDKs](/docs/api-reference/contacts/update-contact-topics).

### Bulk Subscribe to Topics

You can subscribe multiple Contacts to Topics at once:

1. Go to the [Contacts](https://resend.com/audience) page.
2. Select multiple Contacts by clicking the checkbox next to each Contact.
3. Click the **Edit** button in the bulk actions bar.
4. Select **Subscribe to topics**.
5. Choose the Topics you want to subscribe the Contacts to.
6. Click **Subscribe**.

Learn more about [bulk actions for Contacts](/docs/dashboard/audiences/contacts#bulk-actions).


# Contact Properties
Source: https://resend.com/docs/dashboard/audiences/properties

Learn how to work with Contact Properties with Resend.

Contact Properties can be used to store additional information about your Contacts and then personalize your Broadcasts.

Resend includes a few default properties:

* `first_name`: The first name of the contact.
* `last_name`: The last name of the contact.
* `unsubscribed`: Whether the contact is unsubscribed from all Broadcasts.
* `email`: The email address of the contact.

## Add Custom Contact Properties

You can create additional custom Contact Properties for your Contacts to store additional information. These properties can be used to personalize your Broadcasts across all Segments.

Each Contact Property has a key, a value, and optional fallback value.

* `key`: The key of the property (must be alphanumeric and underscore only, max `50` characters).
* `value`: The value of the property (may be a `string` or `number`).
* `fallback_value`: The fallback value of the property (must match the type of the property).

<video />

You can also create Contact Properties [via the API or SDKs](/docs/api-reference/contact-properties/create-contact-property).

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.contactProperties.create({
    key: 'company_name',
    type: 'string',
    fallbackValue: 'Acme Corp',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->contactProperties->create([
    'key' => 'company_name',
    'type' => 'string',
    'fallback_value' => 'Acme Corp',
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = 're_xxxxxxxxx'

  params = {
      "key": "company_name",
      "type": "string",
      "fallback_value": "Acme Corp",
  }

  contact_property = resend.ContactProperties.create(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  property = Resend::ContactProperties.create({
    key: "company_name",
    type: "string",
    fallback_value: "Acme Corp"
  })
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	apiKey := "re_xxxxxxxxx"

  	client := resend.NewClient(apiKey)

  	params := &resend.CreateContactPropertyRequest{
  		Key:           "company_name",
  		Type:          "string",
  		FallbackValue: "Acme Corp",
  	}

  	property, err := client.ContactProperties.CreateWithContext(ctx, params)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(property)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{
    types::{CreateContactPropertyOptions, PropertyType},
    Resend, Result,
  };

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let contact_property = CreateContactPropertyOptions::new("company_name", PropertyType::String)
      .with_fallback("Acme Corp");

    let _contact_property = resend.contacts.create_property(contact_property).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
    public static void main(String[] args) {
      Resend resend = new Resend("re_xxxxxxxxx");

      CreateContactPropertyOptions options = CreateContactPropertyOptions.builder()
        .key("company_name")
        .type("string")
        .fallbackValue("Acme Corp")
        .build();

      resend.contactProperties().create(options);
    }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ContactPropCreateAsync( new ContactPropertyData() {
    Key = "company_name",
    PropertyType = ContactPropertyType.String,
    DefaultValue = "Acme Corp",
  } );
  Console.WriteLine( "Prop Id={0}", resp.Content );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/contact-properties' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "key": "company_name",
    "type": "string",
    "fallback_value": "Acme Corp"
  }'
  ```
</CodeGroup>

## Add Properties to a Contact

When you create a Contact Property you can provide a fallback value. This value will be used whenever you don't provide a custom value for a Contact.

To provide a custom value for a Contact, you can use the dashboard:

1. Go to the [Contacts](https://resend.com/audience) page.
2. Click the **more options** <Icon icon="ellipsis" /> button and then **Edit Contact**.
3. Add the property key and value.
4. Click on the **Save** button.

<video />

You can also add properties to a Contact when you [create a Contact](/docs/api-reference/contacts/create-contact).

<CodeGroup>
  ```ts Node.js {10-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.contacts.create({
    email: 'steve.wozniak@gmail.com',
    firstName: 'Steve',
    lastName: 'Wozniak',
    unsubscribed: false,
    properties: {
      company_name: 'Acme Corp',
    },
  });
  ```

  ```php PHP {9-11} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->contacts->create(
    parameters: [
      'email' => 'steve.wozniak@gmail.com',
      'first_name' => 'Steve',
      'last_name' => 'Wozniak',
      'unsubscribed' => false,
      'properties' => [
        'company_name' => 'Acme Corp',
      ]
    ]
  );
  ```

  ```python Python {10-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Contacts.CreateParams = {
    "email": "steve.wozniak@gmail.com",
    "first_name": "Steve",
    "last_name": "Wozniak",
    "unsubscribed": False,
    "properties": {
      "company_name": "Acme Corp"
    }
  }

  resend.Contacts.create(params)
  ```

  ```ruby Ruby {10-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    "email": "steve.wozniak@gmail.com",
    "first_name": "Steve",
    "last_name": "Wozniak",
    "unsubscribed": false,
    "properties": {
      "company_name": "Acme Corp",
    }
  }

  Resend::Contacts.create(params)
  ```

  ```go Go {10-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import "github.com/resend/resend-go/v3"

  client := resend.NewClient("re_xxxxxxxxx")

  params := &resend.CreateContactRequest{
    Email:        "steve.wozniak@gmail.com",
    FirstName:    "Steve",
    LastName:     "Wozniak",
    Unsubscribed: false,
    Properties: map[string]interface{} {
      "company_name": "Acme Corp",
    }
  }

  contact, err := client.Contacts.Create(params)
  ```

  ```rust Rust {11-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::CreateContactOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let contact = CreateContactOptions::new("steve.wozniak@gmail.com")
      .with_first_name("Steve")
      .with_last_name("Wozniak")
      .with_unsubscribed(false)
      .with_properties(vec![("company_name".to_string(), "Acme Corp".to_string())]);

    let _contact = resend.contacts.create(contact).await?;

    Ok(())
  }
  ```

  ```java Java {12-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateContactOptions params = CreateContactOptions.builder()
                  .email("steve.wozniak@gmail.com")
                  .firstName("Steve")
                  .lastName("Wozniak")
                  .unsubscribed(false)
                  .properties(java.util.Map.of("company_name", "Acme Corp"))
                  .build();

          CreateContactResponseSuccess data = resend.contacts().create(params);
      }
  }
  ```

  ```csharp .NET {12-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.ContactAddAsync(
      new ContactData()
      {
          Email = "steve.wozniak@gmail.com",
          FirstName = "Steve",
          LastName = "Wozniak",
          IsUnsubscribed = false,
          Properties = new Dictionary<string, object> {
            { "company_name", "Acme Corp" }
          }
      }
  );
  Console.WriteLine( "Contact Id={0}", resp.Content );
  ```

  ```bash cURL {9-11} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/contacts' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "email": "steve.wozniak@gmail.com",
    "first_name": "Steve",
    "last_name": "Wozniak",
    "unsubscribed": false,
    "properties": {
      "company_name": "Acme Corp",
    }
  }'
  ```
</CodeGroup>

Or you can update a Contact to add or change a property value [using the update contact endpoint](/docs/api-reference/contacts/update-contact).

<CodeGroup>
  ```ts Node.js {8-10, 16-18} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Update by contact id
  const { data, error } = await resend.contacts.update({
    id: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    properties: {
      company_name: 'Acme Corp',
    },
  });

  // Update by contact email
  const { data, error } = await resend.contacts.update({
    email: 'acme@example.com',
    properties: {
      company_name: 'Acme Corp',
    },
  });
  ```

  ```php PHP {7-9, 17-19} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Update by contact id
  $resend->contacts->update(
    id: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    parameters: [
      'properties' => [
        'company_name' => 'Acme Corp',
      ]
    ]
  );

  // Update by contact email
  $resend->contacts->update(
    email: 'acme@example.com',
    parameters: [
      'properties' => [
        'company_name' => 'Acme Corp',
      ]
    ]
  );
  ```

  ```python Python {8-10, 18-20} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  # Update by contact id
  params: resend.Contacts.UpdateParams = {
    "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
    "properties": {
      "company_name": "Acme Corp",
    }
  }

  resend.Contacts.update(params)

  # Update by contact email
  params: resend.Contacts.UpdateParams = {
    "email": "acme@example.com",
    "properties": {
      "company_name": "Acme Corp",
    }
  }

  resend.Contacts.update(params)
  ```

  ```ruby Ruby {8-10, 18-20} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  # Update by contact id
  params = {
    "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
    "properties": {
      "company_name": "Acme Corp",
    }
  }

  Resend::Contacts.update(params)

  # Update by contact email
  params = {
    "email": "acme@example.com",
    "properties": {
      "company_name": "Acme Corp",
    }
  }

  Resend::Contacts.update(params)
  ```

  ```go Go {8-10, 19-21} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import "github.com/resend/resend-go/v3"

  client := resend.NewClient("re_xxxxxxxxx")

  // Update by contact id
  params := &resend.UpdateContactRequest{
    Id:           "e169aa45-1ecf-4183-9955-b1499d5701d3",
    Properties: new Dictionary<string, object> {
      { "company_name", "Acme Corp" }
    }
  }
  params.SetUnsubscribed(true)

  contact, err := client.Contacts.Update(params)

  // Update by contact email
  params = &resend.UpdateContactRequest{
    Email:        "acme@example.com",
    Properties: new Dictionary<string, object> {
      { "company_name", "Acme Corp" }
    }
  }
  params.SetUnsubscribed(true)

  contact, err := client.Contacts.Update(params)
  ```

  ```rust Rust {7} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::ContactChanges, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let changes = ContactChanges::new().with_properties(vec![("company_name".to_string(), "Acme Corp".to_string())]);

    // Update by contact id
    let _contact = resend
      .contacts
      .update("e169aa45-1ecf-4183-9955-b1499d5701d3", changes.clone())
      .await?;

    // Update by contact email
    let _contact = resend
      .contacts
      .update("acme@example.com", changes)
      .await?;

    Ok(())
  }
  ```

  ```java Java {10, 16} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          // Update by contact id
          UpdateContactOptions params = UpdateContactOptions.builder()
                  .id("e169aa45-1ecf-4183-9955-b1499d5701d3")
                  .properties(vec![("company_name".to_string(), "Acme Corp".to_string())])
                  .build();

          // Update by contact email
          UpdateContactOptions params = UpdateContactOptions.builder()
                  .email("acme@example.com")
                  .properties(vec![("company_name".to_string(), "Acme Corp".to_string())])
                  .build();

          UpdateContactResponseSuccess data = resend.contacts().update(params);
      }
  }
  ```

  ```csharp .NET {12-14, 25-27} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  // By Id
  await resend.ContactUpdateAsync(
      contactId: new Guid( "e169aa45-1ecf-4183-9955-b1499d5701d3" ),
      new ContactData()
      {
          FirstName = "Stevie",
          LastName = "Wozniaks",
          Properties = new Dictionary<string, object> {
            { "company_name", "Acme Corp" }
          }
      }
  );

  // By Email
  await resend.ContactUpdateByEmailAsync(
      "acme@example.com",
      new ContactData()
      {
          FirstName = "Stevie",
          LastName = "Wozniaks",
          Properties = new Dictionary<string, object> {
            { "company_name", "Acme Corp" }
          }
      }
  );
  ```

  ```bash cURL {6-8, 16-18} theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Update by contact id
  curl -X PATCH 'https://api.resend.com/contacts/520784e2-887d-4c25-b53c-4ad46ad38100' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "properties": {
      "company_name": "Acme Corp",
    }
  }'

  # Update by contact email
  curl -X PATCH 'https://api.resend.com/contacts/acme@example.com' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "properties": {
      "company_name": "Acme Corp",
    }
  }'
  ```
</CodeGroup>

When you create or update a Contact with properties, the properties are added to the Contact, but only if the property key already exists and the value type is valid. You can [list all Contact Properties](/docs/api-reference/contact-properties/list-contact-properties) to see all available properties.

<AccordionGroup>
  <Accordion title="What happens if the properties don't exist?">
    If the properties don't exist, they are not added to the Contact and the
    call fails. An error is returned.
  </Accordion>

  <Accordion title="Property keys are case sensitive, right?">
    Yes, property keys are case sensitive. If you create a property with a key
    of "company\_name", you cannot use "CompanyName" or "company\_Name" in your
    Contacts.
  </Accordion>

  <Accordion title="What happens if the value isn't the right type?">
    If the value isn't the right type, the property value is not added to the
    Contact and the call fails. An error is returned.
  </Accordion>
</AccordionGroup>

## Use Contact Properties in Broadcasts

You can use Contact Properties in your Broadcasts to personalize your emails.

<video />

You can also use Contact Properties in your Broadcast HTML and Text content when you [create a Broadcast using the API or SDKs](/docs/api-reference/broadcasts/create-broadcast).


# Add to Segment
Source: https://resend.com/docs/dashboard/automations/add-to-segment

Include contacts to a segment as part of your Automation.

This step adds the current contact to a specified [Segment](/docs/dashboard/segments/introduction) when reached in the Automation flow.

Common use cases:

* **Cohorts**: Add contacts to a cohort segment after a specific event.
* **Lifecycle**: Segment contacts as they progress through onboarding.
* **Engagement**: Group contacts who completed a specific action.

## How it works

<Tabs>
  <Tab title="Using the dashboard">
    Define a **Add to segment** step and select the segment from the dropdown.

    <img alt="Automation Add to Segment" />
  </Tab>

  <Tab title="Using the API">
    The `add_to_segment` step accepts a single `segment_id` field.

    <CodeGroup>
      ```ts Node.js {13-19} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.automations.create({
        name: 'Tag VIP Users',
        steps: [
          {
            key: 'start',
            type: 'trigger',
            config: { eventName: 'purchase.completed' },
          },
          {
            key: 'vip_users',
            type: 'add_to_segment',
            config: {
              segmentId: '83a1e324-26dc-47eb-9b28-ba8b6d1fe808',
            },
          },
        ],
        connections: [{ from: 'start', to: 'vip_users', type: 'default' }],
      });
      ```

      ```php PHP {11-17} theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->automations->create([
        'name' => 'Tag VIP Users',
        'steps' => [
          [
            'key' => 'start',
            'type' => 'trigger',
            'config' => ['event_name' => 'purchase.completed'],
          ],
          [
            'key' => 'vip_users',
            'type' => 'add_to_segment',
            'config' => [
              'segment_id' => '83a1e324-26dc-47eb-9b28-ba8b6d1fe808',
            ],
          ],
        ],
        'connections' => [['from' => 'start', 'to' => 'vip_users', 'type' => 'default']],
      ]);
      ```

      ```python Python {13-19} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      params: resend.Automations.CreateParams = {
        "name": "Tag VIP Users",
        "steps": [
          {
            "key": "start",
            "type": "trigger",
            "config": {"event_name": "purchase.completed"},
          },
          {
            "key": "vip_users",
            "type": "add_to_segment",
            "config": {
              "segment_id": "83a1e324-26dc-47eb-9b28-ba8b6d1fe808",
            },
          },
        ],
        "connections": [{"from": "start", "to": "vip_users", "type": "default"}],
      }

      resend.Automations.create(params)
      ```

      ```ruby Ruby {13-19} theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      params = {
        name: "Tag VIP Users",
        steps: [
          {
            key: "start",
            type: "trigger",
            config: { event_name: "purchase.completed" },
          },
          {
            key: "vip_users",
            type: "add_to_segment",
            config: {
              segment_id: "83a1e324-26dc-47eb-9b28-ba8b6d1fe808",
            },
          },
        ],
        connections: [{ from: "start", to: "vip_users", type: "default" }],
      }

      Resend::Automations.create(params)
      ```

      ```go Go {18-24} theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	params := &resend.CreateAutomationRequest{
      		Name: "Tag VIP Users",
      		Steps: []resend.AutomationStep{
      			{
      				Key:  "start",
      				Type: resend.AutomationStepTypeTrigger,
      				Config: map[string]any{
      					"event_name": "purchase.completed",
      				},
      			},
      			{
      				Key:  "vip_users",
      				Type: resend.AutomationStepTypeAddToSegment,
      				Config: map[string]any{
      					"segment_id": "83a1e324-26dc-47eb-9b28-ba8b6d1fe808",
      				},
      			},
      		},
      		Connections: []resend.AutomationConnection{
      			{From: "start", To: "vip_users", Type: resend.AutomationConnectionTypeDefault},
      		},
      	}

      	client.Automations.Create(params)
      }
      ```

      ```rust Rust {22-27} theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{
        types::{
          AddToSegmentStepConfig, AutomationStatus, Connection, ConnectionType, CreateAutomationOptions,
          Step, TriggerStepConfig,
        },
        Resend, Result,
      };

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let opts = CreateAutomationOptions {
          name: "Tag VIP Users".to_owned(),
          steps: vec![
            Step::Trigger {
              key: "start".to_owned(),
              config: TriggerStepConfig {
                event_name: "purchase.completed".to_owned(),
              },
            },
            Step::AddToSegment {
              key: "vip_users".to_owned(),
              config: AddToSegmentStepConfig {
                segment_id: "83a1e324-26dc-47eb-9b28-ba8b6d1fe808".to_owned(),
              },
            },
          ],
          connections: vec![Connection::new("start", "vip_users").with_type(ConnectionType::Default)],
          status: AutomationStatus::Disabled,
        };
        let _automation = resend.automations.create(opts).await?;

        Ok(())
      }
      ```

      ```java Java {14-18} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              CreateAutomationOptions options = CreateAutomationOptions.builder()
                      .name("Tag VIP Users")
                      .steps(
                          AutomationStep.trigger("start")
                              .eventName("purchase.completed")
                              .build(),
                          AutomationStep.addToSegment("vip_users")
                              .segmentId("83a1e324-26dc-47eb-9b28-ba8b6d1fe808")
                              .build()
                      )
                      .connections(
                          AutomationConnection.builder()
                              .from("start")
                              .to("vip_users")
                              .type(ConnectionType.DEFAULT)
                              .build()
                      )
                      .build();

              CreateAutomationResponseSuccess data = resend.automations().create(options);
          }
      }
      ```

      ```csharp .NET {7,15} theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;
      using System.Text.Json;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      var startConfig = JsonSerializer.SerializeToElement( new { event_name = "purchase.completed" } );
      var segmentConfig = JsonSerializer.SerializeToElement( new { segment_id = "83a1e324-26dc-47eb-9b28-ba8b6d1fe808" } );

      var resp = await resend.AutomationCreateAsync( new AutomationCreateData()
      {
          Name = "Tag VIP Users",
          Steps = new List<AutomationStepData>
          {
              new AutomationStepData { Ref = "start", Type = "trigger", Config = startConfig },
              new AutomationStepData { Ref = "vip_users", Type = "add_to_segment", Config = segmentConfig },
          },
          Connections = new List<AutomationEdge>
          {
              new AutomationEdge { From = "start", To = "vip_users", EdgeType = "default" },
          },
      } );
      ```

      ```bash cURL {10-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X POST 'https://api.resend.com/automations' \
           -H 'Authorization: Bearer re_xxxxxxxxx' \
           -H 'Content-Type: application/json' \
           -d '{
        "name": "Tag VIP Users",
        "steps": [{
          "key": "start",
          "type": "trigger",
          "config": { "event_name": "purchase.completed" }
        }, {
          "key": "vip_users",
          "type": "add_to_segment",
          "config": { "segment_id": "83a1e324-26dc-47eb-9b28-ba8b6d1fe808" }
        }],
        "connections": [
          { "from": "start", "to": "vip_users", "type": "default" }
        ]
      }'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend automations create --name "Tag VIP Users" --file ./automation.json
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Configuration

<ParamField type="string">
  The ID of the segment to add the contact to.
</ParamField>

```json Example theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "add_to_vip",
  "type": "add_to_segment",
  "config": {
    "segment_id": "83a1e324-26dc-47eb-9b28-ba8b6d1fe808"
  }
}
```


# Condition
Source: https://resend.com/docs/dashboard/automations/condition

Route contacts through different paths based on conditions.

A branch step evaluates a condition against event or contact data and routes the Automation down one of two paths: **condition met** or **condition not met**.

Common use cases:

* **Plan-based emails**: Send different content to free vs. paid users.
* **Engagement splits**: Take different actions based on user activity.
* **Personalization**: Tailor follow-ups based on event payload values.

## How it works

<Tabs>
  <Tab title="Using the dashboard">
    Add a **Condition** step and configure the condition using the editor.

    <img alt="Automation Branch" />
  </Tab>

  <Tab title="Using the API">
    The condition step accepts a `type` and the corresponding rule fields.

    <CodeGroup>
      ```ts Node.js {13-22} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.automations.create({
        name: 'Plan-based Welcome',
        steps: [
          {
            key: 'start',
            type: 'trigger',
            config: { eventName: 'user.created' },
          },
          {
            key: 'check_plan',
            type: 'condition',
            config: {
              type: 'rule',
              field: 'event.plan',
              operator: 'eq',
              value: 'pro',
            },
          },
          {
            key: 'send_pro_email',
            type: 'send_email',
            config: { template: { id: 'pro-welcome-template-id' } },
          },
          {
            key: 'send_free_email',
            type: 'send_email',
            config: { template: { id: 'free-welcome-template-id' } },
          },
        ],
        connections: [
          { from: 'start', to: 'check_plan', type: 'default' },
          { from: 'check_plan', to: 'send_pro_email', type: 'condition_met' },
          {
            from: 'check_plan',
            to: 'send_free_email',
            type: 'condition_not_met',
          },
        ],
      });
      ```

      ```php PHP {11-20} theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->automations->create([
        'name' => 'Plan-based Welcome',
        'steps' => [
          [
            'key' => 'start',
            'type' => 'trigger',
            'config' => ['event_name' => 'user.created'],
          ],
          [
            'key' => 'check_plan',
            'type' => 'condition',
            'config' => [
              'type' => 'rule',
              'field' => 'event.plan',
              'operator' => 'eq',
              'value' => 'pro',
            ],
          ],
          [
            'key' => 'send_pro_email',
            'type' => 'send_email',
            'config' => ['template' => ['id' => 'pro-welcome-template-id']],
          ],
          [
            'key' => 'send_free_email',
            'type' => 'send_email',
            'config' => ['template' => ['id' => 'free-welcome-template-id']],
          ],
        ],
        'connections' => [
          ['from' => 'start', 'to' => 'check_plan', 'type' => 'default'],
          ['from' => 'check_plan', 'to' => 'send_pro_email', 'type' => 'condition_met'],
          ['from' => 'check_plan', 'to' => 'send_free_email', 'type' => 'condition_not_met'],
        ],
      ]);
      ```

      ```python Python {13-22} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      params: resend.Automations.CreateParams = {
        "name": "Plan-based Welcome",
        "steps": [
          {
            "key": "start",
            "type": "trigger",
            "config": {"event_name": "user.created"},
          },
          {
            "key": "check_plan",
            "type": "condition",
            "config": {
              "type": "rule",
              "field": "event.plan",
              "operator": "eq",
              "value": "pro",
            },
          },
          {
            "key": "send_pro_email",
            "type": "send_email",
            "config": {"template": {"id": "pro-welcome-template-id"}},
          },
          {
            "key": "send_free_email",
            "type": "send_email",
            "config": {"template": {"id": "free-welcome-template-id"}},
          },
        ],
        "connections": [
          {"from": "start", "to": "check_plan", "type": "default"},
          {"from": "check_plan", "to": "send_pro_email", "type": "condition_met"},
          {"from": "check_plan", "to": "send_free_email", "type": "condition_not_met"},
        ],
      }

      resend.Automations.create(params)
      ```

      ```ruby Ruby {13-22} theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      params = {
        name: "Plan-based Welcome",
        steps: [
          {
            key: "start",
            type: "trigger",
            config: { event_name: "user.created" },
          },
          {
            key: "check_plan",
            type: "condition",
            config: {
              type: "rule",
              field: "event.plan",
              operator: "eq",
              value: "pro",
            },
          },
          {
            key: "send_pro_email",
            type: "send_email",
            config: { template: { id: "pro-welcome-template-id" } },
          },
          {
            key: "send_free_email",
            type: "send_email",
            config: { template: { id: "free-welcome-template-id" } },
          },
        ],
        connections: [
          { from: "start", to: "check_plan", type: "default" },
          { from: "check_plan", to: "send_pro_email", type: "condition_met" },
          { from: "check_plan", to: "send_free_email", type: "condition_not_met" },
        ],
      }

      Resend::Automations.create(params)
      ```

      ```go Go {18-27} theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	params := &resend.CreateAutomationRequest{
      		Name: "Plan-based Welcome",
      		Steps: []resend.AutomationStep{
      			{
      				Key:  "start",
      				Type: resend.AutomationStepTypeTrigger,
      				Config: map[string]any{
      					"event_name": "user.created",
      				},
      			},
      			{
      				Key:  "check_plan",
      				Type: resend.AutomationStepTypeCondition,
      				Config: map[string]any{
      					"type":     "rule",
      					"field":    "event.plan",
      					"operator": "eq",
      					"value":    "pro",
      				},
      			},
      			{
      				Key:  "send_pro_email",
      				Type: resend.AutomationStepTypeSendEmail,
      				Config: map[string]any{
      					"template": map[string]any{"id": "pro-welcome-template-id"},
      				},
      			},
      			{
      				Key:  "send_free_email",
      				Type: resend.AutomationStepTypeSendEmail,
      				Config: map[string]any{
      					"template": map[string]any{"id": "free-welcome-template-id"},
      				},
      			},
      		},
      		Connections: []resend.AutomationConnection{
      			{From: "start", To: "check_plan", Type: resend.AutomationConnectionTypeDefault},
      			{From: "check_plan", To: "send_pro_email", Type: resend.AutomationConnectionTypeConditionMet},
      			{From: "check_plan", To: "send_free_email", Type: resend.AutomationConnectionTypeConditionNotMet},
      		},
      	}

      	client.Automations.Create(params)
      }
      ```

      ```rust Rust {23-31} theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{
        json,
        types::{
          AutomationStatus, AutomationTemplate, Connection, ConnectionType, CreateAutomationOptions,
          SendEmailStepConfig, Step, TriggerStepConfig,
        },
        Resend, Result,
      };

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let opts = CreateAutomationOptions {
          name: "Plan-based Welcome".to_owned(),
          steps: vec![
            Step::Trigger {
              key: "start".to_owned(),
              config: TriggerStepConfig {
                event_name: "user.created".to_owned(),
              },
            },
            Step::Condition {
              key: "check_plan".to_owned(),
              config: json!({
                "type": "rule",
                "field": "event.plan",
                "operator": "eq",
                "value": "pro",
              }),
            },
            Step::SendEmail {
              key: "send_pro_email".to_owned(),
              config: SendEmailStepConfig::new(AutomationTemplate::new("pro-welcome-template-id")),
            },
            Step::SendEmail {
              key: "send_free_email".to_owned(),
              config: SendEmailStepConfig::new(AutomationTemplate::new("free-welcome-template-id")),
            },
          ],
          connections: vec![
            Connection::new("start", "check_plan").with_type(ConnectionType::Default),
            Connection::new("check_plan", "send_pro_email").with_type(ConnectionType::ConditionMet),
            Connection::new("check_plan", "send_free_email").with_type(ConnectionType::ConditionNotMet),
          ],
          status: AutomationStatus::Disabled,
        };
        let _automation = resend.automations.create(opts).await?;

        Ok(())
      }
      ```

      ```java Java {14-21} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              CreateAutomationOptions options = CreateAutomationOptions.builder()
                      .name("Plan-based Welcome")
                      .steps(
                          AutomationStep.trigger("start")
                              .eventName("user.created")
                              .build(),
                          AutomationStep.condition("check_plan")
                              .rule(ConditionRule.builder()
                                      .field("event.plan")
                                      .operator(ConditionOperator.EQ)
                                      .value("pro")
                                      .build())
                              .build(),
                          AutomationStep.sendEmail("send_pro_email")
                              .template("pro-welcome-template-id")
                              .build(),
                          AutomationStep.sendEmail("send_free_email")
                              .template("free-welcome-template-id")
                              .build()
                      )
                      .connections(
                          AutomationConnection.builder()
                              .from("start")
                              .to("check_plan")
                              .type(ConnectionType.DEFAULT)
                              .build(),
                          AutomationConnection.builder()
                              .from("check_plan")
                              .to("send_pro_email")
                              .type(ConnectionType.CONDITION_MET)
                              .build(),
                          AutomationConnection.builder()
                              .from("check_plan")
                              .to("send_free_email")
                              .type(ConnectionType.CONDITION_NOT_MET)
                              .build()
                      )
                      .build();

              CreateAutomationResponseSuccess data = resend.automations().create(options);
          }
      }
      ```

      ```csharp .NET {7-13,23} theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;
      using System.Text.Json;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      var startConfig = JsonSerializer.SerializeToElement( new { event_name = "user.created" } );
      var conditionConfig = JsonSerializer.SerializeToElement( new
      {
          type = "rule",
          field = "event.plan",
          @operator = "eq",
          value = "pro",
      } );
      var proEmailConfig = JsonSerializer.SerializeToElement( new { template = new { id = "pro-welcome-template-id" } } );
      var freeEmailConfig = JsonSerializer.SerializeToElement( new { template = new { id = "free-welcome-template-id" } } );

      var resp = await resend.AutomationCreateAsync( new AutomationCreateData()
      {
          Name = "Plan-based Welcome",
          Steps = new List<AutomationStepData>
          {
              new AutomationStepData { Ref = "start", Type = "trigger", Config = startConfig },
              new AutomationStepData { Ref = "check_plan", Type = "condition", Config = conditionConfig },
              new AutomationStepData { Ref = "send_pro_email", Type = "send_email", Config = proEmailConfig },
              new AutomationStepData { Ref = "send_free_email", Type = "send_email", Config = freeEmailConfig },
          },
          Connections = new List<AutomationEdge>
          {
              new AutomationEdge { From = "start", To = "check_plan", EdgeType = "default" },
              new AutomationEdge { From = "check_plan", To = "send_pro_email", EdgeType = "condition_met" },
              new AutomationEdge { From = "check_plan", To = "send_free_email", EdgeType = "condition_not_met" },
          },
      } );
      ```

      ```bash cURL {10-19} theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X POST 'https://api.resend.com/automations' \
           -H 'Authorization: Bearer re_xxxxxxxxx' \
           -H 'Content-Type: application/json' \
           -d '{
        "name": "Plan-based Welcome",
        "steps": [{
          "key": "start",
          "type": "trigger",
          "config": { "event_name": "user.created" }
        }, {
          "key": "check_plan",
          "type": "condition",
          "config": {
            "type": "rule",
            "field": "event.plan",
            "operator": "eq",
            "value": "pro"
          }
        }, {
          "key": "send_pro_email",
          "type": "send_email",
          "config": { "template": { "id": "pro-welcome-template-id" } }
        }, {
          "key": "send_free_email",
          "type": "send_email",
          "config": { "template": { "id": "free-welcome-template-id" } }
        }],
        "connections": [
          { "from": "start", "to": "check_plan", "type": "default" },
          { "from": "check_plan", "to": "send_pro_email", "type": "condition_met" },
          { "from": "check_plan", "to": "send_free_email", "type": "condition_not_met" }
        ]
      }'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend automations create --name "Plan-based Welcome" --file ./automation.json
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Connection types

A condition step always produces two outgoing connections.

| Connection type     | Description                                 |
| ------------------- | ------------------------------------------- |
| `condition_met`     | Taken when the condition evaluates to true  |
| `condition_not_met` | Taken when the condition evaluates to false |

```json {4,9} theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "from": "check_plan",
  "to": "send_pro_email",
  "type": "condition_met"
},
{
  "from": "check_plan",
  "to": "send_free_email",
  "type": "condition_not_met"
}
```

## Configuration

<ParamField type="string">
  The type of condition node. Possible values:

  * `rule`
  * `and`
  * `or`
</ParamField>

For `rule` type:

<ParamField type="string">
  The field to evaluate. Must use the `event.` or `contact.` namespace prefix
  (e.g., `event.amount`, `contact.email`).
</ParamField>

<ParamField type="string">
  The comparison operator. Possible values:

  * `eq`: equals
  * `neq`: not equals
  * `gt`: greater than
  * `gte`: greater than or equal to
  * `lt`: less than
  * `lte`: less than or equal to
  * `contains`: contains a given value
  * `starts_with`: starts with a given value
  * `ends_with`: ends with a given value
  * `exists`: field exists
  * `is_empty`: field is empty
</ParamField>

<ParamField type="string | number | boolean | null">
  The value to compare against. Not required for `exists` and `is_empty`
  operators.
</ParamField>

For `and` / `or` types:

<ParamField type="object[]">
  An array of nested condition config objects. Must contain at least one item.
</ParamField>

Single rule example:

```json theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "check_plan",
  "type": "condition",
  "config": {
    "type": "rule",
    "field": "event.plan",
    "operator": "eq",
    "value": "pro"
  }
}
```

Use `and` or `or` to combine multiple rules into a single branch:

```json {5-19} theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "check_plan_and_amount",
  "type": "condition",
  "config": {
    "type": "and",
    "rules": [
      {
        "type": "rule",
        "field": "event.plan",
        "operator": "eq",
        "value": "pro"
      },
      {
        "type": "rule",
        "field": "event.amount",
        "operator": "gte",
        "value": 100
      }
    ]
  }
}
```


# Contact Delete
Source: https://resend.com/docs/dashboard/automations/contact-delete

Remove a contact from your audience in an Automation.

This step removes the contact that triggered the Automation from its [Audience](/docs/dashboard/audiences/introduction). Once deleted, the contact will no longer receive emails from that audience and any remaining steps in the Automation run are skipped.

Common use cases:

* **Compliance**: Delete contacts as part of a data-removal workflow.
* **Churn**: Remove a contact, when a user stops using your service.
* **Unsubscribe flows**: Automatically remove contacts who opt out.

## How it works

<Tabs>
  <Tab title="Using the dashboard">
    Include the **Delete contact** step to your Automation.

    <img alt="Automation Contact Delete" />

    No configuration required. It is ready as soon as you add it.
  </Tab>

  <Tab title="Using the API">
    Add a `contact_delete` step to your Automation's `steps` array.

    <CodeGroup>
      ```ts Node.js {13-17} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.automations.create({
        name: 'Remove churned users',
        steps: [
          {
            key: 'start',
            type: 'trigger',
            config: { eventName: 'user.deleted' },
          },
          {
            key: 'remove',
            type: 'contact_delete',
            config: {},
          },
        ],
        connections: [{ from: 'start', to: 'remove', type: 'default' }],
      });
      ```

      ```php PHP {11-15} theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->automations->create([
        'name' => 'Remove churned users',
        'steps' => [
          [
            'key' => 'start',
            'type' => 'trigger',
            'config' => ['event_name' => 'user.deleted'],
          ],
          [
            'key' => 'remove',
            'type' => 'contact_delete',
            'config' => [],
          ],
        ],
        'connections' => [['from' => 'start', 'to' => 'remove', 'type' => 'default']],
      ]);
      ```

      ```python Python {13-17} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      params: resend.Automations.CreateParams = {
        "name": "Remove churned users",
        "steps": [
          {
            "key": "start",
            "type": "trigger",
            "config": {"event_name": "user.deleted"},
          },
          {
            "key": "remove",
            "type": "contact_delete",
            "config": {},
          },
        ],
        "connections": [{"from": "start", "to": "remove", "type": "default"}],
      }

      resend.Automations.create(params)
      ```

      ```ruby Ruby {13-17} theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      params = {
        name: "Remove churned users",
        steps: [
          {
            key: "start",
            type: "trigger",
            config: { event_name: "user.deleted" },
          },
          {
            key: "remove",
            type: "contact_delete",
            config: {},
          },
        ],
        connections: [{ from: "start", to: "remove", type: "default" }],
      }

      Resend::Automations.create(params)
      ```

      ```go Go {18-22} theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	params := &resend.CreateAutomationRequest{
      		Name: "Remove churned users",
      		Steps: []resend.AutomationStep{
      			{
      				Key:  "start",
      				Type: resend.AutomationStepTypeTrigger,
      				Config: map[string]any{
      					"event_name": "user.deleted",
      				},
      			},
      			{
      				Key:    "remove",
      				Type:   resend.AutomationStepTypeContactDelete,
      				Config: map[string]any{},
      			},
      		},
      		Connections: []resend.AutomationConnection{
      			{From: "start", To: "remove", Type: resend.AutomationConnectionTypeDefault},
      		},
      	}

      	client.Automations.Create(params)
      }
      ```

      ```rust Rust {22-25} theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{
        json,
        types::{
          AutomationStatus, Connection, ConnectionType, CreateAutomationOptions, Step, TriggerStepConfig,
        },
        Resend, Result,
      };

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let opts = CreateAutomationOptions {
          name: "Remove churned users".to_owned(),
          steps: vec![
            Step::Trigger {
              key: "start".to_owned(),
              config: TriggerStepConfig {
                event_name: "user.deleted".to_owned(),
              },
            },
            Step::ContactDelete {
              key: "remove".to_owned(),
              config: json!("{}"),
            },
          ],
          connections: vec![Connection::new("start", "remove").with_type(ConnectionType::Default)],
          status: AutomationStatus::Disabled,
        };
        let _automation = resend.automations.create(opts).await?;

        Ok(())
      }
      ```

      ```java Java {14-17} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              CreateAutomationOptions options = CreateAutomationOptions.builder()
                      .name("Remove churned users")
                      .steps(
                          AutomationStep.trigger("start")
                              .eventName("user.deleted")
                              .build(),
                          AutomationStep.contactDelete("remove")
                              .build()
                      )
                      .connections(
                          AutomationConnection.builder()
                              .from("start")
                              .to("remove")
                              .type(ConnectionType.DEFAULT)
                              .build()
                      )
                      .build();

              CreateAutomationResponseSuccess data = resend.automations().create(options);
          }
      }
      ```

      ```csharp .NET {7,15} theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;
      using System.Text.Json;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      var startConfig = JsonSerializer.SerializeToElement( new { event_name = "user.deleted" } );
      var removeConfig = JsonSerializer.SerializeToElement( new { } );

      var resp = await resend.AutomationCreateAsync( new AutomationCreateData()
      {
          Name = "Remove churned users",
          Steps = new List<AutomationStepData>
          {
              new AutomationStepData { Ref = "start", Type = "trigger", Config = startConfig },
              new AutomationStepData { Ref = "remove", Type = "contact_delete", Config = removeConfig },
          },
          Connections = new List<AutomationEdge>
          {
              new AutomationEdge { From = "start", To = "remove", EdgeType = "default" },
          },
      } );
      ```

      ```bash cURL {10-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X POST 'https://api.resend.com/automations' \
           -H 'Authorization: Bearer re_xxxxxxxxx' \
           -H 'Content-Type: application/json' \
           -d '{
        "name": "Remove churned users",
        "steps": [{
          "key": "start",
          "type": "trigger",
          "config": { "event_name": "user.deleted" }
        }, {
          "key": "remove",
          "type": "contact_delete",
          "config": {}
        }],
        "connections": [
          { "from": "start", "to": "remove", "type": "default" }
        ]
      }'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend automations create --name "Remove churned users" --file ./automation.json
      ```
    </CodeGroup>

    The `config` object is empty, so no additional fields are required.
  </Tab>
</Tabs>

<Warning>
  Deleting a contact is **permanent**. The contact and all of its properties are
  removed from the audience. If the contact needs to be re-added later, it must
  be created again.
</Warning>

## Configuration

```json Example theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "remove_contact",
  "type": "contact_delete",
  "config": {}
}
```


# Contact Update
Source: https://resend.com/docs/dashboard/automations/contact-update

Update contact fields during an Automation.

The contact update step modifies a contact's fields as part of an Automation. You can update a contact's name, subscription status, or custom properties.

Common use cases:

* **Enrich profiles**: Copy event data into the contact record.
* **Set flags**: Mark contacts as VIP, or churned based on their activity.
* **Sync properties**: Keep custom properties up to date as events flow in.

## How it works

<Tabs>
  <Tab title="Using the dashboard">
    Add an **Update contact** step and update the fields you want to change.

    <img alt="Automation Contact Update" />
  </Tab>

  <Tab title="Using the API">
    Add a `contact_update` step to your Automation's `steps` array.

    <CodeGroup>
      ```ts Node.js {13-24} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.automations.create({
        name: 'Enrich contact on signup',
        steps: [
          {
            key: 'start',
            type: 'trigger',
            config: { eventName: 'user.created' },
          },
          {
            key: 'update',
            type: 'contact_update',
            config: {
              firstName: { var: 'event.firstName' },
              lastName: { var: 'event.lastName' },
              properties: {
                company: { var: 'event.company' },
                vip: true,
              },
            },
          },
        ],
        connections: [{ from: 'start', to: 'update', type: 'default' }],
      });
      ```

      ```php PHP {11-22} theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->automations->create([
        'name' => 'Enrich contact on signup',
        'steps' => [
          [
            'key' => 'start',
            'type' => 'trigger',
            'config' => ['event_name' => 'user.created'],
          ],
          [
            'key' => 'update',
            'type' => 'contact_update',
            'config' => [
              'first_name' => ['var' => 'event.firstName'],
              'last_name' => ['var' => 'event.lastName'],
              'properties' => [
                'company' => ['var' => 'event.company'],
                'vip' => true,
              ],
            ],
          ],
        ],
        'connections' => [['from' => 'start', 'to' => 'update', 'type' => 'default']],
      ]);
      ```

      ```python Python {13-24} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      params: resend.Automations.CreateParams = {
        "name": "Enrich contact on signup",
        "steps": [
          {
            "key": "start",
            "type": "trigger",
            "config": {"event_name": "user.created"},
          },
          {
            "key": "update",
            "type": "contact_update",
            "config": {
              "first_name": {"var": "event.firstName"},
              "last_name": {"var": "event.lastName"},
              "properties": {
                "company": {"var": "event.company"},
                "vip": True,
              },
            },
          },
        ],
        "connections": [{"from": "start", "to": "update", "type": "default"}],
      }

      resend.Automations.create(params)
      ```

      ```ruby Ruby {13-24} theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      params = {
        name: "Enrich contact on signup",
        steps: [
          {
            key: "start",
            type: "trigger",
            config: { event_name: "user.created" },
          },
          {
            key: "update",
            type: "contact_update",
            config: {
              first_name: { var: "event.firstName" },
              last_name: { var: "event.lastName" },
              properties: {
                company: { var: "event.company" },
                vip: true,
              },
            },
          },
        ],
        connections: [{ from: "start", to: "update", type: "default" }],
      }

      Resend::Automations.create(params)
      ```

      ```go Go {18-29} theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	params := &resend.CreateAutomationRequest{
      		Name: "Enrich contact on signup",
      		Steps: []resend.AutomationStep{
      			{
      				Key:  "start",
      				Type: resend.AutomationStepTypeTrigger,
      				Config: map[string]any{
      					"event_name": "user.created",
      				},
      			},
      			{
      				Key:  "update",
      				Type: resend.AutomationStepTypeContactUpdate,
      				Config: map[string]any{
      					"first_name": map[string]any{"var": "event.firstName"},
      					"last_name":  map[string]any{"var": "event.lastName"},
      					"properties": map[string]any{
      						"company": map[string]any{"var": "event.company"},
      						"vip":     true,
      					},
      				},
      			},
      		},
      		Connections: []resend.AutomationConnection{
      			{From: "start", To: "update", Type: resend.AutomationConnectionTypeDefault},
      		},
      	}

      	client.Automations.Create(params)
      }
      ```

      ```rust Rust {22-32} theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{
        json,
        types::{
          AutomationStatus, Connection, ConnectionType, CreateAutomationOptions, Step, TriggerStepConfig,
        },
        Resend, Result,
      };

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let opts = CreateAutomationOptions {
          name: "Enrich contact on signup".to_owned(),
          steps: vec![
            Step::Trigger {
              key: "start".to_owned(),
              config: TriggerStepConfig {
                event_name: "user.created".to_owned(),
              },
            },
            Step::ContactUpdate {
              key: "update".to_owned(),
              config: json!({
                "firstName": {"var": "event.firstName"},
                "lastName": {"var": "event.lastName"},
                "properties": {
                  "company": {"var": "event.company"},
                  "vip": true
                }
              }),
            },
          ],
          connections: vec![Connection::new("start", "update").with_type(ConnectionType::Default)],
          status: AutomationStatus::Disabled,
        };
        let _automation = resend.automations.create(opts).await?;

        Ok(())
      }
      ```

      ```java Java {15-23} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;
      import java.util.Map;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              CreateAutomationOptions options = CreateAutomationOptions.builder()
                      .name("Enrich contact on signup")
                      .steps(
                          AutomationStep.trigger("start")
                              .eventName("user.created")
                              .build(),
                          AutomationStep.contactUpdate("update")
                              .firstName(Map.of("var", "event.firstName"))
                              .lastName(Map.of("var", "event.lastName"))
                              .properties(Map.of(
                                      "company", Map.of("var", "event.company"),
                                      "vip", true))
                              .build()
                      )
                      .connections(
                          AutomationConnection.builder()
                              .from("start")
                              .to("update")
                              .type(ConnectionType.DEFAULT)
                              .build()
                      )
                      .build();

              CreateAutomationResponseSuccess data = resend.automations().create(options);
          }
      }
      ```

      ```csharp .NET {7-16,24} theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;
      using System.Text.Json;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      var startConfig = JsonSerializer.SerializeToElement( new { event_name = "user.created" } );
      var updateConfig = JsonSerializer.SerializeToElement( new
      {
          first_name = new { @var = "event.firstName" },
          last_name = new { @var = "event.lastName" },
          properties = new
          {
              company = new { @var = "event.company" },
              vip = true,
          },
      } );

      var resp = await resend.AutomationCreateAsync( new AutomationCreateData()
      {
          Name = "Enrich contact on signup",
          Steps = new List<AutomationStepData>
          {
              new AutomationStepData { Ref = "start", Type = "trigger", Config = startConfig },
              new AutomationStepData { Ref = "update", Type = "contact_update", Config = updateConfig },
          },
          Connections = new List<AutomationEdge>
          {
              new AutomationEdge { From = "start", To = "update", EdgeType = "default" },
          },
      } );
      ```

      ```bash cURL {10-21} theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X POST 'https://api.resend.com/automations' \
           -H 'Authorization: Bearer re_xxxxxxxxx' \
           -H 'Content-Type: application/json' \
           -d '{
        "name": "Enrich contact on signup",
        "steps": [{
          "key": "start",
          "type": "trigger",
          "config": { "event_name": "user.created" }
        }, {
          "key": "update",
          "type": "contact_update",
          "config": {
            "first_name": { "var": "event.firstName" },
            "last_name": { "var": "event.lastName" },
            "properties": {
              "company": { "var": "event.company" },
              "vip": true
            }
          }
        }],
        "connections": [
          { "from": "start", "to": "update", "type": "default" }
        ]
      }'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend automations create --name "Enrich contact on signup" --file ./automation.json
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Dynamic variables

Each field value can be a hardcoded value (string, number, boolean) or a dynamic variable reference using the `{ "var": "..." }` syntax. Variable references use dot-notation with one of these scopes:

* `event.*`: references a field from the triggering event payload.
* `contact.*`: references a field from the current contact record.

For more help working with variables in templates, see the [Send Email](/docs/dashboard/automations/send-email#template-variables) step documentation.

```json {5-6,8} theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "update",
  "type": "contact_update",
  "config": {
    "first_name": { "var": "event.firstName" },
    "last_name": { "var": "event.lastName" },
    "properties": {
      "company": { "var": "event.company" },
      "vip": true
    }
  }
}
```

## Configuration

<ParamField type="string | object">
  The contact's first name. Accepts a hardcoded string or a variable reference.
</ParamField>

<ParamField type="string | object">
  The contact's last name. Accepts a hardcoded string or a variable reference.
</ParamField>

<ParamField type="boolean | object">
  The contact's unsubscribed status. Accepts a boolean or a variable reference.
</ParamField>

<ParamField type="object">
  A map of custom contact properties to update. Keys correspond to your [Contact
  Custom Properties](/docs/dashboard/audiences/properties). Each value can be a
  hardcoded value (string, number, boolean) or a variable reference.
</ParamField>

```json Example theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "update_contact",
  "type": "contact_update",
  "config": {
    "properties": {
      "company": { "var": "event.company" },
      "vip": true
    }
  }
}
```


# Custom Events
Source: https://resend.com/docs/dashboard/automations/custom-events

Define custom events to trigger Automations.

Custom events are used to trigger automations and can be defined with an optional schema for payload validation.

If a schema is defined, payloads are validated when the event is sent. Fields that don't match the expected type are rejected with a `422` error and the event is not delivered.

## How it works

<Tabs>
  <Tab title="Using the dashboard">
    The [Events page](https://resend.com/automations/events) shows all existing events. Click **Add event** to create a new event.

    Enter the event name and optional schema to define the event payload you will send with the event.

    <img alt="Add Event" />

    When you're done, **Save** the event.

    <Note>
      The event name can be any string (e.g., `user.created`, `welcome`,
      `my-custom-event`). Dot notation is a recommended convention but is not
      required. If multiple enabled automations use the same event name, all of
      them will be triggered.
    </Note>
  </Tab>

  <Tab title="Using the API">
    All existing events can be retrieved using the [List Events API](/docs/api-reference/events/list-events).

    To create a new event, use the [Create Event API](/docs/api-reference/events/create-event).

    <CodeGroup>
      ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.events.create({
        name: 'user.created',
        schema: {
          plan: 'string',
        },
      });
      ```

      ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->events->create([
        'name' => 'user.created',
        'schema' => ['plan' => 'string'],
      ]);
      ```

      ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      params: resend.Events.CreateParams = {
        "name": "user.created",
        "schema": {
          "plan": "string",
        },
      }

      resend.Events.create(params)
      ```

      ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      params = {
        name: "user.created",
        schema: {
          plan: "string",
        },
      }

      Resend::Events.create(params)
      ```

      ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	params := &resend.CreateEventRequest{
      		Name: "user.created",
      		Schema: map[string]string{
      			"plan": resend.EventSchemaTypeString,
      		},
      	}

      	client.Events.Create(params)
      }
      ```

      ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{json, types::CreateEventOptions, Resend, Result};

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let opts = CreateEventOptions {
          name: "user.created".to_owned(),
          schema: json!({
            "plan": "string",
          }),
        };

        let _event = resend.events.create(opts).await?;

        Ok(())
      }
      ```

      ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              CreateEventOptions params = CreateEventOptions.builder()
                      .name("user.created")
                      .addSchema("plan", "string")
                      .build();

              CreateEventResponseSuccess data = resend.events().create(params);
          }
      }
      ```

      ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;
      using System.Text.Json;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      var schema = JsonSerializer.SerializeToElement( new { plan = "string" } );

      var resp = await resend.EventCreateAsync( new EventCreateData()
      {
          Name = "user.created",
          Schema = schema,
      } );
      Console.WriteLine( "EventId={0}", resp.Content );
      ```

      ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X POST 'https://api.resend.com/events' \
           -H 'Authorization: Bearer re_xxxxxxxxx' \
           -H 'Content-Type: application/json' \
           -d '{
        "name": "user.created",
        "schema": {
          "plan": "string"
        }
      }'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend events create --name user.created --schema '{"plan":"string"}'
      ```
    </CodeGroup>

    <Note>
      The event name can be any string (e.g., `user.created`, `welcome`,
      `my-custom-event`). Dot notation is a recommended convention but is not
      required. If multiple enabled automations use the same event name, all of
      them will be triggered.
    </Note>

    View the [Create Event API reference](/docs/api-reference/events/create-event) for the full endpoint specification.

    ## Configuration

    <ParamField type="string">
      The name of the custom event to create. Used to match events to automation triggers.

      <Warning>
        Event names cannot start with the `resend:` prefix, which is reserved for system events.
      </Warning>
    </ParamField>

    <ParamField type="object">
      An optional schema definition for the event payload. Must be an object with
      flat key/type pairs. Supported types: `string`, `number`, `boolean`, `date`.
    </ParamField>

    ```json Example theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "schema": {
        "plan": "string",
        "amount": "number",
        "date": "date",
        "is_active": "boolean"
      }
    }
    ```
  </Tab>
</Tabs>


# Delay
Source: https://resend.com/docs/dashboard/automations/delay

Pause your Automations with time delays.

A delay step pauses the Automation for a specified duration before continuing to the next step.

Common use cases:

* **Email sequences**: Space out emails in an onboarding series.
* **Cooldowns**: Prevent sending too many emails in a short period.
* **Follow-ups**: Give users time to take action before sending a reminder.

## How it works

<Tabs>
  <Tab title="Using the dashboard">
    You can configure a "Time Delay" duration using natural language.

    <img alt="Automation" />
  </Tab>

  <Tab title="Using the API">
    The delay step accepts a single `duration` field with a human-readable time value.

    <CodeGroup>
      ```ts Node.js {13-17} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.automations.create({
        name: 'Welcome Series',
        steps: [
          {
            key: 'start',
            type: 'trigger',
            config: { eventName: 'user.created' },
          },
          {
            key: 'wait_1_day',
            type: 'delay',
            config: { duration: '1 day' },
          },
        ],
        connections: [{ from: 'start', to: 'wait_1_day', type: 'default' }],
      });
      ```

      ```php PHP {11-15} theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->automations->create([
        'name' => 'Welcome Series',
        'steps' => [
          [
            'key' => 'start',
            'type' => 'trigger',
            'config' => ['event_name' => 'user.created'],
          ],
          [
            'key' => 'wait_1_day',
            'type' => 'delay',
            'config' => ['duration' => '1 day'],
          ],
        ],
        'connections' => [['from' => 'start', 'to' => 'wait_1_day', 'type' => 'default']],
      ]);
      ```

      ```python Python {13-17} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      params: resend.Automations.CreateParams = {
        "name": "Welcome Series",
        "steps": [
          {
            "key": "start",
            "type": "trigger",
            "config": {"event_name": "user.created"},
          },
          {
            "key": "wait_1_day",
            "type": "delay",
            "config": {"duration": "1 day"},
          },
        ],
        "connections": [{"from": "start", "to": "wait_1_day", "type": "default"}],
      }

      resend.Automations.create(params)
      ```

      ```ruby Ruby {13-17} theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      params = {
        name: "Welcome Series",
        steps: [
          {
            key: "start",
            type: "trigger",
            config: { event_name: "user.created" },
          },
          {
            key: "wait_1_day",
            type: "delay",
            config: { duration: "1 day" },
          },
        ],
        connections: [{ from: "start", to: "wait_1_day", type: "default" }],
      }

      Resend::Automations.create(params)
      ```

      ```go Go {18-24} theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	params := &resend.CreateAutomationRequest{
      		Name: "Welcome Series",
      		Steps: []resend.AutomationStep{
      			{
      				Key:  "start",
      				Type: resend.AutomationStepTypeTrigger,
      				Config: map[string]any{
      					"event_name": "user.created",
      				},
      			},
      			{
      				Key:  "wait_1_day",
      				Type: resend.AutomationStepTypeDelay,
      				Config: map[string]any{
      					"duration": "1 day",
      				},
      			},
      		},
      		Connections: []resend.AutomationConnection{
      			{From: "start", To: "wait_1_day", Type: resend.AutomationConnectionTypeDefault},
      		},
      	}

      	client.Automations.Create(params)
      }
      ```

      ```rust Rust {22-27} theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{
        types::{
          AutomationStatus, Connection, ConnectionType, CreateAutomationOptions, DelayStepConfig, Step,
          TriggerStepConfig,
        },
        Resend, Result,
      };

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let opts = CreateAutomationOptions {
          name: "Welcome Series".to_owned(),
          steps: vec![
            Step::Trigger {
              key: "start".to_owned(),
              config: TriggerStepConfig {
                event_name: "user.created".to_owned(),
              },
            },
            Step::Delay {
              key: "wait_1_day".to_owned(),
              config: DelayStepConfig {
                duration: "1 day".to_owned(),
              },
            },
          ],
          connections: vec![Connection::new("start", "wait_1_day").with_type(ConnectionType::Default)],
          status: AutomationStatus::Disabled,
        };
        let _automation = resend.automations.create(opts).await?;

        Ok(())
      }
      ```

      ```java Java {14-18} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              CreateAutomationOptions options = CreateAutomationOptions.builder()
                      .name("Welcome Series")
                      .steps(
                          AutomationStep.trigger("start")
                              .eventName("user.created")
                              .build(),
                          AutomationStep.delay("wait_1_day")
                              .seconds(86400)
                              .build()
                      )
                      .connections(
                          AutomationConnection.builder()
                              .from("start")
                              .to("wait_1_day")
                              .type(ConnectionType.DEFAULT)
                              .build()
                      )
                      .build();

              CreateAutomationResponseSuccess data = resend.automations().create(options);
          }
      }
      ```

      ```csharp .NET {7,15} theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;
      using System.Text.Json;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      var startConfig = JsonSerializer.SerializeToElement( new { event_name = "user.created" } );
      var delayConfig = JsonSerializer.SerializeToElement( new { duration = "1 day" } );

      var resp = await resend.AutomationCreateAsync( new AutomationCreateData()
      {
          Name = "Welcome Series",
          Steps = new List<AutomationStepData>
          {
              new AutomationStepData { Ref = "start", Type = "trigger", Config = startConfig },
              new AutomationStepData { Ref = "wait_1_day", Type = "delay", Config = delayConfig },
          },
          Connections = new List<AutomationEdge>
          {
              new AutomationEdge { From = "start", To = "wait_1_day", EdgeType = "default" },
          },
      } );
      ```

      ```bash cURL {10-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X POST 'https://api.resend.com/automations' \
           -H 'Authorization: Bearer re_xxxxxxxxx' \
           -H 'Content-Type: application/json' \
           -d '{
        "name": "Welcome Series",
        "steps": [{
          "key": "start",
          "type": "trigger",
          "config": { "event_name": "user.created" }
        }, {
          "key": "wait_1_day",
          "type": "delay",
          "config": { "duration": "1 day" }
        }],
        "connections": [
          { "from": "start", "to": "wait_1_day", "type": "default" }
        ]
      }'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend automations create --name "Welcome Series" --file ./automation.json
      ```
    </CodeGroup>

    Example durations: `"30 minutes"`, `"1 hour"`, `"12 hours"`, `"1 day"`, `"3 days"`, `"1 week"`.
  </Tab>
</Tabs>

<Note>The maximum delay is 30 days.</Note>

## Configuration

<ParamField type="string">
  The delay duration in natural language (e.g. `"1 hour"`, `"3 days"`). Maximum:
  30 days.
</ParamField>

```json Example theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "wait_1_hour",
  "type": "delay",
  "config": {
    "duration": "1 hour"
  }
}
```


# Using Automations
Source: https://resend.com/docs/dashboard/automations/introduction

Automate emails with custom events.

Automations allow you to **create email steps** based on custom events from your application.

You can use Automations for use cases like:

* Welcome emails
* Drip campaigns
* Payment recovery
* Abandoned cart
* Trial expiration

Automations support `{{{RESEND_UNSUBSCRIBE_URL}}}` for compliance with non-transactional product and marketing messaging. See [Unsubscribe behavior](/docs/dashboard/automations/send-email#unsubscribe-behavior) for how to add it to a Send Email step, or read more about [when to use an unsubscribe link](/docs/knowledge-base/should-i-add-an-unsubscribe-link).

## How it works

To start executing an Automation, you need to:

<Steps>
  <Step title="Create Automation">
    Outline the sequence of steps to be executed.
  </Step>

  <Step title="Add Trigger">
    Define the event name that will trigger the Automation.
  </Step>

  <Step title="Define Steps">Configure the steps to be executed.</Step>

  <Step title="Send an Event">
    Trigger the Automation by sending an event from your application.
  </Step>

  <Step title="Monitor Runs">
    Track and debug your Automation executions using runs.
  </Step>
</Steps>

## Create an Automation

<Tabs>
  <Tab title="Using the dashboard">
    <Steps>
      <Step title="Create Automation">
        The [Automations page](https://resend.com/automations) shows all existing automations. You can search by name and filter by status (**All Statuses**, **Enabled**, or **Disabled**) to quickly find the automation you need.

        Click **Create automation** to start a new Automation.

        <img alt="Create Automation" />
      </Step>

      <Step title="Add Trigger">
        A trigger is the first step that will run when the Automation is executed. You can use a [custom event](/docs/dashboard/automations/custom-events) like `user.created` or `onboarding.completed`, defining it inline or in the [Events page](https://resend.com/automations/events).

        <img alt="Add Trigger to Automation" />

        In this example, we will receive an event called `user.created` as a trigger.

        <img alt="Add Custom Event" />

        See the [Trigger documentation](/docs/dashboard/automations/trigger) for more details.
      </Step>

      <Step title="Define Steps">
        Now, we need to define the [steps](/docs/dashboard/automations/steps) that will be executed.

        There are several step types you can add to your Automation:

        | Step type                                               | Description                                         |
        | ------------------------------------------------------- | --------------------------------------------------- |
        | [Condition](/docs/dashboard/automations/condition)           | Branches the workflow based on rules                |
        | [Delay](/docs/dashboard/automations/delay)                   | Pauses execution for a specified duration           |
        | [Wait for Event](/docs/dashboard/automations/wait-for-event) | Pauses execution until a specific event is received |
        | [Send Email](/docs/dashboard/automations/send-email)         | Sends an email using a template                     |
        | [Contact Update](/docs/dashboard/automations/contact-update) | Updates a contact's fields                          |
        | [Contact Delete](/docs/dashboard/automations/contact-delete) | Deletes the contact                                 |
        | [Add to Segment](/docs/dashboard/automations/add-to-segment) | Adds the contact to a segment                       |

        On this example, we will use the **Send Email** step.

        <img alt="Define Steps" />

        Once you select that step, you will be able to select an existing template.

        <img alt="Add Send Email Step" />

        If you select a draft template, you can publish it directly from the Send Email node without leaving the workflow editor. Click the **Publish** button that appears when a draft template is selected.

        With the template selected, you will be able to configure the email subject and sender address.

        <img alt="Send Email Step Settings" />

        Once you're done with the email, you can click on **Start** to enable the Automation.

        <img alt="Automation Enabled" />

        <Note>
          While an Automation is enabled, its steps cannot be edited. To make changes,
          duplicate the Automation, edit the copy, and switch over by stopping new runs
          on the original. In-flight runs will finish on the version they started with.
        </Note>
      </Step>

      <Step title="Send an Event">
        Now, we're ready to send an event to trigger the Automation.

        On your application, you can send an event to trigger the Automation by using the API.

        <CodeGroup>
          ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
          import { Resend } from 'resend';

          const resend = new Resend('re_xxxxxxxxx');

          // Trigger with a contact ID
          const { data, error } = await resend.events.send({
            event: 'user.created',
            contactId: '7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b',
            payload: {
              plan: 'pro',
            },
          });

          // Trigger with an email address
          const { data, error } = await resend.events.send({
            event: 'user.created',
            email: 'steve.wozniak@gmail.com',
            payload: {
              plan: 'pro',
            },
          });
          ```

          ```php PHP {6,13} theme={"theme":{"light":"github-light","dark":"vesper"}}
          $resend = Resend::client('re_xxxxxxxxx');

          // Trigger with a contact ID
          $resend->events->send([
            'event' => 'user.created',
            'contact_id' => '7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b',
            'payload' => ['plan' => 'pro'],
          ]);

          // Trigger with an email address
          $resend->events->send([
            'event' => 'user.created',
            'email' => 'steve.wozniak@gmail.com',
            'payload' => ['plan' => 'pro'],
          ]);
          ```

          ```python Python {8,19} theme={"theme":{"light":"github-light","dark":"vesper"}}
          import resend

          resend.api_key = "re_xxxxxxxxx"

          # Trigger with a contact ID
          params: resend.Events.SendParams = {
            "event": "user.created",
            "contact_id": "7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b",
            "payload": {
              "plan": "pro",
            },
          }

          resend.Events.send(params)

          # Trigger with an email address
          params: resend.Events.SendParams = {
            "event": "user.created",
            "email": "steve.wozniak@gmail.com",
            "payload": {
              "plan": "pro",
            },
          }

          resend.Events.send(params)
          ```

          ```ruby Ruby {8,17} theme={"theme":{"light":"github-light","dark":"vesper"}}
          require "resend"

          Resend.api_key = "re_xxxxxxxxx"

          # Trigger with a contact ID
          params = {
            event: "user.created",
            contact_id: "7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b",
            payload: {
              plan: "pro",
            },
          }

          Resend::Events.send(params)

          # Trigger with an email address
          params = {
            event: "user.created",
            email: "steve.wozniak@gmail.com",
            payload: {
              plan: "pro",
            },
          }

          Resend::Events.send(params)
          ```

          ```go Go {11,20} theme={"theme":{"light":"github-light","dark":"vesper"}}
          package main

          import "github.com/resend/resend-go/v3"

          func main() {
          	client := resend.NewClient("re_xxxxxxxxx")

          	// Trigger with a contact ID
          	client.Events.Send(&resend.SendEventRequest{
          		Event:     "user.created",
          		ContactId: "7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b",
          		Payload: map[string]any{
          			"plan": "pro",
          		},
          	})

          	// Trigger with an email address
          	client.Events.Send(&resend.SendEventRequest{
          		Event: "user.created",
          		Email: "steve.wozniak@gmail.com",
          		Payload: map[string]any{
          			"plan": "pro",
          		},
          	})
          }
          ```

          ```rust Rust {10,19} theme={"theme":{"light":"github-light","dark":"vesper"}}
          use resend_rs::{types::SendEventOptions, Resend, Result};

          #[tokio::main]
          async fn main() -> Result<()> {
            let resend = Resend::new("re_xxxxxxxxx");

            // Trigger with a contact ID
            let _event = resend
              .events
              .send(SendEventOptions::new("user.created").contact_id(
                "7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b",
              ).payload(serde_json::json!({
                "plan": "pro"
              })))
              .await?;

            // Trigger with an email address
            let _event = resend
              .events
              .send(SendEventOptions::new("user.created").email(
                "steve.wozniak@gmail.com",
              ).payload(serde_json::json!({
                "plan": "pro"
              })))
              .await?;

            Ok(())
          }
          ```

          ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
          import com.resend.*;

          public class Main {
              public static void main(String[] args) {
                  Resend resend = new Resend("re_xxxxxxxxx");

                  // Trigger with a contact ID
                  SendEventOptions params = SendEventOptions.builder()
                          .event("user.created")
                          .contactId("7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b")
                          .addPayload("plan", "pro")
                          .build();

                  SendEventResponseSuccess data = resend.events().send(params);

                  // Trigger with an email address
                  SendEventOptions params2 = SendEventOptions.builder()
                          .event("user.created")
                          .email("steve.wozniak@gmail.com")
                          .addPayload("plan", "pro")
                          .build();

                  SendEventResponseSuccess data2 = resend.events().send(params2);
              }
          }
          ```

          ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
          using Resend;
          using System.Text.Json;

          IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

          var payload = JsonSerializer.SerializeToElement( new { plan = "pro" } );

          // Trigger with a contact ID
          var resp = await resend.EventSendAsync( new EventSendData()
          {
              Event = "user.created",
              ContactId = new Guid( "7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b" ),
              Payload = payload,
          } );
          Console.WriteLine( "Event={0}", resp.Content.Event );

          // Trigger with an email address
          await resend.EventSendAsync( new EventSendData()
          {
              Event = "user.created",
              Email = "steve.wozniak@gmail.com",
              Payload = payload,
          } );
          ```

          ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
          # Trigger with a contact ID
          curl -X POST 'https://api.resend.com/events/send' \
               -H 'Authorization: Bearer re_xxxxxxxxx' \
               -H 'Content-Type: application/json' \
               -d '{
            "event": "user.created",
            "contact_id": "7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b",
            "payload": {
              "plan": "pro"
            }
          }'

          # Trigger with an email address
          curl -X POST 'https://api.resend.com/events/send' \
               -H 'Authorization: Bearer re_xxxxxxxxx' \
               -H 'Content-Type: application/json' \
               -d '{
            "event": "user.created",
            "email": "steve.wozniak@gmail.com",
            "payload": {
              "plan": "pro"
            }
          }'
          ```

          ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
          # Trigger with a contact ID
          resend events send \
            --event user.created \
            --contact-id 7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b \
            --payload '{"plan":"pro"}'

          # Trigger with an email address
          resend events send \
            --event user.created \
            --email steve.wozniak@gmail.com \
            --payload '{"plan":"pro"}'
          ```
        </CodeGroup>

        View the [API reference](/docs/api-reference/events/send-event) for more details.
      </Step>

      <Step title="Monitor Runs">
        After sending events, you can monitor your Automation executions through Runs. Each time an event triggers an Automation, a Run is created to track the execution.

        <img alt="Monitor Runs" />

        Learn how to:

        * View Run statuses and execution details
        * Filter Runs by status (`running`, `completed`, `failed`, `cancelled`)
        * Debug failed Runs with step-level error information
        * Stop Automation Runs when needed

        See the [Runs documentation](/docs/dashboard/automations/runs) for more details.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Using the API">
    <Steps>
      <Step title="Create Automation">
        When creating an Automation via the API, you can create an entire Automation flow with a single request. It accepts four parameters (status is optional and defaults to `disabled`):

        * `name`: The name of the Automation.
        * `status`: The status of the Automation.
        * `steps`: The [steps](/docs/dashboard/automations/steps) that compose the Automation graph.
        * `connections`: The [connections between steps](/docs/dashboard/automations/connections) in the Automation graph.

        <CodeGroup>
          ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
          import { Resend } from 'resend';

          const resend = new Resend('re_xxxxxxxxx');

          const { data, error } = await resend.automations.create({
            name: 'Welcome series',
            status: 'disabled',
            steps: [
              {
                key: 'start',
                type: 'trigger',
                config: { eventName: 'user.created' },
              },
              {
                key: 'welcome',
                type: 'send_email',
                config: {
                  template: { id: '34a080c9-b17d-4187-ad80-5af20266e535' },
                },
              },
            ],
            connections: [{ from: 'start', to: 'welcome' }],
          });
          ```

          ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
          $resend = Resend::client('re_xxxxxxxxx');

          $resend->automations->create([
            'name' => 'Welcome series',
            'status' => 'disabled',
            'steps' => [
              [
                'key' => 'start',
                'type' => 'trigger',
                'config' => ['event_name' => 'user.created'],
              ],
              [
                'key' => 'welcome',
                'type' => 'send_email',
                'config' => [
                  'template' => ['id' => '34a080c9-b17d-4187-ad80-5af20266e535'],
                ],
              ],
            ],
            'connections' => [['from' => 'start', 'to' => 'welcome']],
          ]);
          ```

          ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
          import resend

          resend.api_key = "re_xxxxxxxxx"

          params: resend.Automations.CreateParams = {
            "name": "Welcome series",
            "status": "disabled",
            "steps": [
              {
                "key": "start",
                "type": "trigger",
                "config": {"event_name": "user.created"},
              },
              {
                "key": "welcome",
                "type": "send_email",
                "config": {
                  "template": {"id": "34a080c9-b17d-4187-ad80-5af20266e535"},
                },
              },
            ],
            "connections": [{"from": "start", "to": "welcome"}],
          }

          resend.Automations.create(params)
          ```

          ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
          require "resend"

          Resend.api_key = "re_xxxxxxxxx"

          params = {
            name: "Welcome series",
            status: "disabled",
            steps: [
              {
                key: "start",
                type: "trigger",
                config: { event_name: "user.created" },
              },
              {
                key: "welcome",
                type: "send_email",
                config: {
                  template: { id: "34a080c9-b17d-4187-ad80-5af20266e535" },
                },
              },
            ],
            connections: [{ from: "start", to: "welcome" }],
          }

          Resend::Automations.create(params)
          ```

          ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
          package main

          import "github.com/resend/resend-go/v3"

          func main() {
          	client := resend.NewClient("re_xxxxxxxxx")

          	params := &resend.CreateAutomationRequest{
          		Name:   "Welcome series",
          		Status: resend.AutomationStatusDisabled,
          		Steps: []resend.AutomationStep{
          			{
          				Key:  "start",
          				Type: resend.AutomationStepTypeTrigger,
          				Config: map[string]any{
          					"event_name": "user.created",
          				},
          			},
          			{
          				Key:  "welcome",
          				Type: resend.AutomationStepTypeSendEmail,
          				Config: map[string]any{
          					"template": map[string]any{
          						"id": "34a080c9-b17d-4187-ad80-5af20266e535",
          					},
          				},
          			},
          		},
          		Connections: []resend.AutomationConnection{
          			{From: "start", To: "welcome"},
          		},
          	}

          	client.Automations.Create(params)
          }
          ```

          ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
          use resend_rs::{
            types::{
              AutomationStatus, AutomationTemplate, Connection, CreateAutomationOptions, SendEmailStepConfig,
              Step, TriggerStepConfig,
            },
            Resend, Result,
          };

          #[tokio::main]
          async fn main() -> Result<()> {
            let resend = Resend::new("re_xxxxxxxxx");

            let opts = CreateAutomationOptions {
              name: "Welcome series".to_owned(),
              status: AutomationStatus::Disabled,
              steps: vec![
                Step::Trigger {
                  key: "start".to_owned(),
                  config: TriggerStepConfig {
                    event_name: "user.created".to_owned(),
                  },
                },
                Step::SendEmail {
                  key: "welcome".to_owned(),
                  config: SendEmailStepConfig::new(AutomationTemplate::new(
                    "34a080c9-b17d-4187-ad80-5af20266e535",
                  )),
                },
              ],
              connections: vec![Connection::new("start", "welcome")],
            };
            let _automation = resend.automations.create(opts).await?;

            Ok(())
          }
          ```

          ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
          import com.resend.*;

          public class Main {
              public static void main(String[] args) {
                  Resend resend = new Resend("re_xxxxxxxxx");

                  CreateAutomationOptions options = CreateAutomationOptions.builder()
                          .name("Welcome series")
                          .status(AutomationStatus.DISABLED)
                          .steps(
                              AutomationStep.trigger("start")
                                  .eventName("user.created")
                                  .build(),
                              AutomationStep.sendEmail("welcome")
                                  .template("34a080c9-b17d-4187-ad80-5af20266e535")
                                  .build()
                          )
                          .connections(
                              AutomationConnection.builder()
                                  .from("start")
                                  .to("welcome")
                                  .build()
                          )
                          .build();

                  CreateAutomationResponseSuccess response = resend.automations().create(options);
              }
          }
          ```

          ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
          using Resend;
          using System.Text.Json;

          IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

          var startConfig = JsonSerializer.SerializeToElement( new { event_name = "user.created" } );
          var welcomeConfig = JsonSerializer.SerializeToElement( new { template = new { id = "34a080c9-b17d-4187-ad80-5af20266e535" } } );

          var resp = await resend.AutomationCreateAsync( new AutomationCreateData()
          {
              Name = "Welcome series",
              Status = "disabled",
              Steps = new List<AutomationStepData>
              {
                  new AutomationStepData { Ref = "start", Type = "trigger", Config = startConfig },
                  new AutomationStepData { Ref = "welcome", Type = "send_email", Config = welcomeConfig },
              },
              Connections = new List<AutomationEdge>
              {
                  new AutomationEdge { From = "start", To = "welcome" },
              },
          } );
          Console.WriteLine( "AutomationId={0}", resp.Content );
          ```

          ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
          curl -X POST 'https://api.resend.com/automations' \
               -H 'Authorization: Bearer re_xxxxxxxxx' \
               -H 'Content-Type: application/json' \
               -d '{
            "name": "Welcome series",
            "steps": [
              {
                "key": "start",
                "type": "trigger",
                "config": { "event_name": "user.created" }
              },
              {
                "key": "welcome",
                "type": "send_email",
                "config": {
                  "template": { "id": "34a080c9-b17d-4187-ad80-5af20266e535" }
                }
              }
            ],
            "connections": [
              { "from": "start", "to": "welcome" }
            ]
          }'
          ```

          ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
          resend automations create --name "Welcome series" --file ./automation.json
          ```
        </CodeGroup>

        The trigger is defined as the first item in the `steps` array with `type: 'trigger'`. It requires you've created a custom event like `user.created` or `onboarding.completed`.

        For more help creating an Automation via the API, see the [Create Automation API reference](/docs/api-reference/automations/create-automation).
      </Step>

      <Step title="Send an Event">
        Trigger the Automation by sending an event from your application.

        <CodeGroup>
          ```ts Node.js {8,17} theme={"theme":{"light":"github-light","dark":"vesper"}}
          import { Resend } from 'resend';

          const resend = new Resend('re_xxxxxxxxx');

          // Trigger with a contact ID
          const { data, error } = await resend.events.send({
            event: 'user.created',
            contactId: '7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b',
            payload: {
              plan: 'pro',
            },
          });

          // Trigger with an email address
          const { data, error } = await resend.events.send({
            event: 'user.created',
            email: 'steve.wozniak@gmail.com',
            payload: {
              plan: 'pro',
            },
          });
          ```

          ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
          $resend = Resend::client('re_xxxxxxxxx');

          // Trigger with a contact ID
          $resend->events->send([
            'event' => 'user.created',
            'contact_id' => '7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b',
            'payload' => ['plan' => 'pro'],
          ]);

          // Trigger with an email address
          $resend->events->send([
            'event' => 'user.created',
            'email' => 'steve.wozniak@gmail.com',
            'payload' => ['plan' => 'pro'],
          ]);
          ```

          ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
          import resend

          resend.api_key = "re_xxxxxxxxx"

          # Trigger with a contact ID
          params: resend.Events.SendParams = {
            "event": "user.created",
            "contact_id": "7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b",
            "payload": {
              "plan": "pro",
            },
          }

          resend.Events.send(params)

          # Trigger with an email address
          params: resend.Events.SendParams = {
            "event": "user.created",
            "email": "steve.wozniak@gmail.com",
            "payload": {
              "plan": "pro",
            },
          }

          resend.Events.send(params)
          ```

          ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
          require "resend"

          Resend.api_key = "re_xxxxxxxxx"

          # Trigger with a contact ID
          params = {
            event: "user.created",
            contact_id: "7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b",
            payload: {
              plan: "pro",
            },
          }

          Resend::Events.send(params)

          # Trigger with an email address
          params = {
            event: "user.created",
            email: "steve.wozniak@gmail.com",
            payload: {
              plan: "pro",
            },
          }

          Resend::Events.send(params)
          ```

          ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
          package main

          import "github.com/resend/resend-go/v3"

          func main() {
          	client := resend.NewClient("re_xxxxxxxxx")

          	// Trigger with a contact ID
          	params := &resend.SendEventRequest{
          		Event:     "user.created",
          		ContactId: "7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b",
          		Payload: map[string]any{
          			"plan": "pro",
          		},
          	}

          	client.Events.Send(params)

          	// Trigger with an email address
          	params = &resend.SendEventRequest{
          		Event: "user.created",
          		Email: "steve.wozniak@gmail.com",
          		Payload: map[string]any{
          			"plan": "pro",
          		},
          	}

          	client.Events.Send(params)
          }
          ```

          ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
          use resend_rs::{
            json,
            types::{ContactIdOrEmail, SendEventOptions},
            Resend, Result,
          };

          #[tokio::main]
          async fn main() -> Result<()> {
            let resend = Resend::new("re_xxxxxxxxx");

            let opts = SendEventOptions {
              event: "user.created".to_owned(),
              contact_id_or_email: ContactIdOrEmail::ContactId(
                "7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b".to_owned(),
              ),
              payload: json!({
                "plan": "pro"
              }),
            };

            let opts = SendEventOptions {
              event: "user.created".to_owned(),
              contact_id_or_email: ContactIdOrEmail::Email("steve.wozniak@gmail.com".to_owned()),
              payload: json!({
                "plan": "pro"
              }),
            };

            let _event = resend.events.send(opts).await?;

            Ok(())
          }
          ```

          ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
          import com.resend.*;

          public class Main {
              public static void main(String[] args) {
                  Resend resend = new Resend("re_xxxxxxxxx");

                  // Trigger with a contact ID
                  SendEventOptions params = SendEventOptions.builder()
                          .event("user.created")
                          .contactId("7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b")
                          .addPayload("plan", "pro")
                          .build();

                  SendEventResponseSuccess data = resend.events().send(params);

                  // Trigger with an email address
                  SendEventOptions params = SendEventOptions.builder()
                          .event("user.created")
                          .email("steve.wozniak@gmail.com")
                          .addPayload("plan", "pro")
                          .build();

                  SendEventResponseSuccess data = resend.events().send(params);
              }
          }
          ```

          ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
          using Resend;
          using System.Text.Json;

          IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

          var payload = JsonSerializer.SerializeToElement( new { plan = "pro" } );

          // Trigger with a contact ID
          var resp = await resend.EventSendAsync( new EventSendData()
          {
              Event = "user.created",
              ContactId = new Guid( "7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b" ),
              Payload = payload,
          } );
          Console.WriteLine( "Event={0}", resp.Content.Event );

          // Trigger with an email address
          await resend.EventSendAsync( new EventSendData()
          {
              Event = "user.created",
              Email = "steve.wozniak@gmail.com",
              Payload = payload,
          } );
          ```

          ```bash cURL {7,19} theme={"theme":{"light":"github-light","dark":"vesper"}}
          # Trigger with a contact ID
          curl -X POST 'https://api.resend.com/events/send' \
               -H 'Authorization: Bearer re_xxxxxxxxx' \
               -H 'Content-Type: application/json' \
               -d '{
            "event": "user.created",
            "contact_id": "7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b",
            "payload": {
              "plan": "pro"
            }
          }'

          # Trigger with an email address
          curl -X POST 'https://api.resend.com/events/send' \
               -H 'Authorization: Bearer re_xxxxxxxxx' \
               -H 'Content-Type: application/json' \
               -d '{
            "event": "user.created",
            "email": "steve.wozniak@gmail.com",
            "payload": {
              "plan": "pro"
            }
          }'
          ```

          ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
          # Trigger with a contact ID
          resend events send \
            --event user.created \
            --contact-id 7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b \
            --payload '{"plan":"pro"}'

          # Trigger with an email address
          resend events send \
            --event user.created \
            --email steve.wozniak@gmail.com \
            --payload '{"plan":"pro"}'
          ```
        </CodeGroup>

        View the [Send Event API reference](/docs/api-reference/events/send-event) for more details.
      </Step>

      <Step title="Monitor Runs">
        After sending events, track your Automation executions through Runs.

        <CodeGroup>
          ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
          import { Resend } from 'resend';

          const resend = new Resend('re_xxxxxxxxx');

          const { data, error } = await resend.automations.runs.list({
            automationId: 'c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd',
          });
          ```

          ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
          $resend = Resend::client('re_xxxxxxxxx');

          $resend->automations->runs->list('c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd');
          ```

          ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
          import resend

          resend.api_key = "re_xxxxxxxxx"

          resend.Automations.Runs.list("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd")
          ```

          ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
          require "resend"

          Resend.api_key = "re_xxxxxxxxx"

          Resend::Automations::Runs.list("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd")
          ```

          ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
          package main

          import "github.com/resend/resend-go/v3"

          func main() {
          	client := resend.NewClient("re_xxxxxxxxx")

          	client.Automations.ListRuns("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd")
          }
          ```

          ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
          use resend_rs::{list_opts::ListOptions, Resend, Result};

          #[tokio::main]
          async fn main() -> Result<()> {
            let resend = Resend::new("re_xxxxxxxxx");

            let _automation = resend
              .automations
              .list_runs(
                "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd",
                None,
                ListOptions::default(),
              )
              .await?;

            Ok(())
          }
          ```

          ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
          import com.resend.*;

          public class Main {
              public static void main(String[] args) {
                  Resend resend = new Resend("re_xxxxxxxxx");

                  ListAutomationRunsResponseSuccess data = resend.automations().listRuns("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd");
              }
          }
          ```

          ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
          using Resend;

          IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

          var resp = await resend.AutomationRunListAsync( new Guid( "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd" ) );
          Console.WriteLine( "Count={0}", resp.Content.Data.Count );
          ```

          ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
          curl -X GET 'https://api.resend.com/automations/c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd/runs' \
               -H 'Authorization: Bearer re_xxxxxxxxx'
          ```

          ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
          resend automations runs list c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd
          ```
        </CodeGroup>

        You can filter Runs by status (`running`, `completed`, `failed`, `cancelled`).

        See the [Runs documentation](/docs/dashboard/automations/runs) and [List Runs API reference](/docs/api-reference/automations/list-automation-runs) for more details.
      </Step>
    </Steps>
  </Tab>
</Tabs>


# Runs
Source: https://resend.com/docs/dashboard/automations/runs

Monitor and debug your Automation executions.

Every time an event [triggers](/docs/dashboard/automations/trigger) an Automation, Resend creates a run.

A run tracks the execution of each step in the workflow, including its status and timing, along with any errors.

## How it works

Each run has one of the following statuses:

| Status      | Description                                                                                        |
| ----------- | -------------------------------------------------------------------------------------------------- |
| `running`   | The Automation is executing steps                                                                  |
| `completed` | All steps finished successfully                                                                    |
| `failed`    | A step encountered an error and the run stopped                                                    |
| `cancelled` | The run was cancelled before completing                                                            |
| `skipped`   | A step was skipped because the contact has either unsubscribed or followed a different branch path |

### Skipped steps

When a contact unsubscribes, any remaining **Send Email** steps in the Automation will be skipped automatically. Other step types (such as Delay, Condition, or Update Contact) will still be executed as normal.

## Listing runs

<Tabs>
  <Tab title="Using the dashboard">
    Navigate to the [Automations page](https://resend.com/automations) and select an Automation to view its runs.

    <img alt="Automation Runs" />

    Each run shows:

    * **Status** — Whether the run is `running`, `completed`, `failed`, `cancelled`, or `skipped`.
    * **Started** — When the run began.
    * **Duration** — When the run finished (if applicable).
  </Tab>

  <Tab title="Using the API">
    List all runs for an Automation:

    <CodeGroup>
      ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.automations.runs.list({
        automationId: 'c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd',
      });
      ```

      ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->automations->runs->list('c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd');
      ```

      ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      resend.Automations.Runs.list("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd")
      ```

      ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      Resend::Automations::Runs.list("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd")
      ```

      ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	client.Automations.ListRuns("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd")
      }
      ```

      ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{list_opts::ListOptions, Resend, Result};

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let _runs = resend
          .automations
          .list_runs(
            "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd",
            None,
            ListOptions::default(),
          )
          .await?;

        Ok(())
      }
      ```

      ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              ListAutomationRunsResponse data = resend.automations().listRuns("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd");
          }
      }
      ```

      ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      var resp = await resend.AutomationRunListAsync( new Guid( "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd" ) );
      Console.WriteLine( "Count={0}", resp.Content.Data.Count );
      ```

      ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X GET 'https://api.resend.com/automations/c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd/runs' \
           -H 'Authorization: Bearer re_xxxxxxxxx'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend automations runs list c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd
      ```
    </CodeGroup>

    Response:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "object": "list",
      "has_more": false,
      "data": [
        {
          "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
          "status": "completed",
          "started_at": "2026-10-01 12:00:00.000000+00",
          "completed_at": "2026-10-01 12:05:00.000000+00",
          "created_at": "2026-10-01 12:00:00.000000+00"
        }
      ]
    }
    ```
  </Tab>
</Tabs>

View the [List Automation Runs API reference](/docs/api-reference/automations/list-automation-runs) for more details.

## Filtering runs by status

<Tabs>
  <Tab title="Using the dashboard">
    You can filter runs by status to find specific executions.

    <img alt="Automation Runs Filter" />
  </Tab>

  <Tab title="Using the API">
    You can filter by multiple statuses using a comma-separated list.

    <CodeGroup>
      ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
      const { data, error } = await resend.automations.runs.list({
        automationId: 'c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd',
        status: ['running', 'completed'],
      });
      ```

      ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->automations->runs->list('c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd', [
        'status' => 'running,completed',
      ]);
      ```

      ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      resend.Automations.Runs.list(
        "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd",
        params={"status": "running,completed"},
      )
      ```

      ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      Resend::Automations::Runs.list(
        "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd",
        status: "running,completed",
      )
      ```

      ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import (
      	"context"

      	"github.com/resend/resend-go/v3"
      )

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	client.Automations.ListRunsWithContext(
      		context.TODO(),
      		"c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd",
      		&resend.ListAutomationRunsOptions{
      			Status: []resend.AutomationRunStatus{
      				resend.AutomationRunStatusRunning,
      				resend.AutomationRunStatusCompleted,
      			},
      		},
      	)
      }
      ```

      ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{list_opts::ListOptions, Resend, Result};

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let _runs = resend
          .automations
          .list_runs(
            "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd",
            Some("running,completed".to_owned()),
            ListOptions::default(),
          )
          .await?;

        Ok(())
      }
      ```

      ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              ListAutomationRunsParams params = ListAutomationRunsParams.builder()
                      .status(RunStatus.RUNNING, RunStatus.COMPLETED)
                      .build();
              ListAutomationRunsResponseSuccess data = resend.automations().listRuns("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd", params);
          }
      }
      ```

      ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
      var resp = await resend.AutomationRunListAsync(
          new Guid( "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd" ),
          new AutomationRunListQuery() { Status = "running,completed" }
      );
      ```

      ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X GET 'https://api.resend.com/automations/c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd/runs?status=running,completed' \
           -H 'Authorization: Bearer re_xxxxxxxxx'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend automations runs list c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Viewing a single run

<Tabs>
  <Tab title="Using the dashboard">
    Click on a run to view its details, and select the step you want to debug.

    <img alt="Automation Run View" />
  </Tab>

  <Tab title="Using the API">
    Get the details of a specific run:

    <CodeGroup>
      ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
      const { data, error } = await resend.automations.runs.get({
        automationId: 'c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd',
        runId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
      });
      ```

      ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->automations->runs->get(
        'c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd',
        'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
      );
      ```

      ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      resend.Automations.Runs.get(
        "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd",
        "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      )
      ```

      ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      Resend::Automations::Runs.get(
        "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd",
        "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      )
      ```

      ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	client.Automations.GetRun(
      		"c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd",
      		"a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      	)
      }
      ```

      ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{Resend, Result};

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let _run = resend
          .automations
          .get_run(
            "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd",
            "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
          )
          .await?;

        Ok(())
      }
      ```

      ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
      AutomationRun data = resend.automations().getRun(
              GetAutomationRunOptions.builder()
                      .automationId("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd")
                      .runId("a1b2c3d4-e5f6-7890-abcd-ef1234567890")
                      .build()
      );
      ```

      ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
      var resp = await resend.AutomationRunRetrieveAsync(
          new Guid( "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd" ),
          new Guid( "a1b2c3d4-e5f6-7890-abcd-ef1234567890" )
      );
      Console.WriteLine( "Status={0}", resp.Content.Status );
      ```

      ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X GET 'https://api.resend.com/automations/c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd/runs/a1b2c3d4-e5f6-7890-abcd-ef1234567890' \
           -H 'Authorization: Bearer re_xxxxxxxxx'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend automations runs get --automation-id c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd --run-id a1b2c3d4-e5f6-7890-abcd-ef1234567890
      ```
    </CodeGroup>

    Response:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "object": "automation_run",
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "status": "completed",
      "started_at": "2026-10-01 12:00:00.000000+00",
      "completed_at": "2026-10-01 12:05:00.000000+00",
      "created_at": "2026-10-01 12:00:00.000000+00",
      "steps": [
        {
          "key": "start",
          "type": "trigger",
          "status": "completed",
          "started_at": "2026-10-01 12:00:00.000000+00",
          "completed_at": "2026-10-01 12:00:01.000000+00",
          "output": null,
          "error": null
        },
        {
          "key": "welcome",
          "type": "send_email",
          "status": "completed",
          "started_at": "2026-10-01 12:00:01.000000+00",
          "completed_at": "2026-10-01 12:00:02.000000+00",
          "output": {
            "to": "user@example.com",
            "email_id": "6278820d-2421-42d0-85f0-80e9e28c1c69",
            "template": {
              "id": "caa9851e-e7bf-4a50-a408-56024edc19c0",
              "variables": null
            }
          },
          "error": null
        }
      ]
    }
    ```

    Each step in the response includes:

    | Field          | Description                                            |
    | -------------- | ------------------------------------------------------ |
    | `key`          | The unique key of the step in the automation graph     |
    | `type`         | The step type (e.g., `trigger`, `send_email`, `delay`) |
    | `status`       | The step's execution status                            |
    | `started_at`   | When the step started executing                        |
    | `completed_at` | When the step finished                                 |
    | `output`       | Output data from the step (if any)                     |
    | `error`        | Error details if the step failed                       |
  </Tab>
</Tabs>

View the [Retrieve Automation Run API reference](/docs/api-reference/automations/get-automation-run) for more details.

## Debugging failed runs

<Tabs>
  <Tab title="Using the dashboard">
    Go to the **Runs** tab and click on a run to view the details.

    <img alt="Automation Run Failed" />
  </Tab>

  <Tab title="Using the API">
    Get the details of a specific failed run:

    <CodeGroup>
      ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
      const { data, error } = await resend.automations.runs.get({
        automationId: 'c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd',
        runId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
      });
      ```

      ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->automations->runs->get(
        'c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd',
        'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
      );
      ```

      ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      resend.Automations.Runs.get(
        "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd",
        "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      )
      ```

      ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      Resend::Automations::Runs.get(
        "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd",
        "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      )
      ```

      ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	client.Automations.GetRun(
      		"c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd",
      		"a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      	)
      }
      ```

      ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{Resend, Result};

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let _run = resend
          .automations
          .get_run(
            "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd",
            "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
          )
          .await?;

        Ok(())
      }
      ```

      ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
      AutomationRun data = resend.automations().getRun(
              GetAutomationRunOptions.builder()
                      .automationId("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd")
                      .runId("a1b2c3d4-e5f6-7890-abcd-ef1234567890")
                      .build()
      );
      ```

      ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
      var resp = await resend.AutomationRunRetrieveAsync(
          new Guid( "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd" ),
          new Guid( "a1b2c3d4-e5f6-7890-abcd-ef1234567890" )
      );
      Console.WriteLine( "Status={0}", resp.Content.Status );
      ```

      ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X GET 'https://api.resend.com/automations/c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd/runs/a1b2c3d4-e5f6-7890-abcd-ef1234567890' \
           -H 'Authorization: Bearer re_xxxxxxxxx'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend automations runs get --automation-id c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd --run-id a1b2c3d4-e5f6-7890-abcd-ef1234567890
      ```
    </CodeGroup>
  </Tab>
</Tabs>

When a run fails, use the step-level details to identify the issue:

1. **List failed runs:** Filter runs by `status=failed` to find problematic executions.
2. **Retrieve the run:** Get the full run details including the `steps` array.
3. **Find the failed step:** Look for the step with a `failed` status.
4. **Check the error:** The `error` field on the failed step contains details about what went wrong.

Common failure scenarios:

* **Condition error:** A referenced field may not exist in the event payload. See [Condition](/docs/dashboard/automations/condition) for how conditions are evaluated.
* **Wait for event timeout:** The expected event was not received within the timeout window.
* **Send email failed:** The template may not be published, or the sender address may not be verified.

## Stopping an Automation

<Tabs>
  <Tab title="Using the dashboard">
    Click on the **Stop** button to stop an Automation.

    <img alt="Automation Run Stop" />
  </Tab>

  <Tab title="Using the API">
    Stop an Automation programmatically:

    <CodeGroup>
      ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
      const { data, error } = await resend.automations.stop(
        'c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd',
      );
      ```

      ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->automations->stop('c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd');
      ```

      ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      resend.Automations.stop("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd")
      ```

      ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      Resend::Automations.stop("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd")
      ```

      ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	client.Automations.Stop("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd")
      }
      ```

      ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{Resend, Result};

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let _automation = resend
          .automations
          .stop("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd")
          .await?;

        Ok(())
      }
      ```

      ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
      StopAutomationResponse data = resend.automations().stop("c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd");
      ```

      ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
      var resp = await resend.AutomationStopAsync( new Guid( "c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd" ) );
      Console.WriteLine( "Status={0}", resp.Content.Status );
      ```

      ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X POST 'https://api.resend.com/automations/c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd/stop' \
           -H 'Authorization: Bearer re_xxxxxxxxx'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend automations stop c9b16d4f-ba6c-4e2e-b044-6bf4404e57fd
      ```
    </CodeGroup>

    <Note>
      Stopping an Automation prevents new runs from being created.

      Existing in-progress runs will continue to completion.
    </Note>
  </Tab>
</Tabs>

View the [Stop Automation API reference](/docs/api-reference/automations/stop-automation) for more details.

## Viewing Metrics

In the dashboard, you can view overall metrics for any Automation. In the **Observability** panel for any Automation, select **Metrics**.

<img alt="Automation Runs Metrics" />

The API does not support fetching metrics for an Automation.


# Send Email
Source: https://resend.com/docs/dashboard/automations/send-email

Trigger templated emails in your Automations.

This automation step triggers a [Template](/docs/dashboard/templates/introduction) email to be sent to the contact.

## How it works

<Tabs>
  <Tab title="Using the dashboard">
    After adding a [trigger](/docs/dashboard/automations/trigger), create a new step to **Send an email**.

    <img alt="Add Send Email Action" />

    Select a published template, then configure the sender address.

    <img alt="Send Email Action Sender Settings" />

    *The subject always comes from the Template. To send a different subject, set `subject` when creating the step via the [API](#configuration).*
  </Tab>

  <Tab title="Using the API">
    Add a `send_email` step to your Automation's `steps` array.

    <CodeGroup>
      ```ts Node.js {13-21} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.automations.create({
        name: 'Welcome series',
        steps: [
          {
            key: 'start',
            type: 'trigger',
            config: { eventName: 'user.created' },
          },
          {
            key: 'welcome',
            type: 'send_email',
            config: {
              template: {
                id: '044db673-fff6-420f-a566-f6aba05d60e7',
              },
            },
          },
        ],
        connections: [{ from: 'start', to: 'welcome' }],
      });
      ```

      ```php PHP {11-19} theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->automations->create([
        'name' => 'Welcome series',
        'steps' => [
          [
            'key' => 'start',
            'type' => 'trigger',
            'config' => ['event_name' => 'user.created'],
          ],
          [
            'key' => 'welcome',
            'type' => 'send_email',
            'config' => [
              'template' => [
                'id' => '044db673-fff6-420f-a566-f6aba05d60e7',
              ],
            ],
          ],
        ],
        'connections' => [['from' => 'start', 'to' => 'welcome']],
      ]);
      ```

      ```python Python {13-21} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      params: resend.Automations.CreateParams = {
        "name": "Welcome series",
        "steps": [
          {
            "key": "start",
            "type": "trigger",
            "config": {"event_name": "user.created"},
          },
          {
            "key": "welcome",
            "type": "send_email",
            "config": {
              "template": {
                "id": "044db673-fff6-420f-a566-f6aba05d60e7",
              },
            },
          },
        ],
        "connections": [{"from": "start", "to": "welcome"}],
      }

      resend.Automations.create(params)
      ```

      ```ruby Ruby {13-21} theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      params = {
        name: "Welcome series",
        steps: [
          {
            key: "start",
            type: "trigger",
            config: { event_name: "user.created" },
          },
          {
            key: "welcome",
            type: "send_email",
            config: {
              template: {
                id: "044db673-fff6-420f-a566-f6aba05d60e7",
              },
            },
          },
        ],
        connections: [{ from: "start", to: "welcome" }],
      }

      Resend::Automations.create(params)
      ```

      ```go Go {18-26} theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	params := &resend.CreateAutomationRequest{
      		Name: "Welcome series",
      		Steps: []resend.AutomationStep{
      			{
      				Key:  "start",
      				Type: resend.AutomationStepTypeTrigger,
      				Config: map[string]any{
      					"event_name": "user.created",
      				},
      			},
      			{
      				Key:  "welcome",
      				Type: resend.AutomationStepTypeSendEmail,
      				Config: map[string]any{
      					"template": map[string]any{
      						"id": "044db673-fff6-420f-a566-f6aba05d60e7",
      					},
      				},
      			},
      		},
      		Connections: []resend.AutomationConnection{
      			{From: "start", To: "welcome"},
      		},
      	}

      	client.Automations.Create(params)
      }
      ```

      ```rust Rust {22-27} theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{
        types::{
          AutomationStatus, AutomationTemplate, Connection, CreateAutomationOptions, SendEmailStepConfig,
          Step, TriggerStepConfig,
        },
        Resend, Result,
      };

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let opts = CreateAutomationOptions {
          name: "Welcome series".to_owned(),
          steps: vec![
            Step::Trigger {
              key: "start".to_owned(),
              config: TriggerStepConfig {
                event_name: "user.created".to_owned(),
              },
            },
            Step::SendEmail {
              key: "welcome".to_owned(),
              config: SendEmailStepConfig::new(AutomationTemplate::new(
                "044db673-fff6-420f-a566-f6aba05d60e7",
              )),
            },
          ],
          connections: vec![Connection::new("start", "welcome")],
          status: AutomationStatus::Disabled,
        };
        let _automation = resend.automations.create(opts).await?;

        Ok(())
      }
      ```

      ```java Java {15-23} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              CreateAutomationOptions options = CreateAutomationOptions.builder()
                      .name("Welcome series")
                      .steps(
                          AutomationStep.trigger("start")
                              .eventName("user.created")
                              .build(),
                          AutomationStep.sendEmail("welcome")
                              .template("044db673-fff6-420f-a566-f6aba05d60e7")
                              .templateVariable("name", Map.of("var", "event.firstName"))
                              .build()
                      )
                      .connections(
                          AutomationConnection.builder()
                              .from("start")
                              .to("welcome")
                              .build()
                      )
                      .build();

              CreateAutomationResponseSuccess data = resend.automations().create(options);
          }
      }
      ```

      ```csharp .NET {7-14,22} theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;
      using System.Text.Json;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      var startConfig = JsonSerializer.SerializeToElement( new { event_name = "user.created" } );
      var welcomeConfig = JsonSerializer.SerializeToElement( new
      {
          template = new
          {
              id = "044db673-fff6-420f-a566-f6aba05d60e7",
              variables = new { name = new { @var = "event.firstName" } },
          },
          subject = "Welcome to Acme!",
          from = "Acme <hello@example.com>",
          reply_to = "support@example.com",
      } );

      var resp = await resend.AutomationCreateAsync( new AutomationCreateData()
      {
          Name = "Welcome series",
          Steps = new List<AutomationStepData>
          {
              new AutomationStepData { Ref = "start", Type = "trigger", Config = startConfig },
              new AutomationStepData { Ref = "welcome", Type = "send_email", Config = welcomeConfig },
          },
          Connections = new List<AutomationEdge>
          {
              new AutomationEdge { From = "start", To = "welcome", EdgeType = "default" },
          },
      } );
      ```

      ```bash cURL {10-17} theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X POST 'https://api.resend.com/automations' \
           -H 'Authorization: Bearer re_xxxxxxxxx' \
           -H 'Content-Type: application/json' \
           -d '{
        "name": "Welcome series",
        "steps": [{
          "key": "start",
          "type": "trigger",
          "config": { "event_name": "user.created" }
        }, {
          "key": "welcome",
          "type": "send_email",
          "config": {
            "template": {
              "id": "044db673-fff6-420f-a566-f6aba05d60e7"
            }
          }
        }],
        "connections": [
          { "from": "start", "to": "welcome" }
        ]
      }'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend automations create --name "Welcome series" --file ./automation.json
      ```
    </CodeGroup>
  </Tab>
</Tabs>

<Note>
  Only `published` templates are available to be used in an Automation.
</Note>

## Template variables

Use the `variables` field to pass data into your template. Each variable value can be a dynamic reference or a static string.

| Type              | Format                                          | Description                                                                                               |
| ----------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| Event data        | `{ "var": "event.<field>" }`                    | Resolves a field from the triggering event's payload.                                                     |
| Contact data      | `{ "var": "contact.<field>" }`                  | Resolves a field from the contact record.                                                                 |
| Waited event data | `{ "var": "wait_events.<event_name>.<field>" }` | Resolves a field from a preceding [wait for event](/docs/dashboard/automations/wait-for-event) step's payload. |
| Static value      | `"<string>"`                                    | Passed as-is to the template.                                                                             |

```json {7-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "welcome",
  "type": "send_email",
  "config": {
    "template": {
      "id": "044db673-fff6-420f-a566-f6aba05d60e7",
      "variables": {
        "firstName": { "var": "event.firstName" },
        "orderNumber": { "var": "event.orderId" },
        "total": { "var": "event.amount" },
        "company": { "var": "contact.properties.company" },
        "feedback": { "var": "wait_events.feedback.received.response" },
        "supportEmail": "help@example.com"
      }
    }
  }
}
```

<Note>
  If the same branch has multiple [wait for
  event](/docs/dashboard/automations/wait-for-event) steps with the same key, the
  resolved data will come from the last event received before the current step.
</Note>

Template variables must be present in your referenced template and the key names must match exactly with the template variable names.

For more help working with variables, see the [Template documentation](/docs/dashboard/templates/template-variables).

## Unsubscribe behavior

Resend does not automatically add an unsubscribe link to emails sent from a `send_email` step. To let contacts opt out, add `{{{RESEND_UNSUBSCRIBE_URL}}}` to the [Template](/docs/dashboard/templates/introduction) used by the step.

<Note>
  `{{{RESEND_UNSUBSCRIBE_URL}}}` must be added to the Template itself, not the step's `config`. If the Template doesn't include this variable, contacts have no way to unsubscribe from within the email.
</Note>

See [when to use an unsubscribe link](/docs/knowledge-base/should-i-add-an-unsubscribe-link) to decide whether your Automation emails need one.

## Configuration

<ParamField type="object">
  The published template to send. Provide `id` and optionally `variables`.

  <Expandable title="properties">
    <ParamField type="string">
      The ID or alias of the template to send.
    </ParamField>

    <ParamField type="object">
      A key-value map of template variables. Each value can be a static string or a variable reference object (`{ "var": "event.fieldName" }`) that resolves dynamically from the `event.*`, `contact.*`, or `wait_events.*` namespaces.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField type="string">
  The sender email address.

  If provided, this value will override the template's default value.
</ParamField>

<ParamField type="string">
  The email subject line.

  If provided, this value will override the template's default value.
</ParamField>

<ParamField type="string">
  Reply-to email address.

  If provided, this value will override the template's default value.
</ParamField>

```json theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "welcome",
  "type": "send_email",
  "config": {
    "template": {
      "id": "062f8ef4-fbfa-44f1-b5e0-ff8e1e8ffa96",
      "variables": {
        "name": { "var": "event.firstName" }
      }
    },
    "from": "hello@example.com",
    "subject": "Welcome!",
    "reply_to": "support@example.com"
  }
}
```


# Trigger
Source: https://resend.com/docs/dashboard/automations/trigger

Start your Automations based on custom events.

A trigger is the first step in every Automation. It defines which event will start the Automation when received.

When your application sends an event to Resend, every active Automation with a matching trigger will execute its workflow for that contact.

## How it works

<Tabs>
  <Tab title="Using the dashboard">
    The trigger is the first node in the editor.

    <img alt="Add Trigger to Automation" />

    Choose an existing [custom event](/docs/dashboard/automations/custom-events) or type a new event name.

    <img alt="Add Custom Event" />
  </Tab>

  <Tab title="Using the API">
    When creating an Automation via the API, the trigger is defined as the first item in the `steps` array with `type: 'trigger'`.

    <CodeGroup>
      ```ts Node.js {8-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.automations.create({
        name: 'Welcome series',
        steps: [
          {
            key: 'start',
            type: 'trigger',
            config: { eventName: 'user.created' },
          },
        ],
        connections: [],
      });
      ```

      ```php PHP {6-10} theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->automations->create([
        'name' => 'Welcome series',
        'steps' => [
          [
            'key' => 'start',
            'type' => 'trigger',
            'config' => ['event_name' => 'user.created'],
          ],
        ],
        'connections' => [],
      ]);
      ```

      ```python Python {8-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      params: resend.Automations.CreateParams = {
        "name": "Welcome series",
        "steps": [
          {
            "key": "start",
            "type": "trigger",
            "config": {"event_name": "user.created"},
          },
        ],
        "connections": [],
      }

      resend.Automations.create(params)
      ```

      ```ruby Ruby {8-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      params = {
        name: "Welcome series",
        steps: [
          {
            key: "start",
            type: "trigger",
            config: { event_name: "user.created" },
          },
        ],
        connections: [],
      }

      Resend::Automations.create(params)
      ```

      ```go Go {11-17} theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	params := &resend.CreateAutomationRequest{
      		Name: "Welcome series",
      		Steps: []resend.AutomationStep{
      			{
      				Key:  "start",
      				Type: resend.AutomationStepTypeTrigger,
      				Config: map[string]any{
      					"event_name": "user.created",
      				},
      			},
      		},
      		Connections: []resend.AutomationConnection{},
      	}

      	client.Automations.Create(params)
      }
      ```

      ```rust Rust {11-16} theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{
        types::{AutomationStatus, CreateAutomationOptions, Step, TriggerStepConfig},
        Resend, Result,
      };

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let opts = CreateAutomationOptions {
          name: "Welcome series".to_owned(),
          steps: vec![Step::Trigger {
            key: "start".to_owned(),
            config: TriggerStepConfig {
              event_name: "user.created".to_owned(),
            },
          }],
          connections: vec![],
          status: AutomationStatus::Disabled,
        };
        let _automation = resend.automations.create(opts).await?;

        Ok(())
      }
      ```

      ```java Java {9-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              CreateAutomationOptions options = CreateAutomationOptions.builder()
                      .name("Welcome series")
                      .steps(
                          AutomationStep.trigger("start")
                              .eventName("user.created")
                              .build()
                      )
                      .build();

              CreateAutomationResponseSuccess data = resend.automations().create(options);
          }
      }
      ```

      ```csharp .NET {6,13} theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;
      using System.Text.Json;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      var startConfig = JsonSerializer.SerializeToElement( new { event_name = "user.created" } );

      var resp = await resend.AutomationCreateAsync( new AutomationCreateData()
      {
          Name = "Welcome series",
          Steps = new List<AutomationStepData>
          {
              new AutomationStepData { Ref = "start", Type = "trigger", Config = startConfig },
          },
          Connections = new List<AutomationEdge>(),
      } );
      ```

      ```bash cURL {6-10} theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X POST 'https://api.resend.com/automations' \
           -H 'Authorization: Bearer re_xxxxxxxxx' \
           -H 'Content-Type: application/json' \
           -d '{
        "name": "Welcome series",
        "steps": [{
          "key": "start",
          "type": "trigger",
          "config": { "event_name": "user.created" }
        }],
        "connections": []
      }'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend automations create --name "Welcome series" --file ./automation.json
      ```
    </CodeGroup>
  </Tab>
</Tabs>

<Warning>
  Event names cannot start with the `resend:` prefix, which is reserved for
  system events.
</Warning>

## Identifying contacts

When sending an event to trigger an Automation, you must identify the contact using either a `contact_id` or an `email` address.

<Tabs>
  <Tab title="Using contact ID">
    Use a contact ID when you already have the contact stored in your [Audience](/docs/dashboard/audiences/introduction):

    <CodeGroup>
      ```ts Node.js {7} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.events.send({
        event: 'user.created',
        contactId: '26e2b838-bf6d-4515-b6a7-17525b12b05a',
        payload: {
          plan: 'pro',
        },
      });
      ```

      ```php PHP {5} theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->events->send([
        'event' => 'user.created',
        'contact_id' => '26e2b838-bf6d-4515-b6a7-17525b12b05a',
        'payload' => ['plan' => 'pro'],
      ]);
      ```

      ```python Python {7} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      params: resend.Events.SendParams = {
        "event": "user.created",
        "contact_id": "26e2b838-bf6d-4515-b6a7-17525b12b05a",
        "payload": {"plan": "pro"},
      }

      resend.Events.send(params)
      ```

      ```ruby Ruby {7} theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      params = {
        event: "user.created",
        contact_id: "26e2b838-bf6d-4515-b6a7-17525b12b05a",
        payload: { plan: "pro" },
      }

      Resend::Events.send(params)
      ```

      ```go Go {10} theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	client.Events.Send(&resend.SendEventRequest{
      		Event:     "user.created",
      		ContactId: "26e2b838-bf6d-4515-b6a7-17525b12b05a",
      		Payload: map[string]any{
      			"plan": "pro",
      		},
      	})
      }
      ```

      ```rust Rust {15-17} theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{
        json,
        types::{ContactIdOrEmail, SendEventOptions},
        Resend, Result,
      };

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let _event = resend
          .events
          .send(SendEventOptions {
            event: "user.created".to_owned(),
            contact_id_or_email: ContactIdOrEmail::ContactId(
              "26e2b838-bf6d-4515-b6a7-17525b12b05a".to_owned(),
            ),
            payload: json!({ "plan": "pro" }),
          })
          .await?;

        Ok(())
      }
      ```

      ```java Java {9} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;
      import com.resend.services.events.model.*;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              SendEventOptions params = SendEventOptions.builder()
                      .event("user.created")
                      .contactId("26e2b838-bf6d-4515-b6a7-17525b12b05a")
                      .addPayload("plan", "pro")
                      .build();

              SendEventResponseSuccess data = resend.events().send(params);
          }
      }
      ```

      ```csharp .NET {11} theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;
      using System.Text.Json;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      var payload = JsonSerializer.SerializeToElement( new { plan = "pro" } );

      var resp = await resend.EventSendAsync( new EventSendData()
      {
          Event = "user.created",
          ContactId = new Guid( "26e2b838-bf6d-4515-b6a7-17525b12b05a" ),
          Payload = payload,
      } );
      ```

      ```bash cURL {6} theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X POST 'https://api.resend.com/events/send' \
           -H 'Authorization: Bearer re_xxxxxxxxx' \
           -H 'Content-Type: application/json' \
           -d '{
        "event": "user.created",
        "contact_id": "26e2b838-bf6d-4515-b6a7-17525b12b05a",
        "payload": {
          "plan": "pro"
        }
      }'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend events send \
        --event user.created \
        --contact-id 26e2b838-bf6d-4515-b6a7-17525b12b05a \
        --payload '{"plan":"pro"}'
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Using email address">
    Use an email address to trigger the Automation. If no contact with the provided email exists in your Audience, Resend will automatically create one when the run starts.

    <CodeGroup>
      ```ts Node.js {7} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.events.send({
        event: 'user.created',
        email: 'user@example.com',
        payload: {
          plan: 'pro',
        },
      });
      ```

      ```php PHP {5} theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->events->send([
        'event' => 'user.created',
        'email' => 'user@example.com',
        'payload' => ['plan' => 'pro'],
      ]);
      ```

      ```python Python {7} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      params: resend.Events.SendParams = {
        "event": "user.created",
        "email": "user@example.com",
        "payload": {"plan": "pro"},
      }

      resend.Events.send(params)
      ```

      ```ruby Ruby {7} theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      params = {
        event: "user.created",
        email: "user@example.com",
        payload: { plan: "pro" },
      }

      Resend::Events.send(params)
      ```

      ```go Go {10} theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	client.Events.Send(&resend.SendEventRequest{
      		Event: "user.created",
      		Email: "user@example.com",
      		Payload: map[string]any{
      			"plan": "pro",
      		},
      	})
      }
      ```

      ```rust Rust {15} theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{
        json,
        types::{ContactIdOrEmail, SendEventOptions},
        Resend, Result,
      };

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let _event = resend
          .events
          .send(SendEventOptions {
            event: "user.created".to_owned(),
            contact_id_or_email: ContactIdOrEmail::Email("user@example.com".to_owned()),
            payload: json!({ "plan": "pro" }),
          })
          .await?;

        Ok(())
      }
      ```

      ```java Java {9} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;
      import com.resend.services.events.model.*;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              SendEventOptions params = SendEventOptions.builder()
                      .event("user.created")
                      .email("user@example.com")
                      .addPayload("plan", "pro")
                      .build();

              SendEventResponseSuccess data = resend.events().send(params);
          }
      }
      ```

      ```csharp .NET {11} theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;
      using System.Text.Json;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      var payload = JsonSerializer.SerializeToElement( new { plan = "pro" } );

      var resp = await resend.EventSendAsync( new EventSendData()
      {
          Event = "user.created",
          Email = "user@example.com",
          Payload = payload,
      } );
      ```

      ```bash cURL {6} theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X POST 'https://api.resend.com/events/send' \
           -H 'Authorization: Bearer re_xxxxxxxxx' \
           -H 'Content-Type: application/json' \
           -d '{
        "event": "user.created",
        "email": "user@example.com",
        "payload": {
          "plan": "pro"
        }
      }'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend events send \
        --event user.created \
        --email user@example.com \
        --payload '{"plan":"pro"}'
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Event payload

You can include a `payload` object with your event to pass data into the Automation. This data becomes available as variables in subsequent steps in the Automation using the `event.*` namespace.

<CodeGroup>
  ```ts Node.js {8-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.events.send({
    event: 'payment.failed',
    contactId: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    payload: {
      amount: 49.99,
      currency: 'USD',
      retryDate: '2026-11-01',
    },
  });
  ```

  ```php PHP {6-10} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->events->send([
    'event' => 'payment.failed',
    'contact_id' => 'e169aa45-1ecf-4183-9955-b1499d5701d3',
    'payload' => [
      'amount' => 49.99,
      'currency' => 'USD',
      'retryDate' => '2026-11-01',
    ],
  ]);
  ```

  ```python Python {8-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Events.SendParams = {
    "event": "payment.failed",
    "contact_id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
    "payload": {
      "amount": 49.99,
      "currency": "USD",
      "retryDate": "2026-11-01",
    },
  }

  resend.Events.send(params)
  ```

  ```ruby Ruby {8-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    event: "payment.failed",
    contact_id: "e169aa45-1ecf-4183-9955-b1499d5701d3",
    payload: {
      amount: 49.99,
      currency: "USD",
      retryDate: "2026-11-01",
    },
  }

  Resend::Events.send(params)
  ```

  ```go Go {11-15} theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	client.Events.Send(&resend.SendEventRequest{
  		Event:     "payment.failed",
  		ContactId: "e169aa45-1ecf-4183-9955-b1499d5701d3",
  		Payload: map[string]any{
  			"amount":    49.99,
  			"currency":  "USD",
  			"retryDate": "2026-11-01",
  		},
  	})
  }
  ```

  ```rust Rust {18-22} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{
    json,
    types::{ContactIdOrEmail, SendEventOptions},
    Resend, Result,
  };

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _event = resend
      .events
      .send(SendEventOptions {
        event: "payment.failed".to_owned(),
        contact_id_or_email: ContactIdOrEmail::ContactId(
          "e169aa45-1ecf-4183-9955-b1499d5701d3".to_owned(),
        ),
        payload: json!({
          "amount": 49.99,
          "currency": "USD",
          "retryDate": "2026-11-01"
        }),
      })
      .await?;

    Ok(())
  }
  ```

  ```java Java {10-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;
  import com.resend.services.events.model.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          SendEventOptions params = SendEventOptions.builder()
                  .event("payment.failed")
                  .contactId("e169aa45-1ecf-4183-9955-b1499d5701d3")
                  .addPayload("amount", 49.99)
                  .addPayload("currency", "USD")
                  .addPayload("retryDate", "2026-11-01")
                  .build();

          SendEventResponseSuccess data = resend.events().send(params);
      }
  }
  ```

  ```csharp .NET {6-11} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;
  using System.Text.Json;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

  var payload = JsonSerializer.SerializeToElement( new
  {
      amount = 49.99,
      currency = "USD",
      retryDate = "2026-11-01",
  } );

  var resp = await resend.EventSendAsync( new EventSendData()
  {
      Event = "payment.failed",
      ContactId = new Guid( "e169aa45-1ecf-4183-9955-b1499d5701d3" ),
      Payload = payload,
  } );
  ```

  ```bash cURL {7-11} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/events/send' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d '{
    "event": "payment.failed",
    "contact_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "payload": {
      "amount": 49.99,
      "currency": "USD",
      "retryDate": "2026-11-01"
    }
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend events send \
    --event payment.failed \
    --contact-id e169aa45-1ecf-4183-9955-b1499d5701d3 \
    --payload '{"amount":49.99,"currency":"USD","retryDate":"2026-11-01"}'
  ```
</CodeGroup>

In this example, you can use `event.amount`, `event.currency`, and `event.retryDate` in other automation [conditions](/docs/dashboard/automations/condition) and steps, or in email templates.

View the [Send Event API reference](/docs/api-reference/events/send-event) for the full endpoint specification.

## Configuration

<ParamField type="string">
  The name of the event that triggers the automation.
</ParamField>

```json theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "start",
  "type": "trigger",
  "config": {
    "event_name": "user.created"
  }
}
```


# Wait for Event
Source: https://resend.com/docs/dashboard/automations/wait-for-event

Hold your Automations until a specific event is received.

A wait-until step holds the Automation until a specific event is received.

Unlike a delay, which resumes after a fixed time, this step resumes when something happens in your application.

Common use cases:

* **Payment**: Wait for a payment to succeed before sending a receipt.
* **Adoption**: Wait for a user to complete an action to unlock a feature.
* **Verification**: Wait for the user to verify their email before continuing.

## How it works

<Tabs>
  <Tab title="Using the dashboard">
    Add a **Wait for event** step and configure the event to wait for.

    <img alt="Automation for Event" />
  </Tab>

  <Tab title="Using the API">
    Add a `wait_for_event` step to your Automation's `steps` array.

    <CodeGroup>
      ```ts Node.js {13-20} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.automations.create({
        name: 'Verification Reminder',
        steps: [
          {
            key: 'start',
            type: 'trigger',
            config: { eventName: 'user.created' },
          },
          {
            key: 'verification',
            type: 'wait_for_event',
            config: {
              eventName: 'email.verified',
              timeout: '1 day',
            },
          },
        ],
        connections: [{ from: 'start', to: 'verification', type: 'default' }],
      });
      ```

      ```php PHP {11-18} theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->automations->create([
        'name' => 'Verification Reminder',
        'steps' => [
          [
            'key' => 'start',
            'type' => 'trigger',
            'config' => ['event_name' => 'user.created'],
          ],
          [
            'key' => 'verification',
            'type' => 'wait_for_event',
            'config' => [
              'event_name' => 'email.verified',
              'timeout' => '24 hours',
            ],
          ],
        ],
        'connections' => [['from' => 'start', 'to' => 'verification', 'type' => 'default']],
      ]);
      ```

      ```python Python {13-20} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      params: resend.Automations.CreateParams = {
        "name": "Verification Reminder",
        "steps": [
          {
            "key": "start",
            "type": "trigger",
            "config": {"event_name": "user.created"},
          },
          {
            "key": "verification",
            "type": "wait_for_event",
            "config": {
              "event_name": "email.verified",
              "timeout": "24 hours",
            },
          },
        ],
        "connections": [{"from": "start", "to": "verification", "type": "default"}],
      }

      resend.Automations.create(params)
      ```

      ```ruby Ruby {13-20} theme={"theme":{"light":"github-light","dark":"vesper"}}
      require "resend"

      Resend.api_key = "re_xxxxxxxxx"

      params = {
        name: "Verification Reminder",
        steps: [
          {
            key: "start",
            type: "trigger",
            config: { event_name: "user.created" },
          },
          {
            key: "verification",
            type: "wait_for_event",
            config: {
              event_name: "email.verified",
              timeout: "24 hours",
            },
          },
        ],
        connections: [{ from: "start", to: "verification", type: "default" }],
      }

      Resend::Automations.create(params)
      ```

      ```go Go {18-25} theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	params := &resend.CreateAutomationRequest{
      		Name: "Verification Reminder",
      		Steps: []resend.AutomationStep{
      			{
      				Key:  "start",
      				Type: resend.AutomationStepTypeTrigger,
      				Config: map[string]any{
      					"event_name": "user.created",
      				},
      			},
      			{
      				Key:  "verification",
      				Type: resend.AutomationStepTypeWaitForEvent,
      				Config: map[string]any{
      					"event_name": "email.verified",
      					"timeout":    "24 hours",
      				},
      			},
      		},
      		Connections: []resend.AutomationConnection{
      			{From: "start", To: "verification", Type: resend.AutomationConnectionTypeDefault},
      		},
      	}

      	client.Automations.Create(params)
      }
      ```

      ```rust Rust {22-29} theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{
        types::{
          AutomationStatus, Connection, ConnectionType, CreateAutomationOptions, Step, TriggerStepConfig,
          WaitForEventStepConfig,
        },
        Resend, Result,
      };

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let opts = CreateAutomationOptions {
          name: "Verification Reminder".to_owned(),
          steps: vec![
            Step::Trigger {
              key: "start".to_owned(),
              config: TriggerStepConfig {
                event_name: "user.created".to_owned(),
              },
            },
            Step::WaitForEvent {
              key: "verification".to_owned(),
              config: WaitForEventStepConfig {
                event_name: "email.verified".to_owned(),
                timeout: Some("24 hours".to_owned()),
                filter_rule: None,
              },
            },
          ],
          connections: vec![Connection::new("start", "verification").with_type(ConnectionType::Default)],
          status: AutomationStatus::Disabled,
        };
        let _automation = resend.automations.create(opts).await?;

        Ok(())
      }
      ```

      ```java Java {14-19} theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              CreateAutomationOptions options = CreateAutomationOptions.builder()
                      .name("Verification Reminder")
                      .steps(
                          AutomationStep.trigger("start")
                              .eventName("user.created")
                              .build(),
                          AutomationStep.waitForEvent("verification")
                              .eventName("email.verified")
                              .timeoutSeconds(86400)
                              .build()
                      )
                      .connections(
                          AutomationConnection.builder()
                              .from("start")
                              .to("verification")
                              .type(ConnectionType.DEFAULT)
                              .build()
                      )
                      .build();

              CreateAutomationResponseSuccess data = resend.automations().create(options);
          }
      }
      ```

      ```csharp .NET {7-11,19} theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;
      using System.Text.Json;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      var startConfig = JsonSerializer.SerializeToElement( new { event_name = "user.created" } );
      var waitConfig = JsonSerializer.SerializeToElement( new
      {
          event_name = "email.verified",
          timeout = "1 day",
      } );

      var resp = await resend.AutomationCreateAsync( new AutomationCreateData()
      {
          Name = "Verification Reminder",
          Steps = new List<AutomationStepData>
          {
              new AutomationStepData { Ref = "start", Type = "trigger", Config = startConfig },
              new AutomationStepData { Ref = "verification", Type = "wait_for_event", Config = waitConfig },
          },
          Connections = new List<AutomationEdge>
          {
              new AutomationEdge { From = "start", To = "verification", EdgeType = "default" },
          },
      } );
      ```

      ```bash cURL {10-16} theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X POST 'https://api.resend.com/automations' \
           -H 'Authorization: Bearer re_xxxxxxxxx' \
           -H 'Content-Type: application/json' \
           -d '{
        "name": "Verification Reminder",
        "steps": [{
          "key": "start",
          "type": "trigger",
          "config": { "event_name": "user.created" }
        }, {
          "key": "verification",
          "type": "wait_for_event",
          "config": {
            "event_name": "email.verified"
          }
        }],
        "connections": [
          { "from": "start", "to": "verification", "type": "default" }
        ]
      }'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend automations create --name "Verification Reminder" --file ./automation.json
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Timeouts

When you set a `timeout`, the step will stop waiting after that duration. This prevents Automations from waiting indefinitely.

When a wait-until step times out, it produces two possible connection types:

| Connection type  | When it's used                                  |
| ---------------- | ----------------------------------------------- |
| `event_received` | The event arrived before the timeout            |
| `timeout`        | The timeout elapsed without receiving the event |

You can create different paths depending on whether the user took action within an given time period.

```json {6} theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "payment",
  "type": "wait_for_event",
  "config": {
    "event_name": "payment.completed",
    "timeout": "3 days"
  }
}
```

<Note>The maximum timeout is 30 days.</Note>

## Filter rules

Use `filter_rule` to match events that meet only specific criteria. This is useful when the same event name might be sent with different payloads.

For example, to wait specifically for a successful payment:

```json {6-11} theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "payment",
  "type": "wait_for_event",
  "config": {
    "event_name": "payment.completed",
    "filter_rule": {
      "type": "rule",
      "field": "event.status",
      "operator": "eq",
      "value": "succeeded"
    }
  }
}
```

The filter rule supports the same [operators](/docs/dashboard/automations/condition#configuration) as condition steps.

## Configuration

<ParamField type="string">
  The name of the event to wait for.
</ParamField>

<ParamField type="string">
  The maximum time to wait before timing out (e.g. `"3 days"`, `"1 hour"`).
  Maximum: 30 days.
</ParamField>

<ParamField type="object">
  An optional rule object to filter incoming events.
</ParamField>

```json Example theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "wait_for_purchase",
  "type": "wait_for_event",
  "config": {
    "event_name": "purchase.completed",
    "timeout": "3 days"
  }
}
```


# Compose and send with the Broadcast editor
Source: https://resend.com/docs/dashboard/broadcasts/editor

Learn how to write and send your Broadcasts in the Dashboard editor

Resend's no-code Broadcast editor is built into the Dashboard to allow anyone on your team to create and send your bulk marketing emails.

<Info>
  To create a Broadcast from your application instead, you can [send Broadcasts
  with the Broadcasts API
  instead](/docs/dashboard/broadcasts/send-broadcast-with-api).
</Info>

## Quickstart

To create and send a Broadcast using the no-code editor:

<Steps>
  <Step title="Go to the Broadcasts page in your Resend dashboard." />

  <Step title="Click `Create Broadcast`." />

  <Step title="Add a `from` name and address.">
    Choose any username at your [verified domain](/docs/dashboard/domains/introduction) to send your Broadcast from.

    We suggest you choose a `from` name and address that describes the purpose of the email, for example:

    * `My Company Name <company@updates.example.com>`
    * `My Newsletter <company@newsletter.example.com>`.
  </Step>

  <Step title="Select the audience you want to send your email to.">
    Choose a [segment of your contacts](/docs/dashboard/segments/introduction) to receive the email.
  </Step>

  <Step title="Create a subject for your email." />

  <Step title="Optionally define other email fields.">
    Resend's Broadcast editor allows you to specify optional fields such as a different Reply-to address, a [topic](/docs/dashboard/topics/introduction), preview text for email clients, and a scheduled time to send.
  </Step>

  <Step title="Write your email content.">
    Use `/` commands in the Broadcast editor for UI elements such as headings, lists, and images. You can also [compose your body text in Markdown](#markdown-support).
  </Step>

  <Step title="Use the sidebar to add custom styles.">
    When you select an element of your Broadcast, such as text, images, or the entire page, contextual styling menu options show in the page sidebar. [Choose colors, sizes, layouts, and more](#custom-styling) or add your own global CSS styles directly in the editor.
  </Step>

  <Step title="Add an unsubscribe link.">
    Use the [Resend unsubscribe footer](#broadcast-unsubscribe-link) to allow your contacts to indicate they no longer want to receive your marketing emails.
  </Step>

  <Step title="Send yourself a test email.">
    Click `Test email` and add one or more email addresses to receive your test email and preview how your Broadcast will look in your own email. If applicable, you can add test data for contact properties used in the Broadcast when sending a test email.
  </Step>

  <Step title="Review your Broadcast.">
    Click **Review** to prompt Resend's review feature, which checks for for any errors or concerns with your Broadcast and helps you catch common mistakes before sending.

    You may be forced to address some issues before you are allowed to send your email.
  </Step>

  <Step title="Slide to send.">
    When there are no errors, the "Slide to send" element will activate. Slide the arrow to confirm that you are ready to send immediately, or at the configured scheduled time.

    Alternatively, exit the editor to leave your Broadcast saved as a draft. It is automatically saved as you compose.
  </Step>
</Steps>

## Markdown Support

You can also write your emails using Markdown headings, lists, italic, bold, links, and quotes.

If you copy and paste content from other rich or plain text applications, the editor maintains formatting consistency.

<video />

## Custom Styling

You can customize the look and feel of your email by changing **global styles** such as the background color, link color, and container size, allowing you to create emails aligned with your brand identity.

To do this, click on **Styles** at the top left of the Broadcast editor. You can edit specific images or lines of text by selecting or highlighting them prior to clicking on **Styles**.

<video />

You can also edit individual styles for each component, including the font size, font weight, letter spacing, line height, and text alignment. You can also set custom properties for each component, such as image alt, button links, and social links.

<video />

The editor additionally includes a built-in AI editor that can style and edit
your content, or `@` mention other Broadcasts for design or content inspiration.

## Personalize your content

When creating Broadcasts, you can include dynamic audience data to personalize the email content.

Add placeholders for your [contact properties](/docs/dashboard/audiences/properties) using the following notation:

* `{{{contact.first_name|fallback}}}`
* `{{{contact.last_name|fallback}}}`
* `{{{contact.email}}}`

## Broadcast unsubscribe link

Resend generates a unique link for each recipient and each Broadcast. Use `{{{RESEND_UNSUBSCRIBE_URL}}}` as the link target in your footer to send readers to your unsubscribe page.

<img alt="Unsubscribe Link" />

When a contact clicks this link, they will be presented with a preference page where they can update their subscription preferences [per topic](/docs/dashboard/topics/introduction) or unsubscribe from all of your emails.

<img alt="Automatic Unsubscribes" />

You can [customize your unsubscribe page with your branding](/docs/dashboard/settings/unsubscribe-page) from your team settings.

<img alt="See Topics on the Unsubscribe Page" />

## Testing & Sending

Once you're finished writing your email, preview it in your personal inbox or send it to your team for feedback.

To do this, click on **Test Email** on the top right of your screen. Enter in the email address you'd like to send your email to, and then click on **Send Test Email** to complete.

Once you're ready to send your email to your Audience, click on **Send**, and slide to confirm.

<video />

<Info>
  Test emails do not include any custom Reply-To address. This behavior is
  limited to test mode and does not affect actual email sends.
</Info>

## Cancel a Broadcast

You can [cancel a Broadcast](/docs/knowledge-base/how-do-i-cancel-a-broadcast) while it is still sending by clicking on the Broadcast's **Cancel** button in the Dashboard. Canceling stops the send and cancels all queued deliveries, so no further emails go out.

This only stops delivery of emails that have not yet been sent. Emails that have already been delivered cannot be recalled.


# Sending Broadcasts
Source: https://resend.com/docs/dashboard/broadcasts/introduction

An introduction to sending bulk marketing emails with Resend.

## Sending marketing emails

Resend provides all the tools you need to send bulk marketing emails to your Contacts. These are useful for:

* Newsletters
* Product Launches
* Investor Updates
* Promotions
* Changelogs

Resend's Broadcast features include tools for content creation, contact management, and performance tracking while handling queuing, throttling, and scheduling for you so that you don't have to roll your own infrastructure.

<Tip>
  To send transactional emails, use the
  [Sending](/docs/dashboard/emails/introduction) feature.
</Tip>

## Broadcast features

With Resend's Broadcast features, you can:

* Compose, schedule, and send marketing emails using a [no-code editor](/docs/dashboard/broadcasts/editor) directly in your Dashboard.
* Organize your contacts into [segments](/docs/dashboard/segments/introduction) and send bulk emails to only targeted contacts.
* Categorize your marketing emails by [topics](/docs/dashboard/topics/introduction) to allow recipients to choose which emails to receive.
* Turn your emails into reusable [templates](/docs/dashboard/templates/introduction).
* [Track performance metrics](/docs/dashboard/broadcasts/performance-tracking) such as delivery, click, and open rates.

## Quickstart

You can send bulk marketing emails from [a verified domain](/docs/dashboard/domains/introduction) to a [segment](/docs/dashboard/segments/introduction) of your contact list.

<Tip>
  You can create a draft Broadcast and send a test email to preview your content
  even before you add any contacts. However, you will need to create a segment
  before you can send your Broadcast.
</Tip>

<Steps>
  <Step title="Add contacts.">
    [Add or import contacts](/docs/dashboard/audiences/contacts#add-contacts)
    manually or programmatically. You can also upload a `.csv` file of existing
    contacts.
  </Step>

  <Step title="Create a segment and add contacts.">
    Broadcasts are sent to a [segment](/docs/dashboard/segments/introduction) of your
    audience.
  </Step>

  <Step title="Write and send your Broadcast.">
    [Create and send a Broadcast entirely using the no-code
    editor](/docs/dashboard/broadcasts/editor). Alternatively, you can [use the
    Broadcast API to build and distribute your
    Broadcast](/docs/dashboard/broadcasts/send-broadcast-with-api) from your
    application.
  </Step>

  <Step title="Check your performance.">
    View the details of any sent Broadcast in the [**Broadcasts Dashboard
    Page**](https://resend.com/broadcasts) to see real-time deliverability
    metrics, open and click tracking (if enabled), and subscriber actions.
  </Step>
</Steps>

## Choose your infrastructure

You can build and send your Broadcasts entirely from the [Resend Dashboard](https://resend.com/broadcasts). This allows all members of your team to create and manage every aspect of your marketing emails.

To create, send, and manage Broadcasts from your application, you can also use a variety of tools:

* [SDK](/docs/sdks): send with an SDK built for your language
* [Integrations](/docs/integrations): send from a framework or tool you already use
* [API](/docs/api-reference/emails/send-email): send with raw cURL calls
* [CLI](/docs/cli#emails): send emails from the terminal
* [MCP](/docs/mcp-server): send through your agent with MCP

<Info>
  You can also create [automations](/docs/dashboard/automations/introduction) for
  repeatable transactional emails like welcoming new subscribers, and Broadcast
  needs like updating your contact list.
</Info>

See how to use Resend's Broadcast and contact management features in the [related guides](#related-guides).

## Manage your Broadcasts

You can view and manage your Broadcasts from the [Broadcasts Dashboard page](https://resend.com/broadcasts).

You can also [manage your Broadcasts through the Broadcast API](/docs/api-reference/broadcasts/create-broadcast) which offers endpoints for programmatically creating, updating, and sending Broadcasts. Many of these actions can also be performed with [Resend Broadcast CLI commands](/docs/cli#broadcasts) and [AI building tools](/docs/ai-onboarding). You can also create [automations](/docs/dashboard/automations/introduction) for workflows related to your Broadcasts, such as managing your contact list.

Learn more about [managing your Broadcasts](/docs/dashboard/broadcasts/manage-broadcasts) in the dedicated guide.

## Export your data

Admins can download your data in CSV format for the following resources:

* Emails
* Broadcasts
* Contacts
* Segments
* Domains
* Logs
* API keys

<Info>Currently, exports are limited to admin users of your team.</Info>

To start, apply filters to your data and click on the "Export" button. Confirm your filters before exporting your data.

<video />

If your exported data includes 1,000 items or less, the export will download immediately. For larger exports, you'll receive an email with a link to download your data.

All admins on your team can securely access the export for 7 days. Unavailable exports are marked as "Expired."

<Note>
  All exports your team creates are listed in the
  [Exports](https://resend.com/exports) page under **Settings** > **Team** >
  **Exports**. Select any export to view its details page. All members of your
  team can view your exports, but only admins can download the data.
</Note>

## Related Guides

See how to use Resend's Broadcast features.

<CardGroup>
  <Card title="No-code editor" icon="pen-line" href="/dashboard/broadcasts/editor" />

  <Card title="Send with API" icon="paper-plane-top" href="/dashboard/broadcasts/send-broadcast-with-api" />

  <Card title="Manage Broadcasts" icon="envelopes-bulk" href="/dashboard/broadcasts/manage-broadcasts" />

  <Card title="Contacts" icon="id-card" href="/dashboard/audiences/contacts" />

  <Card title="Segments" icon="chart-pie" href="/dashboard/segments/introduction" />

  <Card title="Topics" icon="hashtag" href="/dashboard/topics/introduction" />

  <Card title="Track performance" icon="chart-column" href="/dashboard/broadcasts/performance-tracking" />

  <Card title="Handle unsubscribes" icon="right-to-bracket" href="/dashboard/audiences/managing-unsubscribe-list" />
</CardGroup>


# Manage Broadcasts
Source: https://resend.com/docs/dashboard/broadcasts/manage-broadcasts

Learn how to view, update, and delete your Broadcasts.

After you create your first Broadcast, all members of your team can view and manage existing Broadcast details directly in the [**Broadcasts** Dashboard page](https://resend.com/broadcasts). You can also perform bulk actions (cancel, delete) by selecting multiple Broadcasts.

To manage your marketing campaigns directly from your application, you can use the [Broadcast API](/docs/api-reference/broadcasts/create-broadcast) endpoints to list, retrieve, update, and delete your existing Broadcasts.

You can also manage your Broadcasts using [Resend CLI commands](/docs/cli#broadcasts) and [AI building tools](/docs/ai-onboarding).

## View Broadcasts

See the name, [status](#understand-broadcast-statuses), and created date of all your Broadcasts from the Emails Dashboard page. These can also be filtered by status and [audience](/docs/dashboard/segments/introduction).

Select any individual Broadcast to view its details. The view will depend on the status of the email. For example, Broadcasts that have been sent will show deliverability metrics as well as your content as a preview, plain text, and HTML.

Clicking on a draft Broadcast will bring up the Dashboard editor for further editing.

## Understand Broadcast statuses

Here are all the statuses that can be associated with a Broadcast:

* `draft`: The Broadcast is a draft. Drafts can be edited, deleted, or scheduled for sending.
* `scheduled`: The Broadcast is scheduled to be sent at a specific time. Scheduled Broadcasts can have their schedule canceled, which returns them to draft status and prevents any emails from being sent.
* `sent`: The Broadcast was sent.
* `queued`: The Broadcast is queued for delivery. Canceling a queued Broadcast stops delivery to the remaining recipients only. Emails already sent cannot be recalled.

## Edit Broadcasts

You can edit the content and properties of any draft or scheduled Broadcast. Once a Broadcast has been sent, only its name can be updated.

To edit an existing draft or scheduled Broadcast in the Dashboard:

1. Click the name of the Broadcast you want to edit.
2. Use the Dashboard editor to update any properties or content.
3. Exit the editor when you have finished editing. Your changes will be automatically saved.

## Cancel scheduled Broadcasts

Canceling a Broadcast only stops emails that haven't been sent yet. Any emails already delivered cannot be recalled. If a Broadcast is mid-send (`queued`), canceling halts delivery to the remaining recipients.

To cancel the schedule for one or more scheduled Broadcasts in the Dashboard:

1. Select the scheduled Broadcast(s) you want to cancel.
2. Click **Cancel schedule** in the bottom action bar.
3. Type `CANCEL` to confirm.
4. Press **Cmd+Enter** or click **Cancel schedules** to complete.

When you cancel a scheduled Broadcast, it returns to draft status and won't be sent at the scheduled time.

## Delete draft Broadcasts

Only draft (including scheduled) Broadcasts can be deleted. Once a Broadcast has been sent or queued, it can't be deleted.

To delete one or more draft Broadcasts in the Dashboard:

1. Select the Broadcast(s) you want to delete by clicking the checkboxes next to each Broadcast.
2. Click **Delete** in the bottom action bar.
3. Type the Broadcast name (for single selection) or `DELETE N BROADCASTS` (for multiple) to confirm.
4. Press **Cmd+Enter** or click **Delete Broadcasts** to complete.

You can also use keyboard shortcuts:

* **Cmd+A** to select all Broadcasts on the current page
* **Backspace** to open the delete confirmation modal

## API Reference

For complete API documentation, see the [Broadcasts API reference](/docs/api-reference/broadcasts/create-broadcast).


# Performance Tracking
Source: https://resend.com/docs/dashboard/broadcasts/performance-tracking

Track your Broadcasts email performance in real-time

Once your broadcast is sent, you can track its performance right away. The insights you can view are emails delivered, unsubscribed, click rate, and open rate.

You can view these insights by clicking on [Broadcast](https://resend.com/broadcasts) in the left column, and then clicking on the Broadcast that you want to view.

<video />

Please note, at times, open rates can be inaccurate for a number of reasons due to the way inbox providers handle incoming emails. You can [read more about this here.](https://resend.com/docs/knowledge-base/why-are-my-open-rates-not-accurate)


# Compose and send Broadcasts with the API
Source: https://resend.com/docs/dashboard/broadcasts/send-broadcast-with-api

Send marketing emails using the Broadcasts API.

Resend's [no-code Broadcast editor](/docs/dashboard/broadcasts/editor) allows all members of your team to write and send email campaigns directly in the Resend Dashboard, without having to ask for help from developers.

To programmatically create, update, and send Broadcasts, you can use the [Broadcast API](/docs/api-reference/broadcasts/create-broadcast). There are also API endpoints to list, retrieve, and delete Broadcasts, allowing you to manage your marketing campaigns directly from your application.

## Create Broadcasts

The [`create()` method](/docs/api-reference/broadcasts/create-broadcast) takes the same sending properties that can be set in the Editor composer. This allows developers to also create drafts without sending, schedule sending for a time in the future, [personalize with dynamic content data](/docs/dashboard/broadcasts/editor#personalize-your-content), and more.

Set the `send` property to `true` to send immediately or to schedule the Broadcast, or leave `false` (the default) to create a draft:

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  // Create a draft Broadcast
  const { data, error } = await resend.broadcasts.create({
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf',
    from: 'Acme <onboarding@resend.dev>',
    subject: 'hello world',
    html: 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
  });

  // Create and send immediately
  const { data, error } = await resend.broadcasts.create({
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf',
    from: 'Acme <onboarding@resend.dev>',
    subject: 'hello world',
    html: 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
    send: true,
  });

  // Create and schedule
  const { data, error } = await resend.broadcasts.create({
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf',
    from: 'Acme <onboarding@resend.dev>',
    subject: 'hello world',
    html: 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
    send: true,
    scheduledAt: 'in 1 hour',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Create a draft Broadcast
  $resend->broadcasts->create([
    'segment_id' => '78261eea-8f8b-4381-83c6-79fa7120f1cf',
    'from' => 'Acme <onboarding@resend.dev>',
    'subject' => 'hello world',
    'html' => 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
  ]);

  // Create and send immediately
  $resend->broadcasts->create([
    'segment_id' => '78261eea-8f8b-4381-83c6-79fa7120f1cf',
    'from' => 'Acme <onboarding@resend.dev>',
    'subject' => 'hello world',
    'html' => 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
    'send' => true,
  ]);

  // Create and schedule
  $resend->broadcasts->create([
    'segment_id' => '78261eea-8f8b-4381-83c6-79fa7120f1cf',
    'from' => 'Acme <onboarding@resend.dev>',
    'subject' => 'hello world',
    'html' => 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
    'send' => true,
    'scheduled_at' => 'in 1 hour',
  ]);
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  // Create a draft Broadcast
  params: resend.Broadcasts.CreateParams = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
  }
  resend.Broadcasts.create(params)

  // Create and send immediately
  params: resend.Broadcasts.CreateParams = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true,
  }
  resend.Broadcasts.create(params)

  // Create and schedule
  params: resend.Broadcasts.CreateParams = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true,
    "scheduled_at": "in 1 hour",
  }
  resend.Broadcasts.create(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  // Create a draft Broadcast
  params = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "hello world",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
  }
  Resend::Broadcasts.create(params)

  // Create and send immediately
  params = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true,
  }
  Resend::Broadcasts.create(params)

  // Create and schedule
  params = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true,
    "scheduled_at": "in 1 hour",
  }
  Resend::Broadcasts.create(params)

  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  // Create a draft Broadcast
  params := &resend.CreateBroadcastRequest{
    SegmentId: "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    From:       "Acme <onboarding@resend.dev>",
    Html:       "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    Subject:    "Hello, world!",
  }
  broadcast, _ := client.Broadcasts.Create(params)

  // Create and send immediately
  params = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true,
  }
  broadcast, _ := client.Broadcasts.Create(params)

  // Create and schedule
  params = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true,
    "scheduled_at": "in 1 hour",
  }
  broadcast, _ := client.Broadcasts.Create(params)
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::CreateBroadcastOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let segment_id = "78261eea-8f8b-4381-83c6-79fa7120f1cf";
    let from = "Acme <onboarding@resend.dev>";
    let subject = "hello world";
    let html = "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}";

    let opts = CreateBroadcastOptions::new(segment_id, from, subject).with_html(html);

    // Create a draft Broadcast
    let _broadcast = resend.broadcasts.create(opts.clone()).await?;

    // Create and send immediately
    let _broadcast = resend
      .broadcasts
      .create(opts.clone().with_send(true))
      .await?;

    // Create and schedule
    let _broadcast = resend
      .broadcasts
      .create(opts.with_send(true).with_scheduled_at("in 1 hour"))
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend resend = new Resend("re_xxxxxxxxx");

  // Create a draft Broadcast
  CreateBroadcastOptions params = CreateBroadcastOptions.builder()
      .segmentId("78261eea-8f8b-4381-83c6-79fa7120f1cf")
      .from("Acme <onboarding@resend.dev>")
      .subject("hello world")
      .html("Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}")
      .build();
  CreateBroadcastResponseSuccess data = resend.broadcasts().create(params);

  // Create and send immediately
  CreateBroadcastOptions params = CreateBroadcastOptions.builder()
      .segmentId("78261eea-8f8b-4381-83c6-79fa7120f1cf")
      .from("Acme <onboarding@resend.dev>")
      .subject("hello world")
      .html("Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}")
      .send(true)
      .build();
  CreateBroadcastResponseSuccess data = resend.broadcasts().create(params);

  // Create and schedule
  CreateBroadcastOptions params = CreateBroadcastOptions.builder()
      .segmentId("78261eea-8f8b-4381-83c6-79fa7120f1cf")
      .from("Acme <onboarding@resend.dev>")
      .subject("hello world")
      .html("Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}")
      .send(true)
      .scheduledAt("in 1 hour")
      .build();
  CreateBroadcastResponseSuccess data = resend.broadcasts().create(params);
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  // Create a draft Broadcast
  var resp = await resend.BroadcastAddAsync(
      new BroadcastData()
      {
          DisplayName = "Example Broadcast",
          SegmentId = new Guid( "78261eea-8f8b-4381-83c6-79fa7120f1cf" ),
          From = "Acme <onboarding@resend.dev>",
          Subject = "Hello, world!",
          HtmlBody = "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
      }
  );

  Console.WriteLine( "Broadcast Id={0}", resp.Content );

  // Create and send immediately
  var resp = await resend.BroadcastAddAsync(
      new BroadcastData()
      {
          DisplayName = "Example Broadcast",
          SegmentId = new Guid( "78261eea-8f8b-4381-83c6-79fa7120f1cf" ),
          From = "Acme <onboarding@resend.dev>",
          Subject = "Hello, world!",
          HtmlBody = "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
          Send = true,
      }
  );

  Console.WriteLine( "Broadcast Id={0}", resp.Content );

  // Create and schedule
  var resp = await resend.BroadcastAddAsync(
      new BroadcastData()
      {
          DisplayName = "Example Broadcast",
          SegmentId = new Guid( "78261eea-8f8b-4381-83c6-79fa7120f1cf" ),
          From = "Acme <onboarding@resend.dev>",
          Subject = "Hello, world!",
          HtmlBody = "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
          Send = true,
          ScheduledAt = DateTime.UtcNow.AddHours( 1 ),
      }
  );

  Console.WriteLine( "Broadcast Id={0}", resp.Content );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Create a draft Broadcast
  curl -X POST 'https://api.resend.com/broadcasts' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'
  {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "hello world",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}"
  }'

  # Create and send immediately
  curl -X POST 'https://api.resend.com/broadcasts' \
   -H 'Authorization: Bearer re_xxxxxxxxx' \
   -H 'Content-Type: application/json' \
   -d $'
  {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "hello world",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true
  }'

  # Create and schedule
  curl -X POST 'https://api.resend.com/broadcasts' \
   -H 'Authorization: Bearer re_xxxxxxxxx' \
   -H 'Content-Type: application/json' \
   -d $'
  {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "hello world",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    "send": true,
    "scheduled_at": "in 1 hour"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Create a draft Broadcast
  resend broadcasts create \
    --from "Acme <onboarding@resend.dev>" \
    --subject "hello world" \
    --segment-id 78261eea-8f8b-4381-83c6-79fa7120f1cf \
    --html "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}"

  # Create and send immediately
  resend broadcasts create \
    --from "Acme <onboarding@resend.dev>" \
    --subject "hello world" \
    --segment-id 78261eea-8f8b-4381-83c6-79fa7120f1cf \
    --html "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}" \
    --send

  # Create and schedule
  resend broadcasts create \
    --from "Acme <onboarding@resend.dev>" \
    --subject "hello world" \
    --segment-id 78261eea-8f8b-4381-83c6-79fa7120f1cf \
    --html "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}" \
    --send \
    --scheduled-at "in 1 hour"
  ```
</CodeGroup>

## Send Broadcasts

Use the [`send()` method](/docs/api-reference/broadcasts/send-broadcast) to send or schedule an existing API-created Broadcast by ID. Broadcasts created using the Dashboard Broadcast editor cannot be sent with this endpoint.

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.broadcasts.send(
    '559ac32e-9ef5-46fb-82a1-b76b840c0f7b',
    {
      scheduledAt: 'in 1 min',
    },
  );
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->broadcasts->send('559ac32e-9ef5-46fb-82a1-b76b840c0f7b', [
    'scheduled_at' => 'in 1 min',
  ]);
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Broadcasts.SendParams = {
    "broadcast_id": "559ac32e-9ef5-46fb-82a1-b76b840c0f7b",
    "scheduled_at": "in 1 min"
  }
  resend.Broadcasts.send(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    broadcast_id: "559ac32e-9ef5-46fb-82a1-b76b840c0f7b",
    scheduled_at: "in 1 min"
  }
  Resend::Broadcasts.send(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	sendParams := &resend.SendBroadcastRequest{
  		BroadcastId: "559ac32e-9ef5-46fb-82a1-b76b840c0f7b",
  		ScheduledAt: "in 1 min",
  	}

  	client.Broadcasts.Send(sendParams)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::SendBroadcastOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let opts =
      SendBroadcastOptions::new("559ac32e-9ef5-46fb-82a1-b76b840c0f7b").with_scheduled_at("in 1 min");

    let _broadcast = resend.broadcasts.send(opts).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend resend = new Resend("re_xxxxxxxxx");

  SendBroadcastOptions params = SendBroadcastOptions.builder()
      .scheduledAt("in 1 min")
      .build();

  SendBroadcastResponseSuccess data = resend.broadcasts().send(params,
      "498ee8e4-7aa2-4eb5-9f04-4194848049d1");
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  // Send now
  await resend.BroadcastSendAsync( new Guid( "559ac32e-9ef5-46fb-82a1-b76b840c0f7b" ) );

  // Send in 5 mins
  await resend.BroadcastScheduleAsync(
      new Guid( "559ac32e-9ef5-46fb-82a1-b76b840c0f7b" ),
      DateTime.UtcNow.AddMinutes( 5 ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/broadcasts/559ac32e-9ef5-46fb-82a1-b76b840c0f7b/send' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "scheduled_at": "in 1 min"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend broadcasts send 559ac32e-9ef5-46fb-82a1-b76b840c0f7b --scheduled-at "in 1 min"
  ```
</CodeGroup>

## Other ways to send

You can also send and manage Broadcasts using [Resend CLI commands](/docs/cli#broadcasts) and [AI building tools](/docs/ai-onboarding).

## API Reference

For complete API documentation, see the [Broadcasts API reference](/docs/api-reference/broadcasts/create-broadcast).


# Implementing BIMI
Source: https://resend.com/docs/dashboard/domains/bimi

Set up BIMI to gain brand recognition by displaying your logo in the inbox.

## Prerequisites

To get the most out of this guide, you will need to:

* Establish verifiable use of your logo
  * Obtain a registered trademark for your logo
  * Or, use your logo for over one year
* [Add a DMARC record on your domain](/docs/dashboard/domains/dmarc)

## What is BIMI?

BIMI ([Brand Indicators for Message Identification](https://bimigroup.org/)) is a standard that allows you to specify a logo (and sometimes a checkmark) to display next to your email in the inbox. These indicators can increase brand recognition and trust and improve engagement.

<img alt="bimi-example" />

Though this standard is newer, most major mailbox providers now support it. This gives BIMI adoption a competitive edge for brand recognition in the inbox. Most mailbox providers show brand indicators for those who purchase a certificate, of which there are two types: a Common Mark Certificate (CMC) and a Verified Mark Certificate (VMC).

Here's an overview of current email client support:

| Client                                                | BIMI w/a CMC | BIMI w/a VMC | BIMI w/out a VMC or CMC |
| ----------------------------------------------------- | ------------ | ------------ | ----------------------- |
| [Apple Mail](https://support.apple.com/en-us/108340)  | X            | ✓            | X                       |
| [Gmail](https://support.google.com/a/answer/10911320) | ✓            | ✓            | X                       |
| Outlook                                               | X            | X            | X                       |
| [Yahoo](https://senders.yahooinc.com/bimi/)           | ✓            | ✓            | ✓                       |

## Implementing BIMI

<Steps>
  <Step title="Configure DMARC">
    <Note>
      If you haven't set up DMARC yet, follow our [DMARC Setup
      Guide](/docs/dashboard/domains/dmarc).
    </Note>

    BIMI requires a DMARC policy of `p=quarantine;` or `p=reject;`. This policy assures that your emails are properly authenticated and that no one else can spoof your domain and send them with your logo.

    Here's an overview of the required parameters:

    | Parameter | Purpose    | Required Value                 |
    | --------- | ---------- | ------------------------------ |
    | `p`       | Policy     | `p=quarantine;` or `p=reject;` |
    | `pct`     | Percentage | `pct=100;`                     |

    Here is an example of an adequate DMARC record:

    ```
    "v=DMARC1; p=quarantine; pct=100; rua=mailto:dmarcreports@example.com"
    ```

    <Note>
      For BIMI on a subdomain, the root or APEX domain must also have a DMARC policy
      of `p=quarantine` or `p=reject` in addition to the subdomain. If not, the
      subdomain will not be compliant to display a BIMI logo.
    </Note>
  </Step>

  <Step title="Establish verifiable use of your logo">
    To display your logo in most email clients using BIMI, you need to prove ownership of your logo by obtaining a mark certificate. This process is similar to acquiring an SSL certificate for your website. You can purchase a mark certificate from one of the following [authorized mark verifying authorities](https://bimigroup.org/vmc-issuers/):

    * [DigiCert](https://www.digicert.com/tls-ssl/verified-mark-certificates)
    * [GlobalSign](https://www.globalsign.com/)
    * [SSL.com](https://www.ssl.com/)

    There are two possible mark Certificate's to verify the use of your logo:

    * **Verified Mark Certificate (VMC)**: A certificate issued by a Certificate Authority (CA) that is used to verify that you are the owner of the logo you are trying to display. A VMC is available if you have a trademark of your logo. With a VMC, Gmail will display a blue checkmark.
    * **Common Mark Certificate (CMC)**: A certificate also issued by Certificate Authority (CA) to verify you. A CMC is available to you if you can establish that you’ve used your logo for one year. Only Gmail and Yahoo support a CMC.

    A VMC offers the widest email client support, though the barrier of a trademark means a CMC is an easier path if you have established use of your logo for one year.

    Here are a some things to know before starting the certificate purchase process:

    * If you don't hold a trademark for your logo or have not used your logo for a year, you will not be able to purchase a certificate.
    * The process can take weeks, so start early and respond to their requests quickly.
    * You will need to provide a [SVG Tiny P/S formatted logo](https://bimigroup.org/creating-bimi-svg-logo-files/).
    * You will need to prove you own the domain by adding a DNS record.
    * You will need to prove you are the owner of the trademark or logo by providing identification.
    * You will need publicly available proof that your business exists. For newer startups, recommend [Yellow Pages](https://marketing.yellowpages.com/en/) or [Google Business Profiles](https://support.google.com/business/answer/3039617?hl=en) as the easiest method for proving your existence
  </Step>

  <Step title="Set your BIMI DNS Record">
    Once you have your VMC, you can set your BIMI DNS record. This TXT record points to the location of your VMC and your logo.

    | Name           | Type | Value                                               |
    | -------------- | ---- | --------------------------------------------------- |
    | default.\_bimi | TXT  | v=BIMI1; l=link\_to\_logo; a=link\_to\_certificate; |

    Here is an example of a BIMI record:

    ```
    v=BIMI1; l=https://vmc.digicert.com/00-00.svg; a=https://vmc.digicert.com/00-00.pem;
    ```

    <Tip>
      Ensure your logo uses an HTTPS URL. Mailbox providers will not display the
      logo if served from an HTTP URL.
    </Tip>

    It contains a publicly and programmatically accessible link to your verified logo (.svg) and a link to your VMC (.pem).

    To confirm that your BIMI record is published correctly, the [BIMI working group offers a tool](https://bimigroup.org/bimi-generator/) to check it.

    It often takes a few days for your logo to display in inboxes after this record propagates. Mailbox providers will also conditionally decide to show the logo based on the domain's sending email volume and reputation. A domain with a high spam or bounce rate may not have their avatar displayed.
  </Step>
</Steps>

## Reference

| Parameter | Purpose             | Example                                |
| --------- | ------------------- | -------------------------------------- |
| `v`       | The version of BIMI | `v=BIMI1`                              |
| `l`       | Logo                | `l=https://vmc.digicert.com/00-00.svg` |
| `a`       | Certificate         | `a=https://vmc.digicert.com/00-00.pem` |
| `s`       | Selector            | `s=springlogo`                         |

<Tip>
  The BIMI standard allows for multiple logos using the [selector
  parameter](https://bimigroup.org/how-and-why-to-implement-bimi-selectors/).
</Tip>

<Note>
  Having issues setting up BIMI? [We can help](https://resend.com/help).
</Note>


# Claiming a domain
Source: https://resend.com/docs/dashboard/domains/claim

Claim a domain that is already verified by another team.

A domain can only be active on one Resend team at a time. When you try to add a domain that has already been verified by another team, Resend will alert you that the domain is already in use.

* **If you own the team where the domain is registered**, delete the domain so you can add it in your desired team.

* **If you do not have access to the team where the domain is registered**, you can prove ownership and [claim the domain](#claim-a-domain) by adding a TXT record to your DNS and then verifying the claim.

## Why This Happens

Common reasons a domain you own may already be registered:

* A team member or contractor added it to a separate Resend team.
* You are logged into a different Resend team than the one where the domain was originally added.

Before claiming a domain, check with your team members or in your other teams to see if you can locate the verified domain and [transfer it between teams](/docs/dashboard/domains/manage-domains#transfer-a-domain-between-teams) instead.

## Claim a domain

Claim a domain by adding a TXT record to your DNS, or do it in one click via DomainConnect for supported registrars.

This record is provided along with the alert in your Dashboard, or when you [use the Domains API](#using-the-domains-API) and call the [**Claim Domain** API endpoint](/docs/api-reference/domains/claim-domain).

<img alt="Domain claim" />

After adding the TXT record, return to the dashboard and click **I've added the records**.

Resend verifies the domain ownership, releases the domain from the previous team, and shows you the records to add to your DNS for sending or receiving. See the full steps to [add a domain](/docs/add-a-domain).

## Using the Domains API

<Steps>
  <Step title="Start a claim">
    Call [Claim Domain](/docs/api-reference/domains/claim-domain) with the domain
    name. Resend creates a placeholder domain on your team and returns a
    `domain_claim` containing a TXT `record` to add to your DNS.
  </Step>

  <Step title="Add the TXT record">
    Add the returned TXT record at your DNS provider. It proves you control the
    domain.
  </Step>

  <Step title="Verify the claim">
    Call [Verify Domain Claim](/docs/api-reference/domains/verify-domain-claim).
    Resend checks the TXT record and runs ownership-safety checks before
    transferring the domain.
  </Step>

  <Step title="Track the status">
    Poll [Get Domain Claim](/docs/api-reference/domains/get-domain-claim) until the
    claim reaches `completed`.
  </Step>
</Steps>

## Claim status

| Status       | Meaning                                                  |
| ------------ | -------------------------------------------------------- |
| `pending`    | Waiting for DNS verification.                            |
| `verified`   | DNS proof accepted; the transfer is in progress.         |
| `completed`  | The domain now belongs to your team.                     |
| `blocked`    | A safety check blocked the claim — see `blocked_reason`. |
| `expired`    | The claim window passed before it completed.             |
| `superseded` | A newer claim replaced this one.                         |
| `canceled`   | The claim was canceled.                                  |
| `failed`     | The claim could not be completed.                        |

When a claim is `blocked`, `blocked_reason` explains why: `grace_period`,
`recent_owner_activity`, or `pending_scheduled_emails`.

## Canceling a claim

Cancel a pending claim initiated with the API by deleting its placeholder domain with
[Delete Domain](/docs/api-reference/domains/delete-domain), using the `domain_id`
from the `domain_claim` object.

## Support

If you can't locate your domain in another team, and you are unable to successfully claim the domain, contact [Resend support](https://resend.com/help) and share the domain name so the team can help you recover access.


# Configure a custom Return Path
Source: https://resend.com/docs/dashboard/domains/custom-return-path

Learn how to configure a custom Return Path for your verified domain in Resend.

By default, Resend uses the `send` subdomain for the Return-Path address.

You can provide a custom Return-Path address when you [add a new domain in the Dashboard](/docs/add-a-domain) under **Advanced options**, or by setting the optional `custom_return_path` parameter when [creating or updating a domain via the API](/docs/api-reference/domains/create-domain) or with [a domains CLI command](/docs/cli#domains).

<img alt="Custom Return Path" />

For the API, optionally pass the custom return path parameter.

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  resend.domains.create({ name: 'example.com', customReturnPath: 'outbound' });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->domains->create([
    'name' => 'example.com',
    'custom_return_path' => 'outbound'
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Domains.CreateParams = {
    "name": "example.com",
    "custom_return_path": "outbound"
  }

  resend.Domains.create(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend.api_key = ENV["RESEND_API_KEY"]

  params = {
    name: "example.com",
    custom_return_path: "outbound"
  }
  domain = Resend::Domains.create(params)
  puts domain
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import "github.com/resend/resend-go/v3"

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.CreateDomainRequest{
  		Name:             "example.com",
  		CustomReturnPath: "outbound",
  	}

  	domain, err := client.Domains.Create(params)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::CreateDomainOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let _domain = resend
      .domains
      .add(CreateDomainOptions::new("example.com").with_custom_return_path("outbound"))
      .await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateDomainOptions params = CreateDomainOptions
                  .builder()
                  .name("example.com")
                  .customReturnPath("outbound")
                  .build();

          CreateDomainResponse domain = resend.domains().create(params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.DomainAddAsync( new DomainAddData {
     DomainName = "example.com",
     CustomReturnPath = "outbound"
  } );
  Console.WriteLine( "Domain Id={0}", resp.Content.Id );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/domains' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "name": "example.com",
    "custom_return_path": "outbound"
  }'
  ```
</CodeGroup>

Custom return paths must adhere to the following rules:

* Must be 63 characters or less.
* Must start with a letter, and end with a letter or number.
* Must contain only letters, numbers, and hyphens.

Avoid setting values that could undermine credibility (e.g. `testing`), as they may be exposed to recipients in some email clients.


# Implementing DMARC
Source: https://resend.com/docs/dashboard/domains/dmarc

Implement DMARC to build trust in your domain and protect against email spoofing and unauthorized use of your domain in email messages.

## Prerequisites

Since DMARC relies on DKIM and SPF, first ensure your existing emails are passing SPF and DKIM.

* DKIM verifies the email wasn't altered in transit using cryptographic authentication.
* SPF authorizes IP addresses to send email for a domain.

If you have a [verified](/docs/dashboard/domains/introduction) domain with Resend, it means you are already passing SPF and DKIM.

<Info>
  For more details on understanding DMARC reports, see our [guide on how to read
  a DMARC report](https://resend.com/blog/how-to-read-a-dmarc-report). You can
  also use Resend's [DMARC analyzer](/docs/dmarc-analyzer) to visualize your DMARC
  reports.
</Info>

## What is DMARC?

DMARC ([Domain-based Message Authentication, Reporting, and Conformance](https://dmarc.org/overview/)) is an email authentication protocol that instructs mail servers what to do if an email message fails SPF and DKIM, preventing email spoofing (forged headers). DMARC is added to a domain through a TXT record added to the domain at `_dmarc`.

By preventing spoofing, a domain can build trust with mailbox providers, as it allows them to verify that emails are authorized to send on behalf of that domain.

An email must pass either SPF or DKIM checks (but not necessarily both) to achieve DMARC compliance and be considered authenticated. A message fails DMARC if both SPF and DKIM fail on the message.

## Implementing DMARC

<Steps>
  <Step title="Add a TXT _dmarc Record">
    To start, add a flexible DMARC record to your domain.

    | Name                | Type | Value                                                    |
    | ------------------- | ---- | -------------------------------------------------------- |
    | \_dmarc.example.com | TXT  | `v=DMARC1; p=none; rua=mailto:dmarcreports@example.com;` |

    This record is specifying a few parameters (see [Reference](#reference) section for more details):

    * `v` - Version:
      This is the version of DMARC
    * `p` - Policy:
      This is telling the inbox how to process messages that fail DMARC. Options are `none`, `quarantine`, `reject`. It's a best practice to use `quarantine` or `reject`, but only do this once you know your messages are delivering and fully passing DMARC.
    * `rua` - Reporting URI of Aggregate:
      Provide a **valid address** that can receive email. The address can be a different domain than the one on which you set the DMARC policy. The aggregate report comes as an email with a `.xml` file attached that shares the IP sources of your messages and if they passed SPF or DKIM.

    To ensure you don't accidentally introduce breaking changes to your email sending, we suggest starting with a policy of `p=none;` before moving to a stricter policy.
  </Step>

  <Step title="Test to Confirm Delivery and Passing">
    To test emails, send an email from all the applications and services your domain uses. Confirm that the messages are delivered to the inbox and that the headers show DMARC passing. Spending a few at this step is a good rule of thumb to ensure you're checking all sources of email from your domain and catch email that is sent at a different cadence than daily.

    To confirm DMARC passed, you can inspect the email headers and confirm there is `dmarc=pass`.

    <Tip>
      Gradually identify email sources using tools like [Google Postmaster
      Tools](https://gmail.com/postmaster/), which provides DKIM/SPF feedback.
      [DMARC monitoring
      services](https://dmarc.org/resources/products-and-services/) can aggregate
      your email sources by collecting DMARC reports, helping you discover any
      services sending email on your domain's behalf.
    </Tip>
  </Step>

  <Step title="Upgrade Policy">
    Once you have verified DMARC is passing across all your sending, upgrade your Policy to `p=quarantine;`. This policy gives mailbox providers greater confidence in your domain since your domain only allows authenticated email.

    Update the value of your existing `_dmarc` TXT record to use a stricter policy:

    | Name                | Type | Value                                                          |
    | ------------------- | ---- | -------------------------------------------------------------- |
    | \_dmarc.example.com | TXT  | `v=DMARC1; p=quarantine; rua=mailto:dmarcreports@example.com;` |

    Once you're confident that all legitimate email is passing DMARC, you can further tighten the policy to `reject`:

    | Name                | Type | Value                                                      |
    | ------------------- | ---- | ---------------------------------------------------------- |
    | \_dmarc.example.com | TXT  | `v=DMARC1; p=reject; rua=mailto:dmarcreports@example.com;` |

    <Info>
      While tightening your policy, it's important to have visibility into your
      DMARC failures to ensure you're not blocking legitimate email. We recommend
      adding aggregate reporting (`rua`) to your DMARC record to help you monitor
      and troubleshoot DMARC failures. For help analyzing your DMARC reports, see
      our [guide on how to read a DMARC
      report](https://resend.com/blog/how-to-read-a-dmarc-report) or use Resend's
      [DMARC analyzer](/docs/dmarc-analyzer).
    </Info>

    Here is a summary of the available policies and their behavior:

    | Policy        | Value                                            |
    | ------------- | ------------------------------------------------ |
    | p=none;       | Allow all email. Monitoring for DMARC failures.  |
    | p=quarantine; | Send messages that fail DMARC to the spam folder |
    | p=reject;     | Bounce delivery of emails that fail DMARC.       |

    Once your policy is `p=quarantine;` or `p=reject;` you can explore setting up [BIMI](/docs/dashboard/domains/bimi), which can provide established brands even greater sending credibility by displaying a logo as an avatar in an email client.
  </Step>
</Steps>

## Reference

<Tip>
  While the DMARC protocol includes both `pct` and `ruf` parameters, they are
  not widely followed by mailbox providers. These settings may not be respected
  or followed.
</Tip>

| Parameter | Purpose                                       | Example                           |
| --------- | --------------------------------------------- | --------------------------------- |
| `v`       | Protocol version                              | `v=DMARC1`                        |
| `pct`     | Percentage of messages subjected to filtering | `pct=20`                          |
| `ruf`     | Reporting URI for forensic reports            | `ruf=mailto:authfail@example.com` |
| `rua`     | Reporting URI of aggregate reports            | `rua=mailto:aggrep@example.com`   |
| `p`       | Policy for organizational domain              | `p=quarantine`                    |
| `sp`      | Policy for subdomains of the OD               | `sp=reject`                       |
| `adkim`   | Alignment mode for DKIM                       | `adkim=s`                         |
| `aspf`    | Alignment mode for SPF                        | `aspf=r`                          |

<Note>
  Having issues setting up DMARC? [We can help](https://resend.com/help).
</Note>


# Verified Domains
Source: https://resend.com/docs/dashboard/domains/introduction

An introduction to verified domains in Resend.

## Verified domains

Resend sends emails using a domain you own (i.e., not a shared or public domain). You must [add and verify at least one domain](/docs/add-a-domain) to send emails with Resend. You can optionally [configure your domain to receive emails](/docs/dashboard/receiving/custom-domains).

## Domain features

When you add a domain, you can choose to:

* Add a [subdomain](#subdomains) instead of your root domain to communicate the kind of emails you send and receive, and for proper reputation segmentation.
* Enable [open and click tracking](/docs/dashboard/domains/tracking) for your emails.
* Configure [Enforced Transport Layer Security (TLS)](/docs/dashboard/domains/tls) to ensure that you only send encrypted emails.
* Set a custom subdomain for the [Return-Path address](/docs/dashboard/domains/custom-return-path).
* Choose which [geographical region](/docs/dashboard/domains/regions) to send emails from to reach your recipients sooner.

After your domain is verified, you can:

* Send and receive emails [using any email address at your domain](/docs/knowledge-base/how-do-I-create-an-email-address-or-sender-in-resend#sender-email-addresses-in-resend) without any extra configuration.
* Implement [DMARC](/docs/dashboard/domains/dmarc) and [BIMI](/docs/dashboard/domains/bimi) to build trust and improve inbox placement.

## Subdomains

We recommend sending your emails from one or more subdomains (e.g., `updates.example.com`) instead of your root domain to isolate your sending reputation and to clearly communicate your intent to your recipients.

You can [add and verify](/docs/add-a-domain) multiple subdomains of the same domain (e.g. `newsletter.example.com` and `account.example.com`) for different sending purposes.

For example, you can configure your newsletter for open and click tracking while keeping tracking disabled for your important transactional emails such as password resets.

Learn more about [the benefits of sending emails from a subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain).

## Domain management

You can view and manage your domains from the [Domains Dashboard page](https://resend.com/domains). The Dashboard allows all members of your team to create, verify, retrieve, update, and delete your domains.

You can also manage your sending and receiving domains using the [API](/docs/api-reference/domains/create-domain), the [CLI](/docs/cli#domains), or the [MCP server](/docs/mcp-server).

Learn more about [managing your domains](/docs/dashboard/domains/manage-domains).

## Related Guides

See how to use Resend's verified domain features.

<CardGroup>
  <Card title="Manage domains" icon="gear" href="/dashboard/domains/manage-domains" />

  <Card title="Implement DMARC" icon="key" href="/dashboard/domains/dmarc" />

  <Card title="Enable Tracking" icon="chart-line-up-down" href="/dashboard/domains/tracking" />

  <Card title="Enforced TLS" icon="binary-lock" href="/dashboard/domains/tls" />

  <Card title="Custom return path" icon="code-simple" href="/dashboard/domains/custom-return-path" />

  <Card title="Choose region" icon="globe" href="/dashboard/domains/regions" />

  <Card title="Claim a domain" icon="bell-concierge" href="/dashboard/domains/claim" />

  <Card title="DNS provider guides" icon="book-atlas" href="/knowledge-base/cloudflare" />
</CardGroup>


# Managing Domains
Source: https://resend.com/docs/dashboard/domains/manage-domains

Learn how to view, update, and delete your verified domains in Resend.

## Domain management

You can view and manage your domains from the [Domains Dashboard page](https://resend.com/domains). You can also manage your sending and receiving domains using the [API](/docs/api-reference/domains/create-domain), the [CLI](/docs/cli#domains), or the [MCP server](/docs/mcp-server).

All members of your team can create, verify, retrieve, update, and delete your domains.

## View domain details

The [Domains Dashboard page](https://resend.com/domains) shows information about each domain's name, its verification status, and history. You can also filter your domains list by [status](#understand-a-domain-status) and [region](/docs/dashboard/domains/regions) and perform bulk actions on multiple domains, such as [deleting domains](#delete-a-domain).

You can also [retrieve a single domain](/docs/api-reference/domains/get-domain) or [list all domains](/docs/api-reference/domains/list-domains) via the API or SDKs, or use [CLI commands to view your domains](/docs/cli#domains).

## Understand a domain status

Domains can have different statuses, including:

* `not_started`: You've added a domain to Resend, but you haven't clicked on `Verify DNS Records` yet.
* `pending`: Resend is still trying to verify the domain.
* `verified`: Your domain is successfully verified for sending in Resend.
* `partially_verified`: One capability (send or receive) is verified while the other is still pending verification.
* `partially_failed`: The domain is verified but one of the features (send or receive) is not verified.
* `failed`: Resend was unable to detect the DNS records within 72 hours.
* `temporary_failure`: For a previously verified domain, Resend will periodically check for the DNS record required for verification. If at some point, Resend is unable to detect the record, the status would change to "Temporary Failure". Resend will recheck for the DNS record for 72 hours, and if it's unable to detect the record, the domain status would change to "Failure". If it's able to detect the record, the domain status would change to "Verified".

## View DNS records

For each domain you have added, you can view the [DKIM](#what-are-dkim-records) and [SPF](#what-are-spf-records) configurations generated by Resend, as well as [DMARC protocol parameters](/docs/dashboard/domains/dmarc) under the **Records** tab.

<img alt="Domain Details" />

<Info>
  Need specific help adding your records to a DNS provider? View our [DNS
  Guides](/docs/knowledge-base).
</Info>

## Update domain configuration

When viewing an individual domain, you can update its configuration options for [TLS](/docs/dashboard/domains/tls) and [tracking](/docs/dashboard/domains/tracking). You can also [delete your domain](#delete-a-domain) if you no longer want it associated with your Resend team.

## Delete a domain

Delete one or more domains by selecting them in your Domains Dashboard page and use the bulk action bar to delete all selected domains.

You can also delete a domain with the [Domains API](/docs/api-reference/domains/delete-domain), or with a [domains CLI command](/docs/cli#domains).

## Transfer a domain between teams

A domain can only be active on one Resend team at a time. For example, if someone else has already verified your domain in their own team, you will not be able to add it to yours.

To transfer a domain between teams you or your team members own, you must [delete the domain](#delete-a-domain) from the team where it is verified and [add it as a new domain](/docs/add-a-domain) while logged in to the desired team.

If you are unable to add a domain you own because it is already associated with a Resend team that you do not control, you can [claim the domain](/docs/dashboard/domains/claim).

## Export your data

Admins can download your data in CSV format for the following resources:

* Emails
* Broadcasts
* Contacts
* Segments
* Domains
* Logs
* API keys

<Info>Currently, exports are limited to admin users of your team.</Info>

To start, apply filters to your data and click on the "Export" button. Confirm your filters before exporting your data.

<video />

If your exported data includes 1,000 items or less, the export will download immediately. For larger exports, you'll receive an email with a link to download your data.

All admins on your team can securely access the export for 7 days. Unavailable exports are marked as "Expired."

<Note>
  All exports your team creates are listed in the
  [Exports](https://resend.com/exports) page under **Settings** > **Team** >
  **Exports**. Select any export to view its details page. All members of your
  team can view your exports, but only admins can download the data.
</Note>

## What are SPF records

Sender Policy Framework (SPF) is an email authentication standard that includes all the IP addresses authorized to send email on behalf of your domain.

The SPF configuration is made of a TXT DNS record that lists the IP addresses approved by the domain owner. Resend also generates an MX record that allows the recipient to send bounce and complaint feedback to your domain.

<img alt="SPF Records" />

## What are DKIM records

DomainKeys Identified Mail (DKIM) is an email security standard designed to make sure that an email that claims to come from a specific domain was authorized by the owner of that domain.

The DKIM configuration is stored as a TXT DNS record that contains a public key used to verify the authenticity of the email.

<img alt="DKIM Records" />


# Choosing a Region
Source: https://resend.com/docs/dashboard/domains/regions

Resend offers sending from multiple regions

Resend users have the option to send transactional and marketing emails from four different regions:

* North Virginia (us-east-1)
* Ireland (eu-west-1)
* São Paulo (sa-east-1)
* Tokyo (ap-northeast-1)

No matter where your users are, you can ensure that they receive your emails in a timely and efficient manner. You can visualize the different regions in the Resend dashboard:

<img alt="Multi Region Domains" />

## Data Residency

Region selection controls where your emails are **routed and sent from**. It does not control where customer data is stored.

All account data, including email metadata, logs, and API records, is stored in the United States regardless of the sending region you select. Choosing `eu-west-1` means your emails are dispatched from Ireland, but your Resend account data still resides in the US.

If your organization has strict data residency requirements, review the [Resend Subprocessors list](https://resend.com/legal/subprocessors) and [Privacy Policy](https://resend.com/legal/privacy-policy) for details on data handling.

## Benefits of choosing a region

Especially for transactional emails like magic links, password resets, and welcome messages, users expect to receive them right away. If they don't, they might not be able to access your service right away, which is a missed opportunity for your organization.

Here are some of the other benefits of using our multi-region email sending feature:

1. **Faster delivery:** By sending emails from the region closest to your user, you can reduce latency and ensure a faster time-to-inbox. This can be the difference between people using/buying your product or not.
2. **Easier account management:** Instead of having to maintain different accounts for each region, you get multi-region support within the same account. That way, you aren't juggling different login credentials.
3. **Increased resilience:** In case of disruption in one region, our multi-region feature enables you to send emails from a backup domain in a separate region, guaranteeing maximum uptime.

## Get Started

To start using our multi-region email sending feature, go to **[Domains](https://resend.com/domains)**, then select the option to add a new domain.

Finally, select the region you want to send your emails.

## How to set up multi-region for the same domain

For advanced needs, you can set up multiple regions for the same domain. We recommend setting a unique subdomain for each region (e.g., us.example.com, eu.example.com). When sending transactional emails or marketing emails, choose the right domain for your users.

## Changing Domain Region

If you'd like to switch the region your domain is set to:

1. Delete your current domain in the [Domain's page](https://resend.com/domains).
2. Add the same domain again, selecting the new region.
3. Update your DNS records to point to the new domain.

For more help, please reach out to [Support](https://resend.com/help) for assistance.


# Configure Transport Layer Security (TLS)
Source: https://resend.com/docs/dashboard/domains/tls

Learn how to configure TLS for your verified domain in Resend.

## Configure Enforced Transport Layer Security (TLS)

Resend supports TLS 1.2, TLS 1.1 and TLS 1.0 for TLS connections, but only requires TLS for sending when Enforced TLS is configured.

By default, Resend will attempt to make a secure connection, but will fall back to sending messages unencrypted when the receiving server does not support TLS. This is known as Opportunistic TLS.

You can instead configure Enforced TLS in the Resend Dashboard under the **Configuration** tab or with the [Domains API](/docs/api-reference/domains/create-domain) or with [a domains CLI command](/docs/cli#domains). This means that if the receiving server does not support TLS, your email will not be sent.

Learn more about [Opportunistic TLS vs Enforced TLS](/docs/knowledge-base/whats-the-difference-between-opportunistic-tls-vs-enforced-tls).


# Open and Click Tracking
Source: https://resend.com/docs/dashboard/domains/tracking

Track open and click rates of your emails.

Open and click tracking is disabled by default for all domains. We suggest only tracking open rates for [Broadcasts](/docs/dashboard/broadcasts/introduction) to ensure that inbox providers do not mistakenly identify your [transactional emails](/docs/dashboard/emails/introduction) as marketing emails.

You can enable tracking in the Resend Dashboard under the **Configuration** tab or programmatically when you create a new domain or update an existing domain.

Once verified, all tracked links in your emails will use your tracking subdomain (e.g., `links.emails.example.com`).

<Tabs>
  <Tab title="Using the dashboard">
    Go to the [**Domains** page](https://resend.com/domains) and click on the domain you want to configure.

    In the **Configuration** tab, click **Configure** under **Enable tracking metrics**.

    <img alt="Open and Click Tracking" />

    Provide a name for your tracking subdomain, enable open and/or click tracking, and click **+Add domain**.

    <img alt="Verify Custom Tracking Subdomain" />

    Add the CNAME record to your DNS settings (e.g. Cloudflare, GoDaddy, etc.) to verify your tracking subdomain.

    <img alt="Add Custom Tracking Subdomain" />

    <Info>
      If we detect CAA records on your domain, we will show an additional CAA record
      that needs to be created. This ensures that we can issue a TLS certificate for
      your tracking subdomain.
    </Info>

    Click **I've added the records** to verify the domain.

    Once verified, all tracked links in your emails will use your custom tracking subdomain.
  </Tab>

  <Tab title="Using the API">
    You can add a tracking subdomain when creating a new domain by passing the `tracking_subdomain` field along with `click_tracking` and/or `open_tracking`.

    <CodeGroup>
      ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.domains.create({
        name: 'example.com',
        openTracking: true,
        clickTracking: true,
        trackingSubdomain: 'links',
      });
      ```

      ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->domains->create([
        'name' => 'example.com',
        'open_tracking' => true,
        'click_tracking' => true,
        'tracking_subdomain' => 'links',
      ]);
      ```

      ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      params: resend.Domains.CreateParams = {
        "name": "example.com",
        "open_tracking": True,
        "click_tracking": True,
        "tracking_subdomain": "links",
      }

      resend.Domains.create(params)
      ```

      ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
      Resend.api_key = "re_xxxxxxxxx"

      params = {
        name: "example.com",
        open_tracking: true,
        click_tracking: true,
        tracking_subdomain: "links",
      }
      Resend::Domains.create(params)
      ```

      ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	params := &resend.CreateDomainRequest{
      		Name:              "example.com",
      		OpenTracking:      true,
      		ClickTracking:     true,
      		TrackingSubdomain: "links",
      	}

      	client.Domains.Create(params)
      }
      ```

      ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{types::CreateDomainOptions, Resend, Result};

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let _domain = resend
          .domains
          .create(
            CreateDomainOptions::new("example.com")
              .with_open_tracking(true)
              .with_click_tracking(true)
              .with_tracking_subdomain("links"),
          )
          .await?;

        Ok(())
      }
      ```

      ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;
      import com.resend.services.domains.model.CreateDomainOptions;

      Resend resend = new Resend("re_xxxxxxxxx");

      CreateDomainOptions params = CreateDomainOptions.builder()
              .name("example.com")
              .openTracking(true)
              .clickTracking(true)
              .trackingSubdomain("links")
              .build();

      resend.domains().create(params);
      ```

      ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      var resp = await resend.DomainAddAsync( new DomainAddData()
      {
          DomainName = "example.com",
          OpenTracking = true,
          ClickTracking = true,
          TrackingSubdomain = "links",
      } );
      ```

      ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X POST 'https://api.resend.com/domains' \
           -H 'Authorization: Bearer re_xxxxxxxxx' \
           -H 'Content-Type: application/json' \
           -d $'{
        "name": "example.com",
        "open_tracking": true,
        "click_tracking": true,
        "tracking_subdomain": "links"
      }'
      ```
    </CodeGroup>

    If you already have a domain, you can call the `update` endpoint to add a tracking subdomain and enable tracking.

    <CodeGroup>
      ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.domains.update({
        id: 'd91cd9bd-1176-453e-8fc1-35364d380206',
        openTracking: true,
        clickTracking: true,
        trackingSubdomain: 'links',
      });
      ```

      ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->domains->update(
        'd91cd9bd-1176-453e-8fc1-35364d380206',
        [
          'open_tracking' => true,
          'click_tracking' => true,
          'tracking_subdomain' => 'links',
        ]
      );
      ```

      ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      params: resend.Domains.UpdateParams = {
        "id": "d91cd9bd-1176-453e-8fc1-35364d380206",
        "open_tracking": True,
        "click_tracking": True,
        "tracking_subdomain": "links",
      }

      resend.Domains.update(params)
      ```

      ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
      Resend.api_key = "re_xxxxxxxxx"

      Resend::Domains.update({
        id: "d91cd9bd-1176-453e-8fc1-35364d380206",
        open_tracking: true,
        click_tracking: true,
        tracking_subdomain: "links",
      })
      ```

      ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	params := &resend.UpdateDomainRequest{
      		OpenTracking:      true,
      		ClickTracking:     true,
      		TrackingSubdomain: "links",
      	}

      	client.Domains.Update("d91cd9bd-1176-453e-8fc1-35364d380206", params)
      }
      ```

      ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{types::DomainChanges, Resend, Result};

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let changes = DomainChanges::new()
          .with_open_tracking(true)
          .with_click_tracking(true)
          .with_tracking_subdomain("links");

        let _domain = resend
          .domains
          .update("d91cd9bd-1176-453e-8fc1-35364d380206", changes)
          .await?;

        Ok(())
      }
      ```

      ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;
      import com.resend.services.domains.model.UpdateDomainOptions;

      Resend resend = new Resend("re_xxxxxxxxx");

      UpdateDomainOptions params = UpdateDomainOptions.builder()
              .id("d91cd9bd-1176-453e-8fc1-35364d380206")
              .openTracking(true)
              .clickTracking(true)
              .trackingSubdomain("links")
              .build();

      resend.domains().update(params);
      ```

      ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      await resend.DomainUpdateAsync(
          new Guid( "d91cd9bd-1176-453e-8fc1-35364d380206" ),
          new DomainUpdateData()
          {
              TrackOpen = true,
              TrackClicks = true,
              TrackingSubdomain = "links",
          }
      );
      ```

      ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X PATCH 'https://api.resend.com/domains/d91cd9bd-1176-453e-8fc1-35364d380206' \
           -H 'Authorization: Bearer re_xxxxxxxxx' \
           -H 'Content-Type: application/json' \
           -d $'{
        "open_tracking": true,
        "click_tracking": true,
        "tracking_subdomain": "links"
      }'
      ```
    </CodeGroup>

    Whether creating or updating a domain, the API will return the required DNS records that need to be added to your domain provider's DNS settings. Note the `Tracking` record.

    ```json {15-22} API Response Example theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "id": "4dd369bc-aa82-4ff3-97de-514ae3000ee0",
      "name": "example.com",
      "created_at": "2026-03-28 17:12:02.059593+00",
      "status": "not_started",
      "open_tracking": true,
      "click_tracking": true,
      "tracking_subdomain": "links",
      "capabilities": {
        "sending": "enabled",
        "receiving": "disabled"
      },
      "records": [
        // ... other records ...
        {
          "record": "Tracking",
          "name": "links.example.com",
          "type": "CNAME",
          "value": "links1.resend-dns.com",
          "ttl": "Auto",
          "status": "not_started"
        }
      ],
      "region": "us-east-1"
    }
    ```

    Add the required `CNAME` record to your domain provider's DNS settings (e.g. Cloudflare, GoDaddy, etc.).

    <Info>
      If we detect CAA records on your domain, we will show an additional CAA record
      that needs to be created. This ensures that we can issue a TLS certificate for
      your tracking subdomain.
    </Info>

    Once you've added the required DNS record(s), call the `verify` endpoint to verify the domain.

    <CodeGroup>
      ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.domains.verify(
        'd91cd9bd-1176-453e-8fc1-35364d380206',
      );
      ```

      ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->domains->verify('d91cd9bd-1176-453e-8fc1-35364d380206');
      ```

      ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      resend.Domains.verify(domain_id="d91cd9bd-1176-453e-8fc1-35364d380206")
      ```

      ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
      Resend.api_key = "re_xxxxxxxxx"

      Resend::Domains.verify("d91cd9bd-1176-453e-8fc1-35364d380206")
      ```

      ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
      	client := resend.NewClient("re_xxxxxxxxx")

      	client.Domains.Verify("d91cd9bd-1176-453e-8fc1-35364d380206")
      }
      ```

      ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{Resend, Result};

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        resend
          .domains
          .verify("d91cd9bd-1176-453e-8fc1-35364d380206")
          .await?;

        Ok(())
      }
      ```

      ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;

      Resend resend = new Resend("re_xxxxxxxxx");

      VerifyDomainResponse verified = resend.domains().verify("d91cd9bd-1176-453e-8fc1-35364d380206");
      ```

      ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
      using Resend;

      IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

      await resend.DomainVerifyAsync( new Guid( "d91cd9bd-1176-453e-8fc1-35364d380206" ) );
      ```

      ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X POST 'https://api.resend.com/domains/d91cd9bd-1176-453e-8fc1-35364d380206/verify' \
           -H 'Authorization: Bearer re_xxxxxxxxx' \
           -H 'Content-Type: application/json'
      ```
    </CodeGroup>

    <Note>
      Tracking is active only when both of these conditions are met:

      <ol>
        <li>
          The `open_tracking` or `click_tracking` setting is enabled for the domain.
        </li>

        <li>
          A tracking subdomain is configured (e.g., `links.example.com`) and
          successfully verified.
        </li>
      </ol>
    </Note>

    All tracked links in your emails will use your tracking subdomain.

    View the [API reference](/docs/api-reference/domains/create-domain) for more details.
  </Tab>
</Tabs>

## How Open Tracking Works

A 1x1 pixel transparent GIF image is inserted in each email and includes a unique reference to this image file. When
the image is downloaded, Resend can tell exactly which message was opened and by whom.

## How Click Tracking Works

To track clicks, Resend modifies each link in the body of the HTML email to point to your tracking subdomain.

When recipients clicks a link, the request is redirected to your tracking subdomain, their click event is recorded, and they are redirected to the original URL.

## Troubleshooting

### Multiple tracking CNAME records

When you change your tracking subdomain, you may see two CNAME records in the DNS Records table: one active and one inactive (shown dimmed). The inactive record is kept intentionally to avoid breaking links in emails that were already sent using the previous subdomain. You do not need to remove it.

### Changing the Tracking Subdomain

Because tracking subdomains are used in email links, they're handled differently than other records.

* **Not removable**: After your tracking subdomain has been created, it can only be changed, never removed. This behavior preserves any
  email links that may already be sent with the current tracking subdomain. For this reason, do **not remove old tracking DNS records**. (All previously used records remain active and are included in the response.)
* **Requires verification**: After changing the tracking subdomain, a new DNS record must be verified. Until then, the previous value is used.

### Removing a Domain with a Tracking Subdomain

If you remove a domain with a configured tracking subdomain, the Resend provisioned proxy will also be removed, breaking
any existing email links that use that subdomain.

To keep links working, set up your own proxy pointing to Resend’s tracking DNS records before removing the domain.

### Unsupported Domains

Custom tracking subdomains require us to issue a TLS certificate. Some domains under regional restrictions are not
supported by our certificate provider and cannot use custom tracking subdomains. Learn more in the [certificate provider
docs](https://knowledge.digicert.com/solution/embargoed-countries-and-regions).


# Add an unsubscribe link to transactional emails
Source: https://resend.com/docs/dashboard/emails/add-unsubscribe-to-transactional-emails

Learn how to give email recipients the ability to unsubscribe without searching for the unsubscribe link.

<Info>
  For contact and unsubscribe management workflows, see the [Audiences
  overview](/docs/dashboard/audiences/introduction), where Broadcasts are built for
  keeping track of topics, segments, and unsubscribe preferences.
</Info>

Resend doesn't manage contact lists for transactional emails.

If you manage your own list, you can add the `List-Unsubscribe: https://example.com/unsubscribe` header when sending emails using the Resend API.

As of February 2024, your bulk messages must include a URL version in your list-unsubscribe header, `List-Unsubscribe-Post: List-Unsubscribe=One-Click`, and to allow for a `POST` request from the same URL. This follows [RFC 8058](https://datatracker.ietf.org/doc/html/rfc8058) (Signaling One-Click Functionality for List Email Headers).

When receiving a `POST`, return a blank page with `200 (OK)` or `202 (Accepted)`, and show the regular unsubscribe page with the `GET` method. Ensure that users stop receiving email within 48 hours of this request.

This header allows email clients to offer a one-click "Unsubscribe" option in their UI, enhancing user experience and decreasing spam complaints. Gmail and Yahoo require RFC 8058 compliance for bulk senders (those sending more than 5,000 messages per day to their domains).

You can read more about this requirement in our [Bulk Sending Requirements blog post.](https://resend.com/blog/gmail-and-yahoo-bulk-sending-requirements-for-2024#one-click-unsubscribe)

```ts Node.js {11} theme={"theme":{"light":"github-light","dark":"vesper"}}
import { Resend } from 'resend';

const resend = new Resend('re_xxxxxxxxx');

await resend.emails.send({
  from: 'Acme <onboarding@resend.dev>',
  to: ['delivered@resend.dev'],
  subject: 'hello world',
  text: 'it works!',
  headers: {
    'List-Unsubscribe': '<https://example.com/unsubscribe>',
  },
});
```


# Attachments
Source: https://resend.com/docs/dashboard/emails/attachments

Send emails with attachments.

There are two ways to send attachments:

1. [From a remote file](#send-attachments-from-a-remote-file)
2. [From a local file](#send-attachments-from-a-local-file)

<Info>
  We currently do not support sending attachments [when using our batch
  endpoint](/docs/api-reference/emails/send-batch-emails).
</Info>

## Send attachments from a remote file

Include the `path` parameter to send attachments from a remote file. This parameter accepts a URL to the file you want to attach.

Define the file name that will be attached using the `filename` parameter.

<CodeGroup>
  ```ts Node.js {12-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Receipt for your payment',
    html: '<p>Thanks for the payment</p>',
    attachments: [
      {
        path: 'https://resend.com/static/sample/invoice.pdf',
        filename: 'invoice.pdf',
      },
    ],
  });
  ```

  ```php PHP {10-11} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->send([
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'Receipt for your payment',
    'html' => '<p>Thanks for the payment</p>',
    'attachments' => [
      [
        'path' => 'https://resend.com/static/sample/invoice.pdf',
        'filename' => 'invoice.pdf'
      ]
    ]
  ]);
  ```

  ```python Python {6-7} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  attachment: resend.RemoteAttachment = {
    "path": "https://resend.com/static/sample/invoice.pdf",
    "filename": "invoice.pdf",
  }

  params: resend.Emails.SendParams = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Receipt for your payment",
    "html": "<p>Thanks for the payment</p>",
    "attachments": [attachment],
  }

  resend.Emails.send(params)
  ```

  ```rb Ruby {12-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Receipt for your payment",
    "html": "<p>Thanks for the payment</p>",
    "attachments": [
      {
        "path": "https://resend.com/static/sample/invoice.pdf",
        "filename": 'invoice.pdf',
      }
    ]
  }

  Resend::Emails.send(params)
  ```

  ```go Go {12-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
    ctx := context.TODO()
    client := resend.NewClient("re_xxxxxxxxx")

    attachment := &resend.Attachment{
      Path:  "https://resend.com/static/sample/invoice.pdf",
      Filename: "invoice.pdf",
    }

    params := &resend.SendEmailRequest{
        From:        "Acme <onboarding@resend.dev>",
        To:          []string{"delivered@resend.dev"},
        Subject:     "Receipt for your payment",
        Html:        "<p>Thanks for the payment</p>",
        Attachments: []*resend.Attachment{attachment},
    }

    sent, err := client.Emails.SendWithContext(ctx, params)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Id)
  }
  ```

  ```rust Rust {12-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::{CreateAttachment, CreateEmailBaseOptions};
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let from = "Acme <onboarding@resend.dev>";
    let to = ["delivered@resend.dev"];
    let subject = "Receipt for your payment";

    let path = "https://resend.com/static/sample/invoice.pdf";
    let filename = "invoice.pdf";

    let email = CreateEmailBaseOptions::new(from, to, subject)
      .with_html("<p>Thanks for the payment</p>")
      .with_attachment(CreateAttachment::from_path(path).with_filename(filename));

    let _email = resend.emails.send(email).await?;

    Ok(())
  }
  ```

  ```java Java {8-9} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          Attachment att = Attachment.builder()
                  .path("https://resend.com/static/sample/invoice.pdf")
                  .fileName("invoice.pdf")
                  .build();

          CreateEmailOptions params = CreateEmailOptions.builder()
                  .from("Acme <onboarding@resend.dev>")
                  .to("delivered@resend.dev")
                  .subject("Receipt for your payment")
                  .html("<p>Thanks for the payment</p>")
                  .attachments(att)
                  .build();

          CreateEmailResponse data = resend.emails().send(params);
      }
  }
  ```

  ```csharp .NET {14-18} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;
  using System.Collections.Generic;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var message = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = "Receipt for your payment",
      HtmlBody = "<p>Thanks for the payment</p>",
  };

  message.Attachments = new List<EmailAttachment>();
  message.Attachments.Add( new EmailAttachment() {
    Filename = "invoice.pdf",
    Path = "https://resend.com/static/sample/invoice.pdf",
  } );

  var resp = await resend.EmailSendAsync( message );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL {11-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Receipt for your payment",
    "html": "<p>Thanks for the payment</p>",
    "attachments": [
      {
        "path": "https://resend.com/static/sample/invoice.pdf",
        "filename": "invoice.pdf"
      }
    ]
  }'
  ```
</CodeGroup>

## Send attachments from a local file

Include the `content` parameter to send attachments from a local file. This parameter accepts the Base64 encoded content of the file you want to attach.

Define the file name that will be attached using the `filename` parameter.

<CodeGroup>
  ```ts Node.js {16-17} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import fs from 'fs';

  const resend = new Resend('re_xxxxxxxxx');

  const filepath = `${__dirname}/static/invoice.pdf`;
  const attachment = fs.readFileSync(filepath).toString('base64');

  await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Receipt for your payment',
    text: '<p>Thanks for the payment</p>',
    attachments: [
      {
        content: attachment,
        filename: 'invoice.pdf',
      },
    ],
  });
  ```

  ```php PHP {10-11} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->send([
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'Receipt for your payment',
    'html' => '<p>Thanks for the payment</p>',
    'attachments' => [
      [
        'filename' => 'invoice.pdf',
        'content' => $invoiceBuffer
      ]
    ]
  ]);
  ```

  ```python Python {10} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import os
  import resend

  resend.api_key = "re_xxxxxxxxx"

  f: bytes = open(
    os.path.join(os.path.dirname(__file__), "../static/invoice.pdf"), "rb"
  ).read()

  attachment: resend.Attachment = {"content": list(f), "filename": "invoice.pdf"}

  params: resend.Emails.SendParams = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Receipt for your payment",
    "html": "<p>Thanks for the payment</p>",
    "attachments": [attachment],
  }

  resend.Emails.send(params)
  ```

  ```rb Ruby {14-15} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  file = IO.read("invoice.pdf")

  params = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Receipt for your payment",
    "html": "<p>Thanks for the payment</p>",
    "attachments": [
      {
        "content": file.bytes,
        "filename": 'invoice.pdf',
      }
    ]
  }

  Resend::Emails.send(params)
  ```

  ```go Go {19-20} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"fmt"
  	"os"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
    ctx := context.TODO()
    client := resend.NewClient("re_xxxxxxxxx")

    pwd, _ := os.Getwd()
    f, err := os.ReadFile(pwd + "/static/invoice.pdf")
    if err != nil {
      panic(err)
    }

    attachment := &resend.Attachment{
      Content:  f,
      Filename: "invoice.pdf",
    }

    params := &resend.SendEmailRequest{
        From:        "Acme <onboarding@resend.dev>",
        To:          []string{"delivered@resend.dev"},
        Subject:     "Receipt for your payment",
        Html:        "<p>Thanks for the payment</p>",
        Attachments: []*resend.Attachment{attachment},
    }

    sent, err := client.Emails.SendWithContext(ctx, params)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Id)
  }
  ```

  ```rust Rust {22} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use std::fs::File;
  use std::io::Read;

  use resend_rs::types::{CreateAttachment, CreateEmailBaseOptions};
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let from = "Acme <onboarding@resend.dev>";
    let to = ["delivered@resend.dev"];
    let subject = "Receipt for your payment";

    let filename = "invoice.pdf";
    let mut f = File::open(filename).unwrap();
    let mut invoice = Vec::new();
    f.read_to_end(&mut invoice).unwrap();

    let email = CreateEmailBaseOptions::new(from, to, subject)
      .with_html("<p>Thanks for the payment</p>")
      .with_attachment(CreateAttachment::from_content(invoice).with_filename(filename));

    let _email = resend.emails.send(email).await?;

    Ok(())
  }
  ```

  ```java Java {8-9} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          Attachment att = Attachment.builder()
                  .fileName("invoice.pdf")
                  .content("invoiceBuffer")
                  .build();

          CreateEmailOptions params = CreateEmailOptions.builder()
                  .from("Acme <onboarding@resend.dev>")
                  .to("delivered@resend.dev")
                  .subject("Receipt for your payment")
                  .html("<p>Thanks for the payment</p>")
                  .attachments(att)
                  .build();

          CreateEmailOptions params = CreateEmailOptions.builder()
      }
  }
  ```

  ```csharp .NET {15-19} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;
  using System.Collections.Generic;
  using System.IO;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var message = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = "Receipt for your payment",
      HtmlBody = "<p>Thanks for the payment</p>",
  };

  message.Attachments = new List<EmailAttachment>();
  message.Attachments.Add( new EmailAttachment() {
    Filename = "invoice.pdf",
    Content = await File.ReadAllBytesAsync( "invoice.pdf" ),
  } );

  var resp = await resend.EmailSendAsync( message );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL {11-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Receipt for your payment",
    "html": "<p>Thanks for the payment</p>",
    "attachments": [
      {
        "content": "UmVzZW5kIGF0dGFjaG1lbnQgZXhhbXBsZS4gTmljZSBqb2Igc2VuZGluZyB0aGUgZW1haWwh%",
        "filename": "invoice.txt"
      }
    ]
  }'
  ```

  ```bash CLI {6} theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails send \
    --from "Acme <onboarding@resend.dev>" \
    --to delivered@resend.dev \
    --subject "Receipt for your payment" \
    --html "<p>Thanks for the payment</p>" \
    --attachment ./static/invoice.pdf
  ```
</CodeGroup>

## Embed Images using CID

You can optionally embed an image in the HTML body of the email. Both remote and local attachments are supported. All attachment requirements, options, and limitations apply to embedded inline images as well.

Embedding images requires two steps:

**1. Add the CID in the email HTML.**

Use the prefix `cid:` to reference the ID in the `src` attribute of an image tag in the HTML body of the email.

```html theme={"theme":{"light":"github-light","dark":"vesper"}}
<img src="cid:logo-image" />
```

**2. Reference the CID in the attachment**

The content id is an arbitrary string set by you, and must be less than 128 characters.

<CodeGroup>
  ```ts Node.js {9, 14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Thank you for contacting us',
    html: '<p>Here is our <img src="cid:logo-image"/> inline logo</p>',
    attachments: [
      {
        path: 'https://resend.com/static/sample/logo.png',
        filename: 'logo.png',
        contentId: 'logo-image',
      },
    ],
  });
  ```

  ```php PHP {7,12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->send([
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'Thank you for contacting us',
    'html' => '<p>Here is our <img src="cid:logo-image"/> inline logo</p>',
    'attachments' => [
      [
        'path' => 'https://resend.com/static/sample/logo.png',
        'filename' => 'logo.png',
        'content_id' => 'logo-image',
      ]
    ]
  ]);
  ```

  ```python Python {8,15} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  attachment: resend.RemoteAttachment = {
    "path": "https://resend.com/static/sample/logo.png",
    "filename": "logo.png",
    "content_id": "logo-image",
  }

  params: resend.Emails.SendParams = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Thank you for contacting us",
    "html": "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
    "attachments": [attachment],
  }

  resend.Emails.send(params)
  ```

  ```rb Ruby {9, 14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Thank you for contacting us",
    "html": "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
    "attachments": [
      {
        "path": "https://resend.com/static/sample/logo.png",
        "filename": 'logo.png',
        "content_id": "logo-image",
      }
    ]
  }

  Resend::Emails.send(params)
  ```

  ```go Go {14, 21} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
    ctx := context.TODO()
    client := resend.NewClient("re_xxxxxxxxx")

    attachment := &resend.Attachment{
      Path:  "https://resend.com/static/sample/logo.png",
      Filename: "logo.png",
      ContentId: "logo-image",
    }

    params := &resend.SendEmailRequest{
        From:        "Acme <onboarding@resend.dev>",
        To:          []string{"delivered@resend.dev"},
        Subject:     "Thank you for contacting us",
        Html:        "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
        Attachments: []*resend.Attachment{attachment},
    }

    sent, err := client.Emails.SendWithContext(ctx, params)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Id)
  }
  ```

  ```rust Rust {14, 17} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::{CreateAttachment, CreateEmailBaseOptions};
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let from = "Acme <onboarding@resend.dev>";
    let to = ["delivered@resend.dev"];
    let subject = "Thank you for contacting us";

    let path = "https://resend.com/static/sample/logo.png";
    let filename = "logo.png";
    let content_id = "logo-image";

    let email = CreateEmailBaseOptions::new(from, to, subject)
      .with_html("<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>")
      .with_attachment(
        CreateAttachment::from_path(path)
          .with_filename(filename)
          .with_content_id(content_id),
      );

    let _email = resend.emails.send(email).await?;

    Ok(())
  }
  ```

  ```java Java {10, 17} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          Attachment att = Attachment.builder()
                  .path("https://resend.com/static/sample/logo.png")
                  .fileName("logo.png")
                  .ContentId("logo-image")
                  .build();

          CreateEmailOptions params = CreateEmailOptions.builder()
                  .from("Acme <onboarding@resend.dev>")
                  .to("delivered@resend.dev")
                  .subject("Thank you for contacting us")
                  .html("<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>")
                  .attachments(att)
                  .build();

          CreateEmailResponse data = resend.emails().send(params);
      }
  }
  ```

  ```csharp .NET {11, 18} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;
  using System.Collections.Generic;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var message = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = "Thank you for contacting us",
      HtmlBody = "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
  };

  message.Attachments = new List<EmailAttachment>();
  message.Attachments.Add( new EmailAttachment() {
    Filename = "logo.png",
    Path = "https://resend.com/static/sample/logo.png",
    ContentId = "logo-image",
  } );

  var resp = await resend.EmailSendAsync( message );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL {8,13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Thank you for contacting us",
    "html": "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
    "attachments": [
      {
        "path": "https://resend.com/static/sample/logo.png",
        "filename": "logo.png",
        "content_id": "logo-image"
      }
    ]
  }'
  ```
</CodeGroup>

Learn more about [embedding images](/docs/dashboard/emails/embed-inline-images).

## View and Download Attachments

You can view and download attachments from sent emails from the dashboard or programmatically through the [Attachments API](/docs/api-reference/emails/list-email-attachments).

### From the dashboard

1. Go to [Emails](https://resend.com/emails).
2. Navigate to any email you sent with an attachment.
3. Click on the attachment to download it locally.

Attachments include the filename and an icon to help you identify the type of attachment. Each attachment type has a unique icon:

* Image
* PDF
* Spreadsheet
* Default (for unknown types)

### From the API

Use [List Attachments](/docs/api-reference/emails/list-email-attachments) to fetch all attachments for a sent email, or [Retrieve Attachment](/docs/api-reference/emails/retrieve-email-attachment) to fetch a single one. Both endpoints return a signed `download_url` that you can use to download the content.

## Attachment Limitations

* Emails can be no larger than 40MB (including attachments after Base64 encoding).
* Not all file types are supported. See the list of [unsupported file types](/docs/knowledge-base/what-attachment-types-are-not-supported).
* Emails with attachments cannot be sent using our [batching endpoint](/docs/api-reference/emails/send-batch-emails).

## Examples

### Attachments

<CardGroup>
  <Card title="Next.js (TypeScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/attachments">
    See the full source code.
  </Card>

  <Card title="Next.js (JavaScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/attachments">
    See the full source code.
  </Card>

  <Card title="PHP" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/attachments">
    See the full source code.
  </Card>

  <Card title="Laravel" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/laravel-resend-examples">
    See the full source code.
  </Card>

  <Card title="Python" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/python-resend-examples/examples">
    See the full source code.
  </Card>

  <Card title="Ruby" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/examples">
    See the full source code.
  </Card>
</CardGroup>

### Inline Images (CID)

<CardGroup>
  <Card title="Next.js (TypeScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/cid-attachments">
    See the full source code.
  </Card>

  <Card title="Next.js (JavaScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/cid-attachments">
    See the full source code.
  </Card>

  <Card title="PHP" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/attachments">
    See the full source code.
  </Card>

  <Card title="Laravel" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/laravel-resend-examples">
    See the full source code.
  </Card>

  <Card title="Python" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/python-resend-examples/examples">
    See the full source code.
  </Card>

  <Card title="Ruby" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/examples">
    See the full source code.
  </Card>
</CardGroup>


# Batch Sending
Source: https://resend.com/docs/dashboard/emails/batch-sending

Send up to 100 emails in a single API call.

Batch sending allows you to send multiple emails at once (up to 100) instead of making individual API requests for each email.

## When to use batch sending

Use batch sending when you need to:

* Send multiple transactional emails (e.g., order confirmations and notifications)
* Trigger emails to different recipients with unique content
* Reduce the number of API calls to improve performance

<Note>
  For marketing campaigns, [use our no-code editor,
  Broadcasts](/docs/dashboard/broadcasts/introduction), instead.
</Note>

## Send batch emails

You can send up to 100 emails in a single API call using the batch endpoint. Each email in the batch can have different recipients, subjects, and content.

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.batch.send([
    {
      from: 'Acme <onboarding@resend.dev>',
      to: ['delivered@resend.dev'],
      subject: 'Welcome to Acme',
      html: '<p>Thanks for signing up!</p>',
    },
    {
      from: 'Acme <onboarding@resend.dev>',
      to: ['delivered@resend.dev'],
      subject: 'Order Confirmation',
      html: '<p>Your order has been confirmed.</p>',
    },
  ]);

  console.log(data);
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->batch->send([
    [
      'from' => 'Acme <onboarding@resend.dev>',
      'to' => ['delivered@resend.dev'],
      'subject' => 'Welcome to Acme',
      'html' => '<p>Thanks for signing up!</p>',
    ],
    [
      'from' => 'Acme <onboarding@resend.dev>',
      'to' => ['delivered@resend.dev'],
      'subject' => 'Order Confirmation',
      'html' => '<p>Your order has been confirmed.</p>',
    ]
  ]);
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend
  from typing import List

  resend.api_key = "re_xxxxxxxxx"

  params: List[resend.Emails.SendParams] = [
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Welcome to Acme",
      "html": "<p>Thanks for signing up!</p>",
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Order Confirmation",
      "html": "<p>Your order has been confirmed.</p>",
    }
  ]

  resend.Batch.send(params)
  ```

  ```rb Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = 're_xxxxxxxxx'

  params = [
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Welcome to Acme",
      "html": "<p>Thanks for signing up!</p>",
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Order Confirmation",
      "html": "<p>Your order has been confirmed.</p>",
    }
  ]

  Resend::Batch.send(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
    ctx := context.TODO()
    client := resend.NewClient("re_xxxxxxxxx")

    var batchEmails = []*resend.SendEmailRequest{
      {
        From:    "Acme <onboarding@resend.dev>",
        To:      []string{"delivered@resend.dev"},
        Subject: "Welcome to Acme",
        Html:    "<p>Thanks for signing up!</p>",
      },
      {
        From:    "Acme <onboarding@resend.dev>",
        To:      []string{"delivered@resend.dev"},
        Subject: "Order Confirmation",
        Html:    "<p>Your order has been confirmed.</p>",
      },
    }

    sent, err := client.Batch.SendWithContext(ctx, batchEmails)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Data)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::CreateEmailBaseOptions;
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let emails = vec![
      CreateEmailBaseOptions::new(
        "Acme <onboarding@resend.dev>",
        vec!["delivered@resend.dev"],
        "Welcome to Acme",
      )
      .with_html("<p>Thanks for signing up!</p>"),
      CreateEmailBaseOptions::new(
        "Acme <onboarding@resend.dev>",
        vec!["delivered@resend.dev"],
        "Order Confirmation",
      )
      .with_html("<p>Your order has been confirmed.</p>"),
    ];

    let _emails = resend.batch.send(emails).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;
  import java.util.Arrays;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateEmailOptions firstEmail = CreateEmailOptions.builder()
              .from("Acme <onboarding@resend.dev>")
              .to("delivered@resend.dev")
              .subject("Welcome to Acme")
              .html("<p>Thanks for signing up!</p>")
              .build();

          CreateEmailOptions secondEmail = CreateEmailOptions.builder()
              .from("Acme <onboarding@resend.dev>")
              .to("delivered@resend.dev")
              .subject("Order Confirmation")
              .html("<p>Your order has been confirmed.</p>")
              .build();

          CreateBatchEmailsResponse data = resend.batch().send(
              Arrays.asList(firstEmail, secondEmail)
          );
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create("re_xxxxxxxxx");

  var mail1 = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = "Welcome to Acme",
      HtmlBody = "<p>Thanks for signing up!</p>",
  };

  var mail2 = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = "Order Confirmation",
      HtmlBody = "<p>Your order has been confirmed.</p>",
  };

  var resp = await resend.EmailBatchAsync([mail1, mail2]);
  Console.WriteLine("Nr Emails={0}", resp.Content.Data.Count);
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails/batch' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'[
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Welcome to Acme",
      "html": "<p>Thanks for signing up!</p>"
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Order Confirmation",
      "html": "<p>Your order has been confirmed.</p>"
    }
  ]'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails batch --file ./path/to/emails.json
  ```
</CodeGroup>

## Response format

The batch endpoint returns an array of email IDs for successfully created emails.
When the request succeeds, each entry in `data` corresponds to the email at the same index in the batch payload (0-based). The first email in your request will be the first entry in `data`, and so on.

```json theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "data": [
    {
      "id": "ae2014de-c168-4c61-8267-70d2662a1ce1"
    },
    {
      "id": "faccb7a5-8a28-4e9a-ac64-8da1cc3bc1cb"
    }
  ]
}
```

If the request fails, the response will include an `error` object with a `message` property. You can find more information about the error in the [Errors](/docs/api-reference/errors) section of the API Reference.

## Limitations

When using batch sending, keep in mind:

* Maximum of **100 emails** per batch request
* The `attachments` field is not supported yet
* Each email in the batch is processed independently
* The request will fail and return an error if any email in your payload is invalid (for example, required fields are missing or fields contain invalid data).

## View batch emails

All emails sent via the batch endpoint appear in the [Emails page](https://resend.com/emails) of your dashboard along with individually sent emails. Each email will have a `queued` status initially before being processed.

## API Reference

For complete API documentation, see the [Send Batch Emails API reference](/docs/api-reference/emails/send-batch-emails).


# Custom Headers
Source: https://resend.com/docs/dashboard/emails/custom-headers

Customize how emails are sent with your own headers.

Email headers are typically hidden from the end user but are crucial for deliverability. They include information about the sender, receiver, timestamp, and more.

Resend already includes all the necessary headers for you, but now you can also add your own custom headers.

This is a fairly advanced feature, but it can be useful for a few things:

* Prevent threading on Gmail with the **`X-Entity-Ref-ID`** header ([Example](https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/prevent-threading))
* Include a shortcut for users to unsubscribe with the **`List-Unsubscribe`** header

Here's how you can add custom headers to your emails:

<CodeGroup>
  ```ts Node.js {11} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'hello world',
    html: '<p>it works!</p>',
    headers: {
      'X-Entity-Ref-ID': 'xxx_xxxx',
    },
  });
  ```

  ```php PHP {9} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->send([
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'hello world',
    'html' => '<p>it works!</p>',
    'headers' => [
      'X-Entity-Ref-ID' => 'xxx_xxxx',
    ]
  ]);
  ```

  ```python Python {11} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Emails.SendParams = {
    "from": "onboarding@resend.dev",
    "to": ["delivered@resend.dev"],
    "subject": "hi",
    "html": "<p>it works!</p>",
    "headers": {
      "X-Entity-Ref-ID": "xxx_xxxx"
    }
  }

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

  ```rb Ruby {11} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "headers": {
      "X-Entity-Ref-ID": "123"
    },
  }

  sent = Resend::Emails.send(params)
  puts sent
  ```

  ```go Go {17} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
    ctx := context.TODO()
    client := resend.NewClient("re_xxxxxxxxx")

    params := &resend.SendEmailRequest{
        From:        "Acme <onboarding@resend.dev>",
        To:          []string{"delivered@resend.dev"},
        Subject:     "hello world",
        Html:        "<p>it works!</p>",
        Headers:     map[string]string{
          "X-Entity-Ref-ID": "xxx_xxxx",
        }
    }

    sent, err := client.Emails.SendWithContext(ctx, params)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Id)
  }
  ```

  ```rust Rust {14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::{Attachment, CreateEmailBaseOptions, Tag};
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let from = "Acme <onboarding@resend.dev>";
    let to = ["delivered@resend.dev"];
    let subject = "hello world";

    let email = CreateEmailBaseOptions::new(from, to, subject)
      .with_html("<p>it works!</p>")
      .with_header("X-Entity-Ref-ID", "xxx_xxxx");

    let _email = resend.emails.send(email).await?;

    Ok(())
  }
  ```

  ```java Java {13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateEmailOptions params = CreateEmailOptions.builder()
                  .from("Acme <onboarding@resend.dev>")
                  .to("delivered@resend.dev")
                  .subject("hello world")
                  .html("<p>it works!</p>")
                  .headers(Map.of(
                      "X-Entity-Ref-ID", "xxx_xxxx"
                  ))
                  .build();

          CreateEmailResponse data = resend.emails().send(params);
      }
  }
  ```

  ```csharp .NET {12-15} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;
  using System.Collections.Generic;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var message = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = "hello world",
      HtmlBody = "<p>it works!</p>",
      Headers = new Dictionary<string, string>()
      {
          { "X-Entity-Ref-ID", "xxx_xxxx" },
      },
  };

  var resp = await resend.EmailSendAsync( message );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL {10} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "headers": {
      "X-Entity-Ref-ID": "xxx_xxxx"
    }
  }'
  ```

  ```bash CLI {6} theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails send \
    --from "Acme <onboarding@resend.dev>" \
    --to delivered@resend.dev \
    --subject "hello world" \
    --html "<p>it works!</p>" \
    --headers "X-Entity-Ref-ID=xxx_xxxx"
  ```
</CodeGroup>


# Deliverability Insights
Source: https://resend.com/docs/dashboard/emails/deliverability-insights

Improve your deliverability with tailored insights based on your sending.

When you view your email within Resend, there is a "Insights" option. When selected, this will run deliverability best practice checks on your email and recommend possible changes to improve deliverability.

<img alt="Deliverability Insights" />

If a check passes, you'll get a nice green check. If a check fails, you'll get advice broken into two categories: Attention and Improvements.

## Attention Insights

Changes to your email that can improve deliverability.

<img alt="Attention Insights" />

#### Ensure link URLs match sending domain

Ensure that the URLs in your email match the sending domain. Mismatched URLs can trigger spam filters.

For example, if your sending domain is `@widgets.com`, ensure links within the message point back to `https://widgets.com`.

#### Include valid DMARC record

DMARC is a TXT record published in the DNS that specifies how email receivers should handle messages from your domain that don't pass SPF or DKIM validation. [A valid DMARC record](/docs/dashboard/domains/dmarc) can help improve email deliverability.

Gmail and Yahoo have required bulk senders to have a DMARC record published since 2024. When [viewing your domain](https://resend.com/domains) in Resend, you'll see a suggested DMARC record if you’re unsure what to publish.

#### Include Plain Text Version

Including a plain text version of your email ensures that your message is accessible to all recipients, including those who have email clients that do not support HTML.

If you're using Resend's API, [plain text is passed via the `text` parameter](https://resend.com/docs/api-reference/emails/send-email).

This can also generate plain text using [React Email](https://react.email/docs/utilities/render#4-convert-to-plain-text).

#### Don't use "no-reply"

Indicating that this is a one-way communication decreases trust. Some email providers use engagement (email replies) when deciding how to filter your email. A valid email address allows you to communicate with your recipients if they have questions.

#### Keep email body size small

Gmail limits the size of each email message to 102 KB. Once that limit is reached, the remaining content is clipped and hidden behind a link to view the entire message. Keep your email body size small to avoid this issue.

This check will show the current size of your email.

#### Use full YouTube URLs

Gmail's spam filters are flagging emails containing shortened YouTube links (`youtu.be`) as potential phishing attempts. Use full YouTube URLs instead (`youtube.com/watch?v=...`).

For example, instead of using `https://youtu.be/abc123`, use `https://www.youtube.com/watch?v=abc123`.

## Improvement Insights

If you're diagnosing a deliverability issue, changing your email practices may help.

<img alt="Improvement Insights" />

#### Use a Subdomain

Using a subdomain instead of the root domain helps segment your sending by purpose. This protects different types of sending from impacting the reputation of others and clearly shows the sending purpose.

#### Use Custom Subdomain for Click Tracking

You're using a shared tracking domain for click tracking. Shared tracking domains can hurt deliverability because spam filters may flag links rewritten through shared domains as suspicious. Configure a custom tracking subdomain to keep links on your own domain and improve deliverability.

Learn how to [configure a custom tracking subdomain](/docs/dashboard/domains/tracking).

#### Use Custom Subdomain for Open Tracking

You're using a shared tracking domain for open tracking. Spam filters are sensitive to tracking pixels served from shared domains, and may flag them as potential spam. Configure a custom tracking subdomain to serve tracking pixels from your own domain and improve deliverability.

Learn how to [configure a custom tracking subdomain](/docs/dashboard/domains/tracking).

<Info>
  Open rates are not always accurate. Learn more about [why open rates may not
  be accurate](/docs/knowledge-base/why-are-my-open-rates-not-accurate).
</Info>


# Email Bounces
Source: https://resend.com/docs/dashboard/emails/email-bounces

Understanding and resolving delivery issues.

## Why emails bounce

A bounce happens when an email cannot be delivered to the person it was meant for, and is returned to the sender. It essentially "bounces" back to the person who sent it.

Some reasons include invalid email addresses, full mailboxes, and technical issues with email servers. Other causes are spam filters, message size restrictions, or blacklisting of the sender's email server.

## Bounce Types and Subtypes

When an email bounces, Resend receives a message from the recipient's mail server. The bounce message explains why the delivery failed so the sender can fix the issue.

There are three types of bounces:

1. `Permanent` - also known as "hard bounce,” where the recipient's mail server rejects the email and will never be delivered.
   * `General` - The recipient's email provider sent a hard bounce message.
   * `NoEmail` - It was not possible to retrieve the recipient email address from the bounce message.

2. `Transient` - also known as "soft bounce,” where the recipient's mail server rejects the email but it may be delivered in the future.
   * `General` - The recipient's email provider sent a general bounce message. You might be able to send a message to the same recipient in the future if the issue that caused the message to bounce is resolved.
   * `MailboxFull` - The recipient's email provider sent a bounce message because the recipient's inbox was full. You might be able to send to the same recipient in the future when the mailbox is no longer full.
   * `MessageTooLarge` - The recipient's email provider sent a bounce message because message you sent was too large. You might be able to send a message to the same recipient if you reduce the size of the message.
   * `ContentRejected` - The recipient's email provider sent a bounce message because the message you sent contains content that the provider doesn't allow. You might be able to send a message to the same recipient if you change the content of the message.
   * `AttachmentRejected` - The recipient's email provider sent a bounce message because the message contained an unacceptable attachment. For example, some email providers may reject messages with attachments of a certain file type, or messages with large attachments. You might be able to send a message to the same recipient if you remove or change the content of the attachment.

<Tip>
  Sometimes, inboxes use autoresponders to signal a bounce. A `transient` status
  could mean it's related to the autoresponder, and it's not a permanent issue.
</Tip>

3. `Undetermined` - where the recipient's email server bounced, but the bounce message didn't contain enough information for Resend to determine the underlying reason.
   * `Undetermined` - The recipient's email provider sent a bounce message. The bounce message didn't contain enough information for Resend to determine the reason for the bounce.

## Viewing Bounce Details in Resend

You can see the bounce details by clicking on the email, and hovering over the `Bounced` label.

<img alt="Email Bounce Notification" />

Once you click **See Details**, the drawer will open on the right side of your screen with the bounce type, subtype, along with suggestions on how to proceed.

If the email is on the suppression list, you can click **Remove from Suppression List** to remove it.

<img alt="Email Bounce Drawer" />


# Email Suppressions
Source: https://resend.com/docs/dashboard/emails/email-suppressions

Managing your team Suppressions to protect your sending reputation.

When a mailbox provider hard-bounces a recipient, or someone marks your email as spam, continuing to send to that address harms your reputation.

Your suppressions list protects you by intentionally skipping sending to any addresses on your list.

## How addresses are suppressed

An address is added to Suppressions for one of three origins:

* `bounce`: the recipient's mail server [permanently rejected the email](/docs/dashboard/emails/email-bounces).
* `complaint`: the recipient marked your email as spam.
* `manual`: you add the recipient's address yourself.

Suppressions apply to your entire team. Any address added to the suppression list will be skipped across all your domains and subdomains when sending transactional or [Broadcast](/docs/dashboard/broadcasts/introduction) emails.

<Tip>
  Not all Inbox Service Providers return a `complained` event, most notably,
  Gmail/Google Workspace.
</Tip>

## Viewing Suppressions in Resend

You can see all Suppressions [in the Dashboard](https://resend.com/emails/suppressions) or list them [in the API](/docs/api-reference/suppressions/list-suppressions).

<img alt="Email Suppressions" />

You can also programmatically retrieve [a single Suppression](/docs/api-reference/suppressions/get-suppression) or [your entire suppression list](/docs/api-reference/suppressions/list-suppressions), which returns key data about the Suppression.

```json theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "object": "suppression",
  "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
  "email": "steve.wozniak@example.com",
  "origin": "bounce",
  "source_id": "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
  "created_at": "2026-10-06 23:47:56.678+00"
}
```

`source_id` references the email id that triggered the suppression (is `null` for `manual` origin suppressions).

## Add emails to the Suppression List

In the Dashboard, go to the [Suppressions page](https://resend.com/emails/suppressions) and click **+ Add email address** to add an email address to the suppression list.

* **Add manually**: enter the email address you want to suppress.
* **Import CSV**: upload a file with a list of email addresses to suppress.

You can also [suppress individual emails](/docs/api-reference/suppressions/add-suppression) or [bulk suppress up to 100 at a time](/docs/api-reference/suppressions/add-batch-suppressions) using the API.

<Info>
  Remember that adding a Suppression will skip all sending to that recipient
  until it is removed from your team's suppression list.
</Info>

## Remove emails from the Suppression List

Before removing an email address from the suppression list, ensure the reason for suppression has been addressed, or it will be automatically re-suppressed.

You can remove an email address from the suppression list in the Dashboard from the [Suppressions page](https://resend.com/emails/suppressions).

1. Search or filter for a suppression.
2. Click the **more options button** <Icon icon="ellipsis" /> and select **Remove email address**.

You can also [remove individual emails](/docs/api-reference/suppressions/remove-suppression) or [bulk remove up to 100 at a time](/docs/api-reference/suppressions/remove-batch-suppressions) using the API.

<Warning>
  Removing an address from the suppression list does not guarantee delivery. If
  it bounces or is marked as spam again, it will be suppressed again
  automatically and damage your sender reputation.
</Warning>

## Webhook suppression notifications

For maximum visibility, track suppressions using webhook notifications.

* [**suppression.added**](/docs/webhooks/suppressions/added): triggered when an address is added.
* [**suppression.removed**](/docs/webhooks/suppressions/removed): triggered when an address is removed.

You can, for example, use these webhook notifications to sync your suppressions with your own database or third-party service.

## Export your Suppressions

You can export your suppressions as a CSV file from the [Suppressions page](https://resend.com/emails/suppressions). Click the **Download CSV** button to export your suppressions.

<img alt="Email Suppressions" />


# Embed Inline Images
Source: https://resend.com/docs/dashboard/emails/embed-inline-images

Send emails with inline images.

You can optionally embed an image in the HTML body of the email. This allows you to include images without needing to host them in an external server.

<Info>
  We currently do not support sending attachments (including inline images)
  [when using our batch endpoint](/docs/api-reference/emails/send-batch-emails).
</Info>

<Steps>
  <Step title="Add the CID in the email HTML.">
    Use the prefix `cid:` to reference the ID in the `src` attribute of an image tag in the HTML body of the email.

    ```html theme={"theme":{"light":"github-light","dark":"vesper"}}
      <img src="cid:logo-image">
    ```
  </Step>

  <Step title="Reference the CID in the attachment.">
    Include the content id parameter in the attachment object (see below for example implementations). The ID is an arbitrary string set by you, and must be less than 128 characters.
  </Step>
</Steps>

## Implementation details

Both remote and local attachments are supported. All attachment [requirements, options, and limitations](/docs/dashboard/emails/attachments) apply to inline images as well.

As with all our features, inline images are available across all our SDKs.

### Remote image example

<CodeGroup>
  ```ts Node.js {9, 14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Thank you for contacting us',
    html: '<p>Here is our <img src="cid:logo-image"/> inline logo</p>',
    attachments: [
      {
        path: 'https://resend.com/static/sample/logo.png',
        filename: 'logo.png',
        contentId: 'logo-image',
      },
    ],
  });
  ```

  ```php PHP {7,12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->send([
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'Thank you for contacting us',
    'html' => '<p>Here is our <img src="cid:logo-image"/> inline logo</p>',
    'attachments' => [
      [
        'path' => 'https://resend.com/static/sample/logo.png',
        'filename' => 'logo.png',
        'content_id' => 'logo-image',
      ]
    ]
  ]);
  ```

  ```python Python {8,15} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  attachment: resend.RemoteAttachment = {
    "path": "https://resend.com/static/sample/logo.png",
    "filename": "logo.png",
    "content_id": "logo-image",
  }

  params: resend.Emails.SendParams = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Thank you for contacting us",
    "html": "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
    "attachments": [attachment],
  }

  resend.Emails.send(params)
  ```

  ```rb Ruby {9, 14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Thank you for contacting us",
    "html": "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
    "attachments": [
      {
        "path": "https://resend.com/static/sample/logo.png",
        "filename": 'logo.png',
        "content_id": "logo-image",
      }
    ]
  }

  Resend::Emails.send(params)
  ```

  ```go Go {14, 21} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
    ctx := context.TODO()
    client := resend.NewClient("re_xxxxxxxxx")

    attachment := &resend.Attachment{
      Path:  "https://resend.com/static/sample/logo.png",
      Filename: "logo.png",
      ContentId: "logo-image",
    }

    params := &resend.SendEmailRequest{
        From:        "Acme <onboarding@resend.dev>",
        To:          []string{"delivered@resend.dev"},
        Subject:     "Thank you for contacting us",
        Html:        "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
        Attachments: []*resend.Attachment{attachment},
    }

    sent, err := client.Emails.SendWithContext(ctx, params)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Id)
  }
  ```

  ```rust Rust {14, 17} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::{CreateAttachment, CreateEmailBaseOptions};
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let from = "Acme <onboarding@resend.dev>";
    let to = ["delivered@resend.dev"];
    let subject = "Thank you for contacting us";

    let path = "https://resend.com/static/sample/logo.png";
    let filename = "logo.png";
    let content_id = "logo-image";

    let email = CreateEmailBaseOptions::new(from, to, subject)
      .with_html("<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>")
      .with_attachment(
        CreateAttachment::from_path(path)
          .with_filename(filename)
          .with_content_id(content_id),
      );

    let _email = resend.emails.send(email).await?;

    Ok(())
  }
  ```

  ```java Java {10, 17} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          Attachment att = Attachment.builder()
                  .path("https://resend.com/static/sample/logo.png")
                  .fileName("logo.png")
                  .ContentId("logo-image")
                  .build();

          CreateEmailOptions params = CreateEmailOptions.builder()
                  .from("Acme <onboarding@resend.dev>")
                  .to("delivered@resend.dev")
                  .subject("Thank you for contacting us")
                  .html("<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>")
                  .attachments(att)
                  .build();

          CreateEmailResponse data = resend.emails().send(params);
      }
  }
  ```

  ```csharp .NET {11, 18} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;
  using System.Collections.Generic;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var message = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = "Thank you for contacting us",
      HtmlBody = "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
  };

  message.Attachments = new List<EmailAttachment>();
  message.Attachments.Add( new EmailAttachment() {
    Filename = "logo.png",
    Path = "https://resend.com/static/sample/logo.png",
    ContentId = "logo-image",
  } );

  var resp = await resend.EmailSendAsync( message );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL {8,13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Thank you for contacting us",
    "html": "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
    "attachments": [
      {
        "path": "https://resend.com/static/sample/logo.png",
        "filename": "logo.png",
        "content_id": "logo-image"
      }
    ]
  }'
  ```
</CodeGroup>

### Local image example

<CodeGroup>
  ```ts Node.js {13, 18} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import fs from 'fs';

  const resend = new Resend('re_xxxxxxxxx');

  const filepath = `${__dirname}/static/logo.png`;
  const attachment = fs.readFileSync(filepath).toString('base64');

  await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Thank you for contacting us',
    html: '<p>Here is our <img src="cid:logo-image"/> inline logo</p>',
    attachments: [
      {
        content: attachment,
        filename: 'logo.png',
        contentId: 'logo-image',
      },
    ],
  });
  ```

  ```php PHP {7, 12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->send([
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'Thank you for contacting us',
    'html' => '<p>Here is our <img src="cid:logo-image"/> inline logo</p>',
    'attachments' => [
      [
        'filename' => 'logo.png',
        'content' => $invoiceBuffer,
        'content_id' => 'logo-image',
      ]
    ]
  ]);
  ```

  ```python Python {10, 16} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import os
  import resend

  resend.api_key = "re_xxxxxxxxx"

  f: bytes = open(
    os.path.join(os.path.dirname(__file__), "../static/logo.png"), "rb"
  ).read()

  attachment: resend.Attachment = {"content": list(f), "filename": "logo.png", "content_id": "logo-image"}

  params: resend.Emails.SendParams = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Thank you for contacting us",
    "html": "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
    "attachments": [attachment],
  }

  resend.Emails.send(params)
  ```

  ```rb Ruby {11,16} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  file = IO.read("logo.png")

  params = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Thank you for contacting us",
    "html": "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
    "attachments": [
      {
        "content": file.bytes,
        "filename": 'logo.png',
        "content_id": "logo-image",
      }
    ]
  }

  Resend::Emails.send(params)
  ```

  ```go Go {21, 28} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"fmt"
  	"os"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
    ctx := context.TODO()
    client := resend.NewClient("re_xxxxxxxxx")

    pwd, _ := os.Getwd()
    f, err := os.ReadFile(pwd + "/static/logo.png")
    if err != nil {
      panic(err)
    }

    attachment := &resend.Attachment{
      Content:  f,
      Filename: "logo.png",
      ContentId: "logo-image",
    }

    params := &resend.SendEmailRequest{
        From:        "Acme <onboarding@resend.dev>",
        To:          []string{"delivered@resend.dev"},
        Subject:     "Thank you for contacting us",
        Html:        "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
        Attachments: []*resend.Attachment{attachment},
    }

    sent, err := client.Emails.SendWithContext(ctx, params)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Id)
  }
  ```

  ```rust Rust {16,22} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use std::fs::File;
  use std::io::Read;

  use resend_rs::types::{CreateAttachment, CreateEmailBaseOptions};
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let from = "Acme <onboarding@resend.dev>";
    let to = ["delivered@resend.dev"];
    let subject = "Thank you for contacting us";

    let filename = "logo.png";
    let content_id = "logo-image";
    let mut f = File::open(filename).unwrap();
    let mut invoice = Vec::new();
    f.read_to_end(&mut invoice).unwrap();

    let email = CreateEmailBaseOptions::new(from, to, subject)
      .with_html("<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>")
      .with_attachment(
        CreateAttachment::from_content(invoice)
          .with_filename(filename)
          .with_content_id(content_id),
      );

    let _email = resend.emails.send(email).await?;

    Ok(())
  }
  ```

  ```java Java {10, 17} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          Attachment att = Attachment.builder()
                  .fileName("logo.png")
                  .content("invoiceBuffer")
                  .contentId("logo-image")
                  .build();

          CreateEmailOptions params = CreateEmailOptions.builder()
                  .from("Acme <onboarding@resend.dev>")
                  .to("delivered@resend.dev")
                  .subject("Thank you for contacting us")
                  .html("<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>")
                  .attachments(att)
                  .build();

          CreateEmailOptions params = CreateEmailOptions.builder()
      }
  }
  ```

  ```csharp .NET {12, 19} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;
  using System.Collections.Generic;
  using System.IO;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var message = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = "Thank you for contacting us",
      HtmlBody = "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
  };

  message.Attachments = new List<EmailAttachment>();
  message.Attachments.Add( new EmailAttachment() {
    Filename = "logo.png",
    Content = await File.ReadAllBytesAsync( "logo.png" ),
    ContentId = "logo-image",
  } );

  var resp = await resend.EmailSendAsync( message );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL {8, 13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Thank you for contacting us",
    "html": "<p>Here is our <img src=\"cid:logo-image\"/> inline logo</p>",
    "attachments": [
      {
        "content": "UmVzZW5kIGF0dGFjaG1lbnQgZXhhbXBsZS4gTmljZSBqb2Igc2VuZGluZyB0aGUgZW1haWwh%",
        "filename": "invoice.txt",
        "content_id": "logo-image"
      }
    ]
  }'
  ```
</CodeGroup>

## Other considerations

Before adding inline images, consider the following.

* As these images are sent as attachments, you need to encode your image as Base64 when sending the raw content via the API. There is no need to do this when passing the path of a remote image (the API handles this for you).
* Inline images increase the size of the email.
* Inline images may be rejected by some clients (especially webmail).
* As with all attachments, add a `content_type` (e.g. `image/png`) or `filename` (e.g. `logo.png`) parameter to the attachment object. This helps email clients render the attachment correctly.

<Note>
  All attachments (including inline images) do not currently display in the
  [emails dashboard](https://resend.com/emails) when previewing email HTML.
</Note>


# Idempotency Keys
Source: https://resend.com/docs/dashboard/emails/idempotency-keys

Use idempotency keys to ensure that emails are sent only once.

Include an idempotency key in any email requests to ensure that the same email request is processed only once, even if it's sent multiple times.

<Info>
  Idempotency keys are currently supported on the `POST /emails` and the `POST
      /emails/batch` endpoints on the Resend API.
</Info>

## How it works

When you send an email with an idempotency key, Resend checks whether an email with the same idempotency key has already been sent in the last 24 hours. This is an optional feature that simplifies managing retries on your side.

This makes it safe to retry requests that send an email. You don't have to worry about checking if the original request was sent. Instead, you can make the same request and our API will give the same response, without actually sending the email again.

## How to use idempotency keys

Idempotency keys can be up to 256 characters and must be unique per API request.

We recommend that you use a UUID or other string that uniquely identifies that specific email.

<Tip>If you have multiple events that trigger emails related to a single entity in your system, you can format your idempotency keys to take advantage of that entity's ID. One idea is to format idempotency keys like `<event-type>/<entity-id>`, for example `welcome-user/123456789`. The specific format you use is up to you.</Tip>

Send the key in the `Idempotency-Key` HTTP header in your API requests. Our SDKs also provide a convenient way to set this header. If you're using SMTP, you can set the `Resend-Idempotency-Key` email header instead.

Idempotency keys are kept in the system for **24 hours**. This gives you an ample window to retry any failed processes on your end without having to keep track of the sent status.

### `POST /emails` endpoint example

<CodeGroup>
  ```ts Node.js {9} theme={"theme":{"light":"github-light","dark":"vesper"}}
  await resend.emails.send(
    {
      from: 'Acme <onboarding@resend.dev>',
      to: ['delivered@resend.dev'],
      subject: 'hello world',
      html: '<p>it works!</p>',
    },
    {
      idempotencyKey: 'welcome-user/123456789',
    },
  );
  ```

  ```php PHP {9} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->send([
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'hello world',
    'html' => '<p>it works!</p>',
  ], [
    'idempotency_key' => 'welcome-user/123456789',
  ]);
  ```

  ```python Python {9} theme={"theme":{"light":"github-light","dark":"vesper"}}
  params: resend.Emails.SendParams = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>"
  }

  options: resend.Emails.SendOptions = {
    "idempotency_key": "welcome-user/123456789",
  }

  resend.Emails.send(params, options)
  ```

  ```rb Ruby {9} theme={"theme":{"light":"github-light","dark":"vesper"}}
  params = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>"
  }
  Resend::Emails.send(
    params,
    options: { idempotency_key: "welcome-user/123456789" }
  )
  ```

  ```go Go {13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.SendEmailRequest{
  		From:    "onboarding@resend.dev",
  		To:      []string{"delivered@resend.dev"},
  		Subject: "hello world",
  		Html:    "<p>it works!</p>",
  	}
  	options := &resend.SendEmailOptions{
  		IdempotencyKey: "welcome-user/123456789",
  	}
  	_, err := client.Emails.SendWithOptions(ctx, params, options)
  	if err != nil {
  		panic(err)
  	}
  }
  ```

  ```rust Rust {14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::CreateEmailBaseOptions;
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let from = "Acme <onboarding@resend.dev>";
    let to = ["delivered@resend.dev"];
    let subject = "Hello World";

    let email = CreateEmailBaseOptions::new(from, to, subject)
      .with_html("<p>it works!</p>")
      .with_idempotency_key("welcome-user/123456789");

    let _email = resend.emails.send(email).await?;

    Ok(())
  }
  ```

  ```java Java {9} theme={"theme":{"light":"github-light","dark":"vesper"}}
  CreateEmailOptions params = CreateEmailOptions.builder()
    .from("Acme <onboarding@resend.dev>")
    .to("delivered@resend.dev")
    .subject("hello world")
    .html("<p>it works!</p>")
    .build();

  RequestOptions options = RequestOptions.builder()
    .setIdempotencyKey("welcome-user/123456789").build();

  CreateEmailResponse data = resend.emails().send(params, options);
  ```

  ```csharp C# {11} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var key = IdempotencyKey.New<int>( "welcome-user", 123456789 );
  var resp = await resend.EmailSendAsync(key, new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = "hello world",
      HtmlBody = "<p>it works!</p>",
  } );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL {4} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -H 'Idempotency-Key: welcome-user/123456789' \
       -d $'{
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>"
  }'
  ```

  ```bash CLI {6} theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails send \
    --from "Acme <onboarding@resend.dev>" \
    --to delivered@resend.dev \
    --subject "hello world" \
    --html "<p>it works!</p>" \
    --idempotency-key "welcome-user/123456789"
  ```

  ```yaml SMTP {4} theme={"theme":{"light":"github-light","dark":"vesper"}}
  From: Acme <onboarding@resend.dev>
  To: delivered@resend.dev
  Subject: hello world
  Resend-Idempotency-Key: welcome-user/123456789

  <p>it works!</p>
  ```
</CodeGroup>

### `POST /emails/batch` endpoint example

<Tip>
  Format your idempotency keys to take advantage of that entity's ID (i.e.,
  `<event-type>/<entity-id>`). For batch sends, choose a key that represents the whole batch, like a team, workspace, or project (i.e., `team-quota/123456789`).
</Tip>

<CodeGroup>
  ```ts Node.js {21} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  await resend.batch.send(
    [
      {
        from: 'Acme <onboarding@resend.dev>',
        to: ['foo@gmail.com'],
        subject: 'hello world',
        html: '<h1>it works!</h1>',
      },
      {
        from: 'Acme <onboarding@resend.dev>',
        to: ['bar@outlook.com'],
        subject: 'world hello',
        html: '<p>it works!</p>',
      },
    ],
    {
      idempotencyKey: 'team-quota/123456789',
    },
  );
  ```

  ```php PHP {19} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->batch->send(
    [
      [
        'from' => 'Acme <onboarding@resend.dev>',
        'to' => ['foo@gmail.com'],
        'subject' => 'hello world',
        'html' => '<h1>it works!</h1>',
      ],
      [
        'from' => 'Acme <onboarding@resend.dev>',
        'to' => ['bar@outlook.com'],
        'subject' => 'world hello',
        'html' => '<p>it works!</p>',
      ]
    ],
    [
      'idempotency_key' => 'team-quota/123456789',
    ]
  );
  ```

  ```py Python {22} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend
  from typing import List

  resend.api_key = "re_xxxxxxxxx"

  params: List[resend.Emails.SendParams] = [
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["foo@gmail.com"],
      "subject": "hello world",
      "html": "<h1>it works!</h1>",
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["bar@outlook.com"],
      "subject": "world hello",
      "html": "<p>it works!</p>",
    }
  ]

  options: resend.Batch.SendOptions = {
    "idempotency_key": "team-quota/123456789",
  }

  resend.Batch.send(params, options)
  ```

  ```rb Ruby {22} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = 're_xxxxxxxxx'

  params = [
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["foo@gmail.com"],
      "subject": "hello world",
      "html": "<h1>it works!</h1>",
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["bar@outlook.com"],
      "subject": "world hello",
      "html": "<p>it works!</p>",
    }
  ]

  Resend::Batch.send(
    params,
    options: { idempotency_key: "team-quota/123456789" }
  )
  ```

  ```go Go {32} theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"fmt"
  	"os"

  	"github.com/resend/resend-go/v3"
  )

  func main() {

    ctx := context.TODO()

    client := resend.NewClient("re_xxxxxxxxx")

    var batchEmails = []*resend.SendEmailRequest{
      {
        From:    "Acme <onboarding@resend.dev>",
        To:      []string{"foo@gmail.com"},
        Subject: "hello world",
        Html:    "<h1>it works!</h1>",
      },
      {
        From:    "Acme <onboarding@resend.dev>",
        To:      []string{"bar@outlook.com"},
        Subject: "world hello",
        Html:    "<p>it works!</p>",
      },
    }

    options := &resend.BatchSendEmailOptions{
      IdempotencyKey: "team-quota/123456789",
    }

    sent, err := client.Batch.SendWithOptions(ctx, batchEmails, options)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Data)
  }
  ```

  ```rust Rust {23} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::CreateEmailBaseOptions;
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let emails = vec![
      CreateEmailBaseOptions::new(
        "Acme <onboarding@resend.dev>",
        vec!["foo@gmail.com"],
        "hello world",
      )
      .with_html("<h1>it works!</h1>"),
      CreateEmailBaseOptions::new(
        "Acme <onboarding@resend.dev>",
        vec!["bar@outlook.com"],
        "world hello",
      )
      .with_html("<p>it works!</p>"),
    ];

    let _emails = resend.batch.send_with_idempotency_key(emails, "team-quota/123456789").await?;

    Ok(())
  }
  ```

  ```java Java {23} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateEmailOptions firstEmail = CreateEmailOptions.builder()
              .from("Acme <onboarding@resend.dev>")
              .to("foo@gmail.com")
              .subject("hello world")
              .html("<h1>it works!</h1>")
              .build();

          CreateEmailOptions secondEmail = CreateEmailOptions.builder()
              .from("Acme <onboarding@resend.dev>")
              .to("bar@outlook.com")
              .subject("world hello")
              .html("<p>it works!</p>")
              .build();

          CreateBatchEmailsResponse data = resend.batch().send(
              Arrays.asList(firstEmail, secondEmail),
              Map.of("idempotency_key", "team-quota/123456789")
          );
      }
  }
  ```

  ```csharp .NET {5} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var key = IdempotencyKey.New<int>( "team-quota", 123456789 );

  var mail1 = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "foo@gmail.com",
      Subject = "hello world",
      HtmlBody = "<p>it works!</p>",
  };

  var mail2 = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "bar@outlook.com",
      Subject = "hello world",
      HtmlBody = "<p>it works!</p>",
  };

  var resp = await resend.EmailBatchAsync(key, [ mail1, mail2 ] );
  Console.WriteLine( "Nr Emails={0}", resp.Content.Count );
  ```

  ```bash cURL {4} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails/batch' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -H 'Idempotency-Key: team-quota/123456789' \
       -d $'[
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["foo@gmail.com"],
      "subject": "hello world",
      "html": "<h1>it works!</h1>"
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["bar@outlook.com"],
      "subject": "world hello",
      "html": "<p>it works!</p>"
    }
  ]'
  ```
</CodeGroup>

## Possible responses

After checking if an email with the same idempotency key has already been sent, Resend returns one of the following responses:

* **Successful responses** will return the email ID of the sent email.
* **Error responses** will return one of the following errors:
  * `400`: `invalid_idempotency_key` - the idempotency key has to be between 1–256 characters. You can retry with a valid key or without supplying an idempotency key.
  * `409`: `invalid_idempotent_request` - this idempotency key has already been used on a request that had a different payload. Retrying this request is useless without changing the idempotency key or payload.
  * `409`: `concurrent_idempotent_requests` - another request with the same idempotency key is in progress. As it isn't finished yet, Resend can't return its original response, but it is safe to retry this request later if needed.


# Sending Emails
Source: https://resend.com/docs/dashboard/emails/introduction

An introduction to sending emails with Resend.

## Sending transactional emails

Resend provides all the tools you need to send [transactional emails](/docs/email-types#send-transactional-emails) from your application. These are useful for:

* order confirmations
* password reset emails
* account notifications

<Tip>
  To send bulk marketing emails, use the
  [Broadcasts](/docs/dashboard/broadcasts/introduction) feature.
</Tip>

Once you [verify a domain](/docs/add-a-domain) in your Resend account, you can send from any email address at that domain. You do not need to “create an email address,” “set up a sender identity,” or “add a from-address” before sending.

## Sending Features

With Resend's email sending features, you can:

* Send, retrieve, cancel, and manage individual and transactional email delivery through the [Sending API](/docs/api-reference/emails/send-email) and [SDKs](/docs/sdks), [CLI commands](/docs/cli#emails), [automations](/docs/dashboard/automations/introduction), and [AI building tools](/docs/ai-onboarding).
* [View and manage all sent emails](/docs/dashboard/emails/manage-emails) in the Emails Dashboard page.
* Send single or [batch transactional emails](/docs/dashboard/emails/batch-sending).
* [Schedule emails](/docs/dashboard/emails/schedule-email) to be sent at a future date.
* Send emails [with attachments](/docs/dashboard/emails/attachments) and [embedded images](/docs/dashboard/emails/embed-inline-images).
* Include [custom headers](/docs/dashboard/emails/custom-headers) in your emails.
* Use [idempotency keys](/docs/dashboard/emails/idempotency-keys) to ensure emails are sent only once.
* Receive tailored [deliverability insights](/docs/dashboard/emails/deliverability-insights) about each email with suggestions for improvement.
* [View API endpoint logs](/docs/dashboard/logs/introduction) and deliverability metrics for monitoring and troubleshooting.

## Quickstart

Get started with a [quick setup sending example](/docs/introduction#quickstart) for your language or an [AI builder guide](/docs/ai-onboarding#ai-builder-guides) to see how to incorporate Resend into your application.

## Choose your infrastructure

To send transactional emails from your application, you can use a variety of tools:

* [SDK](/docs/sdks): send with an SDK built for your language
* [Integrations](/docs/integrations): send from a framework or tool you already use
* [API](/docs/api-reference/emails/send-email): send with raw cURL calls
* [CLI](/docs/cli#emails): send emails from the terminal
* [MCP](/docs/mcp-server): send through your agent with MCP (see also [skills](/docs/react-email-skill))
* [SMTP](/docs/send-with-smtp): send without external dependencies

You can also send emails as part of [automated workflows](/docs/dashboard/automations/introduction) such as abandoned cart reminders, and create [email templates](/docs/dashboard/templates/introduction) for repeatable content.

See how to use additional sending features, including scheduling and attachments, in the [sending email guides](#related-guides).

## Manage your sent emails

After you've sent or scheduled your first email, you'll be able to view and manage your emails in the [Emails Dashboard page](https://resend.com/emails). From here, you can view email details, share a public version, and more. This allows all members of your team to view and manage your sent emails.

You can also manage your emails programmatically using the [Sending API](/docs/api-reference/emails/send-email), [CLI commands](/docs/cli#emails), or the [MCP server](/docs/mcp-server).

Learn more about [managing your sent emails](/docs/dashboard/emails/manage-emails) in the dedicated guide.

## Related Guides

See how to use Resend's sending features.

<CardGroup>
  <Card title="View and manage sent emails" icon="envelope" href="/dashboard/emails/manage-emails" />

  <Card title="Send test emails" icon="flask-gear" href="/dashboard/emails/send-test-emails" />

  <Card title="Include attachments" icon="file-plus" href="/dashboard/emails/attachments" />

  <Card title="Embed inline images" icon="image" href="/dashboard/emails/embed-inline-images" />

  <Card title="Schedule emails" icon="clock" href="/dashboard/emails/schedule-email" />

  <Card title="Batch sending" icon="envelopes" href="/dashboard/emails/batch-sending" />

  <Card title="Customize headers" icon="rectangle-history-circle-user" href="/dashboard/emails/custom-headers" />

  <Card title="Prevent duplicate emails" icon="key" href="/dashboard/emails/idempotency-keys" />

  <Card title="Add an unsubscribe link" icon="person-from-portal" href="/dashboard/emails/add-unsubscribe-to-transactional-emails" />

  <Card title="Add identifier tags" icon="tags" href="/dashboard/emails/tags" />
</CardGroup>


# View and manage emails
Source: https://resend.com/docs/dashboard/emails/manage-emails

An introduction to managing your sent emails with Resend.

## Manage your sent emails

After you've sent or scheduled your first email, your emails appear in the [**Emails** Dashboard page](https://resend.com/emails). You can [view email details](#view-email-details), [share a public version](#share-email-link), [view email logs](#see-associated-logs), and more.

You can also manage your scheduled and sent emails using Resend's code tools including the [MCP server](/docs/mcp-server), [API endpoints](/docs/api-reference/emails/send-email) and [CLI commands](/docs/cli#emails) for tasks such as listing, sending, updating, and canceling emails.

## View email details

See all the metadata associated with a sent or scheduled email, including the sender address, recipient address, subject, and more from the [**Emails** Dashboard page](https://resend.com/emails). Select any email to view its details.

<img alt="Email Details" />

Each email contains a **Preview**, **Plain Text**, and **HTML** version to visualize the content of your sent email in its various formats.

## Understand email events

Here are all the events that can be associated with an email:

* `bounced` - The recipient's mail server rejected the email. ([Learn more about bounced emails](/docs/dashboard/emails/email-bounces))
* `canceled` - The scheduled email was canceled (by user).
* `clicked` - The recipient clicked on a link in the email.
* `complained` - The email was successfully delivered to the recipient's mail server, but the recipient marked it as spam.
* `delivered` - Resend successfully delivered the email to the recipient's mail server.
* `delivery_delayed` - The email couldn't be delivered to the recipient's mail server because a temporary issue occurred. Delivery delays can occur, for example, when the recipient's inbox is full, or when the receiving email server experiences a transient issue.
* `failed` - The email failed to be sent.
* `opened` - The recipient opened the email. ([Open rates are not always accurate](/docs/knowledge-base/why-are-my-open-rates-not-accurate))
* `queued` - The email created from Broadcasts or Batches is queued for delivery.
* `scheduled` - The email is scheduled for delivery.
* `sent` - The email was sent successfully.
* `suppressed` - The email was not sent because the recipient is on the suppression list. ([Learn more about the suppression list](/docs/knowledge-base/why-are-my-emails-landing-on-the-suppression-list))

## Share email link

You can share a public link of a sent email, which is valid for 48 hours. Anyone with the link can view the email.

To share a link, click on the **dropdown menu** <Icon icon="ellipsis" />, and select **Share email**.

<img alt="Email - Share Link Option" />

Copy the URL and share it with your team members.

<img alt="Email - Share Link Modal" />

Anyone with the link can view the email without authenticating for 48 hours.

<img alt="Email - Share Link Item" />

## See associated logs

Check all the logs associated with an email to help you troubleshoot any issues with the request itself.

To view the logs, click on the dropdown menu, and select "View log".

<img alt="Email - View Logs Option" />

This will take you to logs, where you can see all the logs associated with the email.

<img alt="Email - View Logs Item" />

## Export your data

Admins can download your data in CSV format for the following resources:

* Emails
* Broadcasts
* Contacts
* Segments
* Domains
* Logs
* API keys

<Info>Currently, exports are limited to admin users of your team.</Info>

To start, apply filters to your data and click on the "Export" button. Confirm your filters before exporting your data.

<video />

If your exported data includes 1,000 items or less, the export will download immediately. For larger exports, you'll receive an email with a link to download your data.

All admins on your team can securely access the export for 7 days. Unavailable exports are marked as "Expired."

<Note>
  All exports your team creates are listed in the
  [Exports](https://resend.com/exports) page under **Settings** > **Team** >
  **Exports**. Select any export to view its details page. All members of your
  team can view your exports, but only admins can download the data.
</Note>

## API Reference

For complete API documentation, see the [Sending API reference](/docs/api-reference/emails/send-email).


# Schedule Email
Source: https://resend.com/docs/dashboard/emails/schedule-email

Send emails at a specific time without additional complexity.

While some emails need to be delivered as soon as possible, like password resets or magic links, others can be scheduled for a specific time.

Here are some examples of when you might want to schedule an email:

* Send welcome email **5 minutes after** signup
* Trigger a reminder email **24 hours before** an event
* Schedule a weekly digest email for the **next day at 9am PST**

Before, you had to use external services to handle the scheduling logic, but now you can use the new Resend API to schedule emails.

<Info>Emails can be scheduled up to 30 days in advance.</Info>

There are two ways to schedule an email:

1. [Using natural language](#schedule-using-natural-language)
2. [Using date format](#schedule-using-date-format)

## Schedule using natural language

You can use the various Resend SDKs to schedule emails.

The date can be defined using natural language, such as `"in 1 hour"`, `"tomorrow at 9am"`, or `"Friday at 3pm ET"`.

<CodeGroup>
  ```ts Node.js {10} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'hello world',
    html: '<p>it works!</p>',
    scheduledAt: 'in 1 min',
  });
  ```

  ```php PHP {8} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->send([
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'hello world',
    'html' => '<p>it works!</p>',
    'scheduled_at' => 'in 1 min'
  ]);
  ```

  ```python Python {10} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Emails.SendParams = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "scheduled_at": "in 1 min"
  }

  resend.Emails.send(params)
  ```

  ```rb Ruby {10} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "scheduled_at": "in 1 min"
  }

  Resend::Emails.send(params)
  ```

  ```go Go {17} theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.SendEmailRequest{
  		From:        "Acme <onboarding@resend.dev>",
  		To:          []string{"delivered@resend.dev"},
  		Subject:     "hello world",
  		Html:        "<p>it works!</p>",
  		ScheduledAt: "in 1 min",
  	}

  	sent, err := client.Emails.SendWithContext(ctx, params)

  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(sent.Id)
  }
  ```

  ```rust Rust {14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::CreateEmailBaseOptions;
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let from = "Acme <onboarding@resend.dev>";
    let to = ["delivered@resend.dev"];
    let subject = "hello world";

    let email = CreateEmailBaseOptions::new(from, to, subject)
      .with_html("<p>it works!</p>")
      .with_scheduled_at("in 1 min");

    let _email = resend.emails.send(email).await?;

    Ok(())
  }
  ```

  ```java Java {12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateEmailOptions params = CreateEmailOptions.builder()
                  .from("Acme <onboarding@resend.dev>")
                  .to("delivered@resend.dev")
                  .subject("hello world")
                  .html("<p>it works!</p>")
                  .scheduledAt("in 1 min")
                  .build();

          CreateEmailResponse data = resend.emails().send(params);
      }
  }
  ```

  ```csharp .NET {11} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.EmailSendAsync( new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = "hello world",
      HtmlBody = "<p>it works!</p>",
      MomentSchedule = "in 1 min",
  } );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL {9} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "scheduled_at": "in 1 min"
  }'
  ```

  ```bash CLI {6} theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails send \
    --from "Acme <onboarding@resend.dev>" \
    --to delivered@resend.dev \
    --subject "hello world" \
    --html "<p>it works!</p>" \
    --scheduled-at "in 1 min"
  ```
</CodeGroup>

## Schedule using date format

You can also use a date in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format (e.g: `2026-08-05T11:52:01.858Z`).

<CodeGroup>
  ```ts Node.js {5} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const oneMinuteFromNow = new Date(Date.now() + 1000 * 60).toISOString();

  await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'hello world',
    html: '<p>it works!</p>',
    scheduledAt: oneMinuteFromNow,
  });
  ```

  ```php PHP {3} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $oneMinuteFromNow = (new DateTime())->modify('+1 minute')->format(DateTime::ISO8601);

  $resend->emails->send([
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'hello world',
    'html' => '<p>it works!</p>',
    'scheduled_at' => $oneMinuteFromNow
  ]);
  ```

  ```python Python {6} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend
  from datetime import datetime, timedelta

  resend.api_key = "re_xxxxxxxxx"

  one_minute_from_now = (datetime.now() + timedelta(minutes=1)).isoformat()

  params: resend.Emails.SendParams = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "scheduled_at": one_minute_from_now
  }

  resend.Emails.send(params)
  ```

  ```rb Ruby {5} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  one_minute_from_now = (Time.now + 1 * 60).strftime("%Y-%m-%dT%H:%M:%S.%L%z")

  params = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "scheduled_at": one_minute_from_now
  }

  Resend::Emails.send(params)
  ```

  ```go Go {13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"
  	"time"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	ctx := context.TODO()
  	client := resend.NewClient("re_xxxxxxxxx")

  	oneMinuteFromNow := time.Now().Add(time.Minute * time.Duration(1))
  	oneMinuteFromNowISO := oneMinuteFromNow.Format("2006-01-02T15:04:05-0700")

  	params := &resend.SendEmailRequest{
  		From:        "Acme <onboarding@resend.dev>",
  		To:          []string{"delivered@resend.dev"},
  		Subject:     "hello world",
  		Html:        "<p>it works!</p>",
  		ScheduledAt: oneMinuteFromNowISO,
  	}

  	sent, err := client.Emails.SendWithContext(ctx, params)

  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(sent.Id)
  }
  ```

  ```rust Rust {12-15} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use chrono::{Local, TimeDelta};
  use resend_rs::types::CreateEmailBaseOptions;
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let from = "Acme <onboarding@resend.dev>";
    let to = ["delivered@resend.dev"];
    let subject = "hello world";
    let one_minute_from_now = Local::now()
      .checked_add_signed(TimeDelta::minutes(1))
      .unwrap()
      .to_rfc3339();

    let email = CreateEmailBaseOptions::new(from, to, subject)
      .with_html("<p>it works!</p>")
      .with_scheduled_at(&one_minute_from_now);

    let _email = resend.emails.send(email).await?;

    Ok(())
  }
  ```

  ```java Java {7-10} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          String oneMinuteFromNow = Instant
            .now()
            .plus(1, ChronoUnit.MINUTES)
            .toString();

          CreateEmailOptions params = CreateEmailOptions.builder()
                  .from("Acme <onboarding@resend.dev>")
                  .to("delivered@resend.dev")
                  .subject("hello world")
                  .html("<p>it works!</p>")
                  .scheduledAt(oneMinuteFromNow)
                  .build();

          CreateEmailResponse data = resend.emails().send(params);
      }
  }
  ```

  ```csharp .NET {11} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.EmailSendAsync( new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = "hello world",
      HtmlBody = "<p>it works!</p>",
      MomentSchedule = DateTime.UtcNow.AddMinutes( 1 ),
  } );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL {9} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "scheduled_at": "2026-08-20T11:52:01.858Z"
  }'
  ```

  ```bash CLI {6} theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails send \
    --from "Acme <onboarding@resend.dev>" \
    --to delivered@resend.dev \
    --subject "hello world" \
    --html "<p>it works!</p>" \
    --scheduled-at "2026-08-20T11:52:01.858Z"
  ```
</CodeGroup>

## Schedule emails on the `POST /emails/batch` endpoint

Each email in a batch request can be scheduled independently using natural language or ISO 8601 date format.

<CodeGroup>
  ```ts Node.js {11,18} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.batch.send([
    {
      from: 'Acme <onboarding@resend.dev>',
      to: ['foo@gmail.com'],
      subject: 'hello world',
      html: '<h1>it works!</h1>',
      scheduledAt: 'in 1 min',
    },
    {
      from: 'Acme <onboarding@resend.dev>',
      to: ['bar@outlook.com'],
      subject: 'world hello',
      html: '<p>it works!</p>',
      scheduledAt: 'in 5 min',
    },
  ]);
  ```

  ```php PHP {9,16} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->batch->send([
    [
      'from' => 'Acme <onboarding@resend.dev>',
      'to' => ['foo@gmail.com'],
      'subject' => 'hello world',
      'html' => '<h1>it works!</h1>',
      'scheduled_at' => 'in 1 min'
    ],
    [
      'from' => 'Acme <onboarding@resend.dev>',
      'to' => ['bar@outlook.com'],
      'subject' => 'world hello',
      'html' => '<p>it works!</p>',
      'scheduled_at' => 'in 5 min'
    ]
  ]);
  ```

  ```py Python {12,19} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend
  from typing import List

  resend.api_key = "re_xxxxxxxxx"

  params: List[resend.Emails.SendParams] = [
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["foo@gmail.com"],
      "subject": "hello world",
      "html": "<h1>it works!</h1>",
      "scheduled_at": "in 1 min"
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["bar@outlook.com"],
      "subject": "world hello",
      "html": "<p>it works!</p>",
      "scheduled_at": "in 5 min"
    }
  ]

  resend.Batch.send(params)
  ```

  ```rb Ruby {11,18} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = 're_xxxxxxxxx'

  params = [
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["foo@gmail.com"],
      "subject": "hello world",
      "html": "<h1>it works!</h1>",
      "scheduled_at": "in 1 min"
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["bar@outlook.com"],
      "subject": "world hello",
      "html": "<p>it works!</p>",
      "scheduled_at": "in 5 min"
    }
  ]

  Resend::Batch.send(params)
  ```

  ```go Go {22,29} theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {

    ctx := context.TODO()

    client := resend.NewClient("re_xxxxxxxxx")

    var batchEmails = []*resend.SendEmailRequest{
      {
        From:        "Acme <onboarding@resend.dev>",
        To:          []string{"foo@gmail.com"},
        Subject:     "hello world",
        Html:        "<h1>it works!</h1>",
        ScheduledAt: "in 1 min",
      },
      {
        From:        "Acme <onboarding@resend.dev>",
        To:          []string{"bar@outlook.com"},
        Subject:     "world hello",
        Html:        "<p>it works!</p>",
        ScheduledAt: "in 5 min",
      },
    }

    sent, err := client.Batch.SendWithContext(ctx, batchEmails)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Data)
  }
  ```

  ```rust Rust {15,22} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::CreateEmailBaseOptions;
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let emails = vec![
      CreateEmailBaseOptions::new(
        "Acme <onboarding@resend.dev>",
        vec!["foo@gmail.com"],
        "hello world",
      )
      .with_html("<h1>it works!</h1>")
      .with_scheduled_at("in 1 min"),
      CreateEmailBaseOptions::new(
        "Acme <onboarding@resend.dev>",
        vec!["bar@outlook.com"],
        "world hello",
      )
      .with_html("<p>it works!</p>")
      .with_scheduled_at("in 5 min"),
    ];

    let _emails = resend.batch.send(emails).await?;

    Ok(())
  }
  ```

  ```java Java {13,21} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;
  import java.util.Arrays;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateEmailOptions firstEmail = CreateEmailOptions.builder()
              .from("Acme <onboarding@resend.dev>")
              .to("foo@gmail.com")
              .subject("hello world")
              .html("<h1>it works!</h1>")
              .scheduledAt("in 1 min")
              .build();

          CreateEmailOptions secondEmail = CreateEmailOptions.builder()
              .from("Acme <onboarding@resend.dev>")
              .to("bar@outlook.com")
              .subject("world hello")
              .html("<p>it works!</p>")
              .scheduledAt("in 5 min")
              .build();

          CreateBatchEmailsResponse data = resend.batch().send(
              Arrays.asList(firstEmail, secondEmail)
          );
      }
  }
  ```

  ```csharp .NET {11,20} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var mail1 = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "foo@gmail.com",
      Subject = "hello world",
      HtmlBody = "<h1>it works!</h1>",
      MomentSchedule = "in 1 min",
  };

  var mail2 = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "bar@outlook.com",
      Subject = "world hello",
      HtmlBody = "<p>it works!</p>",
      MomentSchedule = "in 5 min",
  };

  var resp = await resend.EmailBatchAsync( [ mail1, mail2 ] );
  Console.WriteLine( "Nr Emails={0}", resp.Content.Count );
  ```

  ```bash cURL {10,17} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails/batch' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'[
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["foo@gmail.com"],
      "subject": "hello world",
      "html": "<h1>it works!</h1>",
      "scheduled_at": "in 1 min"
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["bar@outlook.com"],
      "subject": "world hello",
      "html": "<p>it works!</p>",
      "scheduled_at": "in 5 min"
    }
  ]'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Each email in emails.json can set its own scheduled_at
  resend emails batch --file ./emails.json
  ```
</CodeGroup>

## View a scheduled email

Once you schedule an email, you can see the scheduled time in the Resend dashboard.

<video />

## Reschedule an email

After scheduling an email, you might need to update the scheduled time.

You can do so with the following method:

<CodeGroup>
  ```ts Node.js {3} theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend.emails.update({
    id: '49a3999c-0ce1-4ea6-ab68-afcd6dc2e794',
    scheduledAt: 'in 1 min',
  });
  ```

  ```php PHP {2} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend->emails->update('49a3999c-0ce1-4ea6-ab68-afcd6dc2e794', [
    'scheduled_at' => 'in 1 min'
  ]);
  ```

  ```python Python {3} theme={"theme":{"light":"github-light","dark":"vesper"}}
  update_params: resend.Emails.UpdateParams = {
    "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
    "scheduled_at": "in 1 min"
  }

  resend.Emails.update(params=update_params)
  ```

  ```rb Ruby {3} theme={"theme":{"light":"github-light","dark":"vesper"}}
  update_params = {
    "email_id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
    "scheduled_at": "in 1 min"
  }

  updated_email = Resend::Emails.update(update_params)
  ```

  ```go Go {7} theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	updateParams := &resend.UpdateEmailRequest{
  		Id:          "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
  		ScheduledAt: "in 1 min",
  	}

  	updatedEmail, err := client.Emails.Update(updateParams)

  	if err != nil {
  		panic(err)
  	}
  	fmt.Printf("%v\n", updatedEmail)
  }
  ```

  ```rust Rust {2} theme={"theme":{"light":"github-light","dark":"vesper"}}
  let update = UpdateEmailOptions::new()
    .with_scheduled_at("in 1 min");

  let _email = resend
    .emails
    .update("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794", update)
    .await?;
  ```

  ```java Java {2} theme={"theme":{"light":"github-light","dark":"vesper"}}
  UpdateEmailOptions updateParams = UpdateEmailOptions.builder()
    .scheduledAt("in 1 min")
    .build();

  UpdateEmailResponse data = resend.emails().update("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794", updateParams);
  ```

  ```csharp .NET {7} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.EmailRescheduleAsync(
    new Guid( "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794" ),
    "in 1 min"
  );
  ```

  ```bash cURL {5} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X PATCH 'https://api.resend.com/emails/49a3999c-0ce1-4ea6-ab68-afcd6dc2e794' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "scheduled_at": "in 1 min"
  }'
  ```

  ```bash CLI {2} theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails update 49a3999c-0ce1-4ea6-ab68-afcd6dc2e794 \
    --scheduled-at "in 1 min"
  ```
</CodeGroup>

You can also reschedule an email directly in the Resend Dashboard.

<video />

## Cancel a scheduled email

<Warning>Once an email is canceled, it cannot be rescheduled.</Warning>

If you need to cancel a scheduled email, you can do so with the following code:

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend.emails.cancel('49a3999c-0ce1-4ea6-ab68-afcd6dc2e794');
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend->emails->cancel('49a3999c-0ce1-4ea6-ab68-afcd6dc2e794');
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend.Emails.cancel(email_id="49a3999c-0ce1-4ea6-ab68-afcd6dc2e794")
  ```

  ```rb Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend::Emails.cancel("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  canceled, err := client.Emails.Cancel("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794")
  if err != nil {
    panic(err)
  }
  fmt.Println(canceled.Id)
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  let _canceled = resend
    .emails
    .cancel("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794")
    .await?;
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  CancelEmailResponse canceled = resend
      .emails()
      .cancel("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794");
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  await resend.EmailCancelAsync( new Guid( "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794" ) );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails/49a3999c-0ce1-4ea6-ab68-afcd6dc2e794/cancel' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails cancel 49a3999c-0ce1-4ea6-ab68-afcd6dc2e794
  ```
</CodeGroup>

You can also cancel a scheduled email in the Resend dashboard.

<video />

## Scheduled email failures

Scheduled emails may fail to send for several reasons. When this happens, you'll see a failure notification in the email details screen with specific information about why the email couldn't be sent.

Common failure reasons include:

* **API key is no longer active** - The API key used to schedule the email has been deleted, expired, or suspended. The email cannot be sent.
* **Account under review** - Your account has been flagged for review and sending has been temporarily suspended. Contact [support@resend.com](mailto:support@resend.com) if you believe this is an error.

You can view the failure reason and details in the Resend dashboard by clicking on the failed email.

## Limitations

* Emails sent via SMTP cannot be scheduled

## Try it yourself

<CardGroup>
  <Card title="Next.js (TypeScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/scheduling">
    See the full source code.
  </Card>

  <Card title="Next.js (JavaScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/scheduling">
    See the full source code.
  </Card>

  <Card title="PHP" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/scheduling">
    See the full source code.
  </Card>

  <Card title="Laravel" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/laravel-resend-examples">
    See the full source code.
  </Card>

  <Card title="Python" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/python-resend-examples/examples">
    See the full source code.
  </Card>

  <Card title="Ruby" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/examples">
    See the full source code.
  </Card>
</CardGroup>


# Send Test Emails
Source: https://resend.com/docs/dashboard/emails/send-test-emails

Simulate different events by sending test emails.

## How to send test emails

During development, it's important to test different deliverability scenarios.

> **Example**: When an email hard bounces or is marked as spam, it's important to stop sending emails to the recipient, as continuing to send emails to those addresses will damage your domain reputation. Consider [creating a webhook endpoint](/docs/webhooks/introduction) to capture these events and remove the addresses from your mailing lists.

When testing, avoid:

* sending to fake email addresses
* setting up a fake SMTP server

Use the provided `resend.dev` test email addresses to simulate different email events without damaging your domain reputation. These test emails enable the safe use of Resend's Dashboard, Webhooks, and API when developing your application.

<Note>Test emails count against your account's sending quota.</Note>

All test email addresses support labeling, which enables you to send emails to the same test address in multiple ways. You can add a label after the `+` symbol (e.g., `delivered+label1@resend.dev`) to help track and differentiate between different test scenarios in your application.

## Test delivered emails

To test that your emails are being successfully delivered, you can send an email to:

```
delivered@resend.dev
```

With labeling support, you can also use:

```
delivered+user1@resend.dev
delivered+user2@resend.dev
delivered+user3@resend.dev
```

## Test bounced emails

To test that the recipient's email provider rejected your email, you can send an email to:

```
bounced@resend.dev
```

With labeling support, you can also use:

```
bounced+user1@resend.dev
bounced+user2@resend.dev
bounced+user3@resend.dev
```

This will generate a SMTP 550 5.1.1 ("Unknown User") response code.

## Test "Marked as Spam" emails

To test that your emails are being received but marked as spam, you can send an email to:

```
complained@resend.dev
```

With labeling support, you can also use:

```
complained+user1@resend.dev
complained+user2@resend.dev
complained+user3@resend.dev
```

## Test suppressed emails

To test that your emails are being suppressed, you can send an email to:

```
suppressed@resend.dev
```

<Info>
  When using this test email, the suppression reason will indicate the address
  was previously bounced
</Info>

## Using labels effectively

<Warning>
  The suppressed test email address does not support labeling yet
</Warning>

The labeling feature allows you to use any string as a label after the `+` symbol. This is particularly useful for:

* Testing different email flows (e.g., `delivered+signup@resend.dev`, `delivered+password-reset@resend.dev`)
* Tracking webhook responses for specific test scenarios
* Differentiating between multiple test runs
* Matching responses with the specific email address that triggered the event


# Managing Tags
Source: https://resend.com/docs/dashboard/emails/tags

Add unique identifiers to emails sent.

Tags are unique identifiers you can add to your emails. They help associate emails with your application. They are passed in key/value pairs. After the email is sent, the tag is included in the webhook event. Tags can include ASCII letters, numbers, underscores, or dashes. You can add up to 75 tags per email.

Some examples of when to use a tag:

* Associate the email a "customer ID" from your application
* Add a label from your database like "free" or "enterprise"
* Note the category of email sent, like "welcome" or "password reset"

Here's how you can add custom tags to your emails.

## Add tags on the `POST /emails` endpoint

<CodeGroup>
  ```ts Node.js {10-15} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'hello world',
    html: '<p>it works!</p>',
    tags: [
      {
        name: 'category',
        value: 'confirm_email',
      },
    ],
  });
  ```

  ```php PHP {8-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->send([
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'hello world',
    'html' => '<p>it works!</p>',
    'tags' => [
      [
        'name' => 'category',
        'value' => 'confirm_email',
      ],
    ]
  ]);
  ```

  ```python Python {10-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Emails.SendParams = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "tags": [
      {"name": "category", "value": "confirm_email"},
    ],
  }

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

  ```rb Ruby {10-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "tags": [
      {"name": "category", "value": "confirm_email"}
    ]
  }

  sent = Resend::Emails.send(params)
  puts sent
  ```

  ```go Go {16} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
    ctx := context.TODO()
    client := resend.NewClient("re_xxxxxxxxx")

    params := &resend.SendEmailRequest{
        From:        "Acme <onboarding@resend.dev>",
        To:          []string{"delivered@resend.dev"},
        Text:        "<p>it works!</p>",
        Subject:     "hello world",
        Tags:        []resend.Tag{{Name: "category", Value: "confirm_email"}},
    }

    sent, err := client.Emails.SendWithContext(ctx, params)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Id)
  }
  ```

  ```rust Rust {14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::{CreateEmailBaseOptions, Tag};
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let from = "Acme <onboarding@resend.dev>";
    let to = ["delivered@resend.dev"];
    let subject = "hello world";

    let email = CreateEmailBaseOptions::new(from, to, subject)
      .with_html("<p>it works!</p>")
      .with_tag(Tag::new("category", "confirm_email"));

    let _email = resend.emails.send(email).await?;

    Ok(())
  }
  ```

  ```java Java {17} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          Tag tag = Tag.builder()
                  .name("category")
                  .value("confirm_email")
                  .build();

          SendEmailRequest sendEmailRequest = SendEmailRequest.builder()
                  .from("Acme <onboarding@resend.dev>")
                  .to("delivered@resend.dev")
                  .subject("hello world")
                  .html("<p>it works!</p>")
                  .tags(tag)
                  .build();

          SendEmailResponse data = resend.emails().send(sendEmailRequest);
      }
  }
  ```

  ```csharp .NET {12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.EmailSendAsync( new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = "hello world",
      HtmlBody = "<p>it works!</p>",
      ReplyTo = "onboarding@resend.dev",
      Tags = new List<EmailTag> { new EmailTag { Name = "category", Value = "confirm_email" } }
  } );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL {9-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "tags": [
      {
        "name": "category",
        "value": "confirm_email"
      }
    ]
  }'
  ```

  ```bash CLI {6} theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails send \
    --from "Acme <onboarding@resend.dev>" \
    --to delivered@resend.dev \
    --subject "hello world" \
    --html "<p>it works!</p>" \
    --tags "category=confirm_email"
  ```
</CodeGroup>

## Add tags on the `POST /emails/batch` endpoint

<CodeGroup>
  ```ts Node.js {11-16,23-28} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.batch.send([
    {
      from: 'Acme <onboarding@resend.dev>',
      to: ['foo@gmail.com'],
      subject: 'hello world',
      html: '<h1>it works!</h1>',
      tags: [
        {
          name: 'category',
          value: 'confirm_email',
        },
      ],
    },
    {
      from: 'Acme <onboarding@resend.dev>',
      to: ['bar@outlook.com'],
      subject: 'world hello',
      html: '<p>it works!</p>',
      tags: [
        {
          name: 'category',
          value: 'confirm_email',
        },
      ],
    },
  ]);
  ```

  ```php PHP {9-13,21-25} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->batch->send([
    [
      'from' => 'Acme <onboarding@resend.dev>',
      'to' => ['foo@gmail.com'],
      'subject' => 'hello world',
      'html' => '<h1>it works!</h1>',
      'tags' => [
        [
          'name' => 'category',
          'value' => 'confirm_email'
        ]
      ]
    ],
    [
      'from' => 'Acme <onboarding@resend.dev>',
      'to' => ['bar@outlook.com'],
      'subject' => 'world hello',
      'html' => '<p>it works!</p>',
      'tags' => [
        [
          'name' => 'category',
          'value' => 'confirm_email'
        ]
      ]
    ]
  ]);
  ```

  ```py Python {12-17,24-29} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend
  from typing import List

  resend.api_key = "re_xxxxxxxxx"

  params: List[resend.Emails.SendParams] = [
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["foo@gmail.com"],
      "subject": "hello world",
      "html": "<h1>it works!</h1>",
      "tags": [
        {
          "name": "category",
          "value": "confirm_email"
        }
      ]
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["bar@outlook.com"],
      "subject": "world hello",
      "html": "<p>it works!</p>",
      "tags": [
        {
          "name": "category",
          "value": "confirm_email"
        }
      ]
    }
  ]

  resend.Batch.send(params)
  ```

  ```rb Ruby {11-16,23-28} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = 're_xxxxxxxxx'

  params = [
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["foo@gmail.com"],
      "subject": "hello world",
      "html": "<h1>it works!</h1>",
      "tags": [
        {
          "name": "category",
          "value": "confirm_email"
        }
      ]
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["bar@outlook.com"],
      "subject": "world hello",
      "html": "<p>it works!</p>",
      "tags": [
        {
          "name": "category",
          "value": "confirm_email"
        }
      ]
    }
  ]

  Resend::Batch.send(params)
  ```

  ```go Go {22,29} theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"fmt"
  	"os"

  	"github.com/resend/resend-go/v3"
  )

  func main() {

    ctx := context.TODO()

    client := resend.NewClient("re_xxxxxxxxx")

    var batchEmails = []*resend.SendEmailRequest{
      {
        From:    "Acme <onboarding@resend.dev>",
        To:      []string{"foo@gmail.com"},
        Subject: "hello world",
        Html:    "<h1>it works!</h1>",
        Tags:    []resend.Tag{{Name: "category", Value: "confirm_email"}},
      },
      {
        From:    "Acme <onboarding@resend.dev>",
        To:      []string{"bar@outlook.com"},
        Subject: "world hello",
        Html:    "<p>it works!</p>",
        Tags:    []resend.Tag{{Name: "category", Value: "confirm_email"}},
      },
    }

    sent, err := client.Batch.SendWithContext(ctx, batchEmails)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Data)
  }
  ```

  ```rust Rust {15,22} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::CreateEmailBaseOptions;
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let emails = vec![
      CreateEmailBaseOptions::new(
        "Acme <onboarding@resend.dev>",
        vec!["foo@gmail.com"],
        "hello world",
      )
      .with_html("<h1>it works!</h1>")
      .with_tag(Tag::new("category", "confirm_email")),
      CreateEmailBaseOptions::new(
        "Acme <onboarding@resend.dev>",
        vec!["bar@outlook.com"],
        "world hello",
      )
      .with_html("<p>it works!</p>")
      .with_tag(Tag::new("category", "confirm_email")),
    ];

    let _emails = resend.batch.send(emails).await?;

    Ok(())
  }
  ```

  ```java Java {12-15,23-26} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateEmailOptions firstEmail = CreateEmailOptions.builder()
              .from("Acme <onboarding@resend.dev>")
              .to("foo@gmail.com")
              .subject("hello world")
              .html("<h1>it works!</h1>")
              .tags(Tag.builder()
                  .name("category")
                  .value("confirm_email")
                  .build())
              .build();

          CreateEmailOptions secondEmail = CreateEmailOptions.builder()
              .from("Acme <onboarding@resend.dev>")
              .to("bar@outlook.com")
              .subject("world hello")
              .html("<p>it works!</p>")
              .tags(Tag.builder()
                  .name("category")
                  .value("confirm_email")
                  .build())
              .build();

          CreateBatchEmailsResponse data = resend.batch().send(
              Arrays.asList(firstEmail, secondEmail)
          );
      }
  }
  ```

  ```csharp .NET {11,20} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var mail1 = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "foo@gmail.com",
      Subject = "hello world",
      HtmlBody = "<p>it works!</p>",
      Tags = new List<EmailTag> { new EmailTag { Name = "category", Value = "confirm_email" } }
  };

  var mail2 = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "bar@outlook.com",
      Subject = "hello world",
      HtmlBody = "<p>it works!</p>",
      Tags = new List<EmailTag> { new EmailTag { Name = "category", Value = "confirm_email" } }
  };

  var resp = await resend.EmailBatchAsync( [ mail1, mail2 ] );
  Console.WriteLine( "Nr Emails={0}", resp.Content.Count );
  ```

  ```bash cURL {10-15,22-27} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails/batch' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'[
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["foo@gmail.com"],
      "subject": "hello world",
      "html": "<h1>it works!</h1>",
      "tags": [
        {
          "name": "category",
          "value": "confirm_email"
        }
      ]
    },
    {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["bar@outlook.com"],
      "subject": "world hello",
      "html": "<p>it works!</p>",
      "tags": [
        {
          "name": "category",
          "value": "confirm_email"
        }
      ]
    }
  ]'
  ```
</CodeGroup>


# Introduction
Source: https://resend.com/docs/dashboard/logs/introduction

Learn how to view and troubleshoot API logs.

## Overview

Logs are a powerful tool for monitoring activity and troubleshooting issues.

<Tabs>
  <Tab title="Using the dashboard">
    Access your logs from the [Logs page](https://resend.com/logs) in the dashboard.

    <img alt="Logs" />

    Each log entry shows:

    * **Endpoint** - The API endpoint called (e.g., `/domains`, `/api-keys`, `/contacts`)
    * **Status** - The HTTP response status code (200, 201, etc.)
    * **Method** - The HTTP method used (GET, POST, DELETE, etc.)
    * **Created** - When the request was made (displayed as relative time)

    ## Searching Logs

    Use the search bar to find specific logs. This is useful when tracking down a particular request or debugging an issue.

    ## Filtering Logs

    Filter logs by response status to quickly identify issues:

    * **All Statuses** - View all logs
    * **Successes** - Show only successful requests (2xx status codes)
    * **Errors** - Show only failed requests (4xx and 5xx status codes)
    * **Specific codes** - Select one or more specific HTTP status codes (200, 201, 403, 429, etc.)

    You can select multiple status codes to create custom filters.

    * **Date range** - Adjust the time period for logs (e.g., Last 15 days)
    * **User Agents** - Filter by SDK or client
    * **API Keys** - Filter by specific API key

    ## Log details

    Click any log entry to view complete details.

    <img alt="Logs" />

    ### Request information

    * **Request body** - The full JSON payload sent to the API (with copyable code blocks)
    * **HTTP method** - GET, POST, etc.
    * **Endpoint** - The API endpoint called
    * **User-Agent** - The client or SDK used, with automatic SDK detection showing name and version

    ### Response information

    * **Response body** - The complete API response (with copyable code blocks)
    * **Status code** - The HTTP status code returned
    * **Timestamp** - When the request was processed

    ### Related emails

    When a log entry is associated with one or more email sends, an Email field appears in the log details, linking directly to the corresponding email records. The corresponding email's detail page includes a Log field linking to the API request log that triggered it, so you can trace the full request-to-delivery flow in both directions.

    ### SDK detection

    The dashboard automatically detects and displays Resend SDK information from the User-Agent header, showing:

    * SDK name (e.g., "Resend Node.js")
    * Version number
    * Update notification when a newer SDK version is available

    ## Troubleshooting errors

    For supported error types, click the **Help me fix** button to open a troubleshooting drawer.

    <img alt="Logs" />

    The drawer includes:

    * **Raw response** - The complete API response
    * **Detailed guidance** - Step-by-step instructions to resolve the issue
    * **Relevant links** - Documentation and knowledge base articles
    * **Contextual information** - Your current rate limits, verified domains, and other relevant data

    ## Copy for AI

    For error logs (4xx and 5xx status codes), use the **Copy for AI** dropdown to get help debugging:

    * **Copy log** - Copy the log details as Markdown formatted for AI tools
    * **Open in ChatGPT** - Open ChatGPT with the log prefilled for analysis
    * **Open in Claude** - Open Claude with the log prefilled for analysis

    The copied content includes the request method, endpoint, request body, response status, and response body to help AI assistants understand and troubleshoot the issue.
  </Tab>

  <Tab title="Using the API">
    The Logs API allows you to **programmatically retrieve logs**. This is useful for integrating with your own systems, automating tasks, and equipping your AI agents with the ability to troubleshoot issues.

    ## List logs

    Retrieve a list of API request logs.

    The response includes details such as:

    * The **endpoint** called
    * The response **status code**
    * The **user agent**

    <CodeGroup>
      ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.logs.list();
      ```

      ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->logs->list();
      ```

      ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      resend.Logs.list()
      ```

      ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
      Resend.api_key = "re_xxxxxxxxx"

      logs = Resend::Logs.list
      puts logs
      ```

      ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import (
        "context"

        "github.com/resend/resend-go/v3"
      )

      func main() {
        ctx := context.TODO()
        client := resend.NewClient("re_xxxxxxxxx")

        logs, err := client.Logs.ListWithOptions(ctx, nil)
        if err != nil {
          panic(err)
        }

        if logs.HasMore {
          opts := &resend.ListOptions{
            After: &logs.Data[len(logs.Data)-1].Id,
          }
          client.Logs.ListWithOptions(ctx, opts)
        }
      }
      ```

      ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{Resend, Result, list_opts::ListOptions};

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let _logs = resend
          .logs
          .list(ListOptions::default())
          .await?;

        Ok(())
      }
      ```

      ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              resend.logs().list();
          }
      }
      ```

      ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
      // C# SDK is not available yet
      ```

      ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X GET 'https://api.resend.com/logs' \
          -H 'Authorization: Bearer re_xxxxxxxxx'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend logs list
      ```
    </CodeGroup>

    ## Retrieve log

    Once you're ready to inspect a log in greater detail, you can use the [Retrieve Log](/docs/api-reference/logs/retrieve-log) endpoint.

    This endpoint returns the full request body and response, as well as the endpoint, status code, and user agent.

    <CodeGroup>
      ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend('re_xxxxxxxxx');

      const { data, error } = await resend.logs.get(
        '37e4414c-5e25-4dbc-a071-43552a4bd53b',
      );
      ```

      ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
      $resend = Resend::client('re_xxxxxxxxx');

      $resend->logs->get('37e4414c-5e25-4dbc-a071-43552a4bd53b');
      ```

      ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
      import resend

      resend.api_key = "re_xxxxxxxxx"

      resend.Logs.get("37e4414c-5e25-4dbc-a071-43552a4bd53b")
      ```

      ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
      Resend.api_key = "re_xxxxxxxxx"

      log = Resend::Logs.get("37e4414c-5e25-4dbc-a071-43552a4bd53b")
      puts log
      ```

      ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
      package main

      import "github.com/resend/resend-go/v3"

      func main() {
        client := resend.NewClient("re_xxxxxxxxx")

        client.Logs.Get("37e4414c-5e25-4dbc-a071-43552a4bd53b")
      }
      ```

      ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
      use resend_rs::{Resend, Result};

      #[tokio::main]
      async fn main() -> Result<()> {
        let resend = Resend::new("re_xxxxxxxxx");

        let _logs = resend
          .logs
          .get("37e4414c-5e25-4dbc-a071-43552a4bd53b")
          .await?;

        Ok(())
      }
      ```

      ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
      import com.resend.*;

      public class Main {
          public static void main(String[] args) {
              Resend resend = new Resend("re_xxxxxxxxx");

              resend.logs().get("37e4414c-5e25-4dbc-a071-43552a4bd53b");
          }
      }
      ```

      ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
      // C# SDK is not available yet
      ```

      ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
      curl -X GET 'https://api.resend.com/logs/37e4414c-5e25-4dbc-a071-43552a4bd53b' \
          -H 'Authorization: Bearer re_xxxxxxxxx'
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      resend logs get 37e4414c-5e25-4dbc-a071-43552a4bd53b
      ```
    </CodeGroup>
  </Tab>
</Tabs>

***

<Note>
  View a comprehensive list of error codes and their meanings in the [Resend API
  Reference](/docs/api-reference/errors).
</Note>

## Export your data

Admins can download your data in CSV format for the following resources:

* Emails
* Broadcasts
* Contacts
* Segments
* Domains
* Logs
* API keys

<Info>Currently, exports are limited to admin users of your team.</Info>

To start, apply filters to your data and click on the "Export" button. Confirm your filters before exporting your data.

<video />

If your exported data includes 1,000 items or less, the export will download immediately. For larger exports, you'll receive an email with a link to download your data.

All admins on your team can securely access the export for 7 days. Unavailable exports are marked as "Expired."

<Note>
  All exports your team creates are listed in the
  [Exports](https://resend.com/exports) page under **Settings** > **Team** >
  **Exports**. Select any export to view its details page. All members of your
  team can view your exports, but only admins can download the data.
</Note>


# Process Receiving Attachments
Source: https://resend.com/docs/dashboard/receiving/attachments

Process attachments from receiving emails.

A common use case for Receiving emails is to process attachments.

You can access received email attachments in two ways:

* [View and download from the dashboard](#view-and-download-attachments) to inspect a single email.
* [Use the Attachments API](#process-attachments-programmatically) to process attachments programmatically.

## View and download attachments

You can view and download attachments directly from the dashboard when inspecting a received email.

1. Go to [Emails](https://resend.com/emails) and select the **Receiving** tab.
2. Open the received email that includes the attachment.
3. Click the attachment to download it locally.

For automated processing, use the [Attachments API](#process-attachments-programmatically) instead.

## Process attachments programmatically

<Info>
  Webhooks do not include the actual content of attachments, only their
  metadata. You must call the [Attachments
  API](/docs/api-reference/emails/list-received-email-attachments) to retrieve the
  content. This design choice supports large attachments in serverless
  environments that have limited request body sizes.
</Info>

Users can forward airplane tickets, receipts, and expenses to you. Then, you can extract key information from attachments and use that data.

To do this, call the [Attachments API](/docs/api-reference/emails/list-received-email-attachments) after receiving the webhook event. That API will return a list of attachments with their metadata and a `download_url` that you can use to download the actual content. To retrieve a single attachment, use [Retrieve Attachment](/docs/api-reference/emails/retrieve-received-email-attachment).

Note that the `download_url` is valid for 1 hour. After that, you will need to call the
[Attachments API](/docs/api-reference/emails/list-received-email-attachments)
again to get a new `download_url`. You can also check the `expires_at` field on
each attachment to see exactly when it will expire.

Here's how you can implement this:

<CodeGroup>
  ```ts Next.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  // app/api/events/route.ts
  import type { NextRequest } from 'next/server';
  import { NextResponse } from 'next/server';
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  export const POST = async (request: NextRequest) => {
    const event = await request.json();

    if (event.type === 'email.received') {
      const { data: attachments } =
        await resend.emails.receiving.attachments.list({
          emailId: event.data.email_id,
        });

      for (const attachment of attachments) {
        // use the download_url to download attachments however you want
        const response = await fetch(attachment.download_url);
        if (!response.ok) {
          console.error(`Failed to download ${attachment.filename}`);
          continue;
        }

        // get the file's contents
        const buffer = Buffer.from(await response.arrayBuffer());

        // process the content (e.g., save to storage, analyze, etc.)
      }

      return NextResponse.json({ attachmentsProcessed: attachments.length });
    }

    return NextResponse.json({});
  };
  ```

  ```php Laravel theme={"theme":{"light":"github-light","dark":"vesper"}}
  // routes/api.php
  use Illuminate\Http\Request;
  use Illuminate\Support\Facades\Http;
  use Illuminate\Support\Facades\Log;
  use Illuminate\Support\Facades\Route;
  use Resend\Laravel\Facades\Resend;

  Route::post('/events', function (Request $request) {
    $event = $request->json()->all();

      if ($event['type'] === 'email.received') {
          $attachments = Resend::emails()->receiving->attachments->list(
              emailId: $event['data']['email_id']
          );

          foreach ($attachments->data as $attachment) {
              $response = Http::get($attachment->download_url);

              if ($response->failed()) {
                  Log::error("Failed to download {$attachment->filename}");
                  continue;
              }

              // get the file's contents
              $contents = $response->body();

              // process the content (e.g., save to storage, analyze, etc.)
          }

          return response()->json($event);
      }

      return response()->json([]);
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  // index.php
  // Include Composer autoload file to load Resend SDK classes...
  require __DIR__ . '/vendor/autoload.php';

  header('Content-Type: application/json');

  if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
      http_response_code(405);
      echo json_encode(['error' => 'Method Not Allowed']);
      exit;
  }

  $body = file_get_contents('php://input');
  $event = json_decode($body, true);

  if (json_last_error() !== JSON_ERROR_NONE) {
      http_response_code(400);
      echo json_encode(['error' => 'Invalid JSON']);
      exit;
  }

  if ($event['type'] === 'email.received') {
      $resend = Resend::client('re_xxxxxxxxx');

      $attachments = $resend->emails->receiving->attachments->list(
          emailId: $event['data']['email_id']
      );

      foreach ($attachments->data as $attachment) {
          $ch = curl_init($attachment->download_url);
          curl_setopt_array($ch, [
              CURLOPT_RETURNTRANSFER => true,
              CURLOPT_FOLLOWLOCATION => true,
          ]);

          $contents = curl_exec($ch);
          $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          $ch = null;

          if ($contents === false || $statusCode !== 200) {
              error_log("Failed to download {$attachment->filename}");
              continue;
          }

          // process the content (e.g., save to disk, analyze, etc.)
      }

      echo json_encode($event);
      exit;
  }

  echo json_encode([]);
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use axum::{
      extract::State,
      response::{IntoResponse, Json, Response},
  };
  use resend_rs::{json, list_opts::ListOptions, Resend};
  use serde::Serialize;
  use std::sync::Arc;

  #[derive(Serialize)]
  struct Empty {}

  async fn example(
      State(state): State<Arc<AppState>>,
      Json(event): Json<resend_rs::events::EmailEvent>,
  ) -> Response {
      if matches!(
          event.r#type,
          resend_rs::events::EmailEventType::EmailReceived
      ) {
          let attachments = state
              .resend
              .receiving
              .list_attachments(&event.data.email_id, ListOptions::default())
              .await
              .unwrap();

          for attachment in &attachments.data {
              // use the download_url to download attachments however you want
              let response = reqwest::get(&attachment.download_url).await;

              if response.is_err() {
                  dbg!(format!(
                      "Failed to download {}",
                      attachment.filename.clone().unwrap()
                  ));
              }

              // get the file's contents
              let _buffer = response.unwrap().bytes().await.unwrap();

              // process the content (e.g., save to storage, analyze, etc.)
          }

          Json(json!({
              "attachmentsProcessed": attachments.len()
          }))
          .into_response()
      } else {
          Json(Empty {}).into_response()
      }
  }
  ```
</CodeGroup>

Once you process attachments, you may want to forward the email to another address. Learn more about [forwarding emails](/docs/dashboard/receiving/forward-emails).


# Custom Receiving Domains
Source: https://resend.com/docs/dashboard/receiving/custom-domains

Receive emails using your own domain.

Besides [using Resend-managed domains](/docs/dashboard/receiving/introduction), you can also receive emails using your own custom domain, such as `yourdomain.tld`.

## Enabling receiving for a new domain

<Steps>
  <Step title="Add the DNS record">
    First, [verify your domain](/docs/dashboard/domains/introduction).

    Receiving emails requires an extra [MX record](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records) to work. You'll need to add this record to your DNS provider.

    1. Go to the [Domains](https://resend.com/domains) page
    2. Copy the MX record
    3. Paste the MX record into your domain's DNS service

    <img alt="Add DNS records for Receiving Emails" />

    <Info>
      If you already have existing MX records for your domain (because you're already
      using it for a real inbox, for example), we recommend that you
      create a subdomain (e.g. `subdomain.yourdomain.tld`) and add the MX record
      there. This way, you can use Resend for receiving emails without affecting
      your existing email service. Note that you will *not* receive emails at Resend
      if the required `MX` record is not the lowest priority value for the domain.

      Alternatively, you can configure your email service to forward emails to an address
      that's configured in Resend or forward them directly to the SMTP server address
      that appears in the receiving `MX` record.
    </Info>
  </Step>

  <Step title="Configure webhooks">
    Next, create a new webhook endpoint to receive email events.

    1. Go to the [Webhooks](https://resend.com/webhooks) page
    2. Click "Add Webhook"
    3. Enter the URL of your webhook endpoint
    4. Select the event type `email.received`
    5. Click "Add"

    <img alt="Add Webhook for Receiving Emails" />
  </Step>

  <Step title="Receive email events">
    In your application, create a new route that can accept `POST` requests.

    Here's how you can implement this:

    <CodeGroup>
      ```js Next.js theme={"theme":{"light":"github-light","dark":"vesper"}}
      // app/api/events/route.ts
      import type { NextRequest } from 'next/server';
      import { NextResponse } from 'next/server';

      export const POST = async (request: NextRequest) => {
        const event = await request.json();

        if (event.type === 'email.received') {
          return NextResponse.json(event);
        }

        return NextResponse.json({});
      };
      ```

      ```php Laravel theme={"theme":{"light":"github-light","dark":"vesper"}}
      // routes/api.php
      use Illuminate\Http\Request;
      use Illuminate\Support\Facades\Route;

      Route::post('/events', function (Request $request) {
          $event = $request->json()->all();

          if ($event['type'] === 'email.received') {
              return response()->json($event);
          }

          return response()->json([]);
      });
      ```

      ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
      // index.php
      header('Content-Type: application/json');

      if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
          http_response_code(405);
          echo json_encode(['error' => 'Method Not Allowed']);
          exit;
      }

      $body = file_get_contents('php://input');
      $event = json_decode($body, true);

      if (json_last_error() !== JSON_ERROR_NONE) {
          http_response_code(400);
          echo json_encode(['error' => 'Invalid JSON']);
          exit;
      }

      if ($event['type'] === 'email.received') {
          echo json_encode($event);
          exit;
      }

      echo json_encode([]);
      ```

      ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
      #[derive(Serialize)]
      struct Empty {}

      async fn example(Json(event): Json<resend_rs::events::EmailEvent>) -> Response {
          if matches!(
              event.r#type,
              resend_rs::events::EmailEventType::EmailReceived
          ) {
              Json(event).into_response()
          } else {
              Json(Empty {}).into_response()
          }
      }
      ```
    </CodeGroup>

    Once you receive the email event, you can process the email body and attachments. You can also implement [webhook request verification](/docs/webhooks/verify-webhooks-requests) to secure your webhook endpoint.

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "type": "email.received",
      "created_at": "2026-02-22T23:41:12.126Z",
      "data": {
        "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
        "created_at": "2026-02-22T23:41:11.894Z",
        "from": "onboarding@resend.dev",
        "to": ["delivered@resend.dev"],
        "bcc": [],
        "cc": [],
        "received_for": ["forwarded@example.com"],
        "message_id": "<111-222-333@email.example.com>",
        "subject": "Sending this example",
        "attachments": [
          {
            "id": "2a0c9ce0-3112-4728-976e-47ddcd16a318",
            "filename": "avatar.png",
            "content_type": "image/png",
            "content_disposition": "inline",
            "content_id": "img001"
          }
        ]
      }
    }
    ```
  </Step>
</Steps>

## Enabling receiving for an existing domain

If you already have a verified domain, you can enable receiving by using the toggle in the receiving section of the domain details page.

<img alt="Enable Receiving Emails for a verified domain" />

After enabling receiving, you'll see a modal showing the MX record that you need to add to your DNS provider to start receiving emails.

Once you add the MX record, confirm by clicking the **I've added the record** button and wait for the receiving record to show as "verified".

## FAQ

<AccordionGroup>
  <Accordion title="What happens if I already have MX records for my domain?">
    If you already have existing MX records for your domain, we recommend that you
    create a subdomain (e.g. `subdomain.yourdomain.tld`) and add the MX record
    there.

    That's because emails will usually only be delivered to the MX record with the lowest
    priority value. Therefore, if you add Resend's MX record to your root domain alongside existing MX records,
    it will either not receive any emails at all (if the existing MX records have a lower priority),
    or it will interfere with your existing email service (if Resend's MX record has a lower priority). If you
    use the same priority, email delivery will be unpredictable and may hit either Resend or your existing email
    service.

    If you still want to use the same domain both in for Resend and your day-to-day
    email service, you can also set up forwarding rules in your existing email service
    to forward emails to an address that's configured in Resend or forward them directly
    to the SMTP server address that appears in the receiving `MX` record.
  </Accordion>

  <Accordion title="I have already verified my domain for sending. Do I need to verify it again for receiving?">
    No, you do not need to verify your entire domain again. If you already have a
    verified domain for sending, you can simply enable receiving for that domain,
    add the required MX record to your DNS provider, and click "I've added the record"
    to start verifying *only* the MX record.
  </Accordion>
</AccordionGroup>


# Forward Received Emails
Source: https://resend.com/docs/dashboard/receiving/forward-emails

Forward Received emails to another email address.

Received emails can also be forwarded to another email address.

<Info>
  Webhooks do not include the email body, headers, or attachments, only their
  metadata. You must call the [Received emails
  API](/docs/api-reference/emails/retrieve-received-email) or the [Attachments
  API](/docs/api-reference/emails/list-received-email-attachments) to retrieve them.
  This design choice supports large attachments in serverless environments that
  have limited request body sizes.
</Info>

## Using the `forward` helper method

The Node.js SDK provides a `forward()` helper method that simplifies forwarding received emails. This method automatically handles fetching the email content and attachments.

Here's how you can implement this:

<CodeGroup>
  ```ts Next.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import type { NextRequest } from 'next/server';
  import { NextResponse } from 'next/server';
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  export const POST = async (request: NextRequest) => {
    const event = await request.json();

    if (event.type === 'email.received') {
      const { data, error } = await resend.emails.receiving.forward({
        emailId: event.data.email_id,
        to: 'delivered@resend.dev',
        from: 'onboarding@resend.dev',
      });

      if (error) {
        return new NextResponse(`Error: ${error.message}`, { status: 500 });
      }

      return NextResponse.json(data);
    }

    return NextResponse.json({});
  };
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  async fn example(
      State(state): State<Arc<AppState>>,
      Json(event): Json<resend_rs::events::EmailEvent>,
  ) -> Result<Response, Response> {
      if matches!(
          event.r#type,
          resend_rs::events::EmailEventType::EmailReceived
      ) {
          let opts = ForwardReceivingEmail::new(
              InboundEmailId::new(&event.data.email_id),
              "onboarding@resend.dev",
              vec!["delivered@resend.dev"],
          );
          let data = state.resend.receiving.forward(opts).await.map_err(|e| {
              (StatusCode::INTERNAL_SERVER_ERROR, format!("Error: {}", e)).into_response()
          })?;
          Ok(Json(data).into_response())
      } else {
          Ok(Json(Empty {}).into_response())
      }
  }
  ```
</CodeGroup>

By default, the `forward` method forwards the email in a way that preserves the original email content and attachments exactly as received.

Alternatively, you can forward emails as if they had been forwarded through an email client, with the `forwarded message` footer. For that, use `passthrough: false` and provide custom text or HTML content. The original email will be shown after the `forwarded message` footer:

<CodeGroup>
  ```ts Next.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.receiving.forward({
    emailId: event.data.email_id,
    to: 'delivered@resend.dev',
    from: 'onboarding@resend.dev',
    passthrough: false,
    text: 'See attached forwarded message.',
    html: '<p>See attached forwarded message.</p>',
  });
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  let opts = ForwardReceivingEmail::new(
      InboundEmailId::new(&event.data.email_id),
      "onboarding@resend.dev",
      vec!["delivered@resend.dev"],
  )
  .with_passthrough(false)
  .with_text("See attached forwarded message.")
  .with_html("<p>See attached forwarded message.</p>");

  let data = state.resend.receiving.forward(opts).await;
  ```
</CodeGroup>

## Manual forwarding

If you're not using Node.js or prefer not to use the `forward` helper method, you can manually forward received emails using the [Send Email API](/docs/api-reference/emails/send-email).

The recommended approach is to download the raw email and parse it to properly extract content and attachments (especially for inline images). Then, you can send a new email with the extracted content and attachments using the [Send Email API](/docs/api-reference/emails/send-email).

<CodeGroup>
  ```js app/api/events/route.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
  import type { NextRequest } from 'next/server';
  import { NextResponse } from 'next/server';
  import { Resend } from 'resend';
  import { simpleParser } from 'mailparser';

  const resend = new Resend('re_xxxxxxxxx');

  export const POST = async (request: NextRequest) => {
    const event = await request.json();

    if (event.type === 'email.received') {
      // Get the email metadata
      const { data: email } = await resend
        .emails
        .receiving
        .get(event.data.email_id);

      // Download the raw email content if available
      if (!email?.raw?.download_url) {
        return new NextResponse('Raw email not available', { status: 500 });
      }

      const rawResponse = await fetch(email.raw.download_url);
      const rawEmailContent = await rawResponse.text();

      // Parse the raw email to extract content and attachments
      const parsed = await simpleParser(rawEmailContent, {
        skipImageLinks: true,
      });

      // Extract attachments with content_id for inline images
      const attachments = parsed.attachments.map((attachment) => {
        // Strip < and > from content IDs for proper inline image handling
        const contentId = attachment.contentId
          ? attachment.contentId.replace(/^<|>$/g, '')
          : undefined;

        return {
          filename: attachment.filename,
          content: attachment.content.toString('base64'),
          content_type: attachment.contentType,
          content_id: contentId || undefined,
        };
      });

      const { data, error } = await resend.emails.send({
        from: 'Acme <onboarding@resend.dev>',
        to: ['delivered@resend.dev'],
        subject: email.subject || '(no subject)',
        html: parsed.html || undefined,
        text: parsed.text || undefined,
        attachments: attachments.length > 0 ? attachments : undefined,
      });

      if (error) {
        return new NextResponse(`Error: ${error.message}`, { status: 500 });
      }

      return NextResponse.json(data);
    }

    return NextResponse.json({});
  };
  ```
</CodeGroup>

<Note>
  This example uses the [`mailparser`](https://www.npmjs.com/package/mailparser)
  library (`npm install mailparser`) to parse the raw email. For other
  languages/SDKs, you'll need an equivalent email parsing library capable of
  processing emails compliant to [RFC
  5322](https://datatracker.ietf.org/doc/html/rfc5322).
</Note>


# Get Email Content
Source: https://resend.com/docs/dashboard/receiving/get-email-content

Get the body and headers of a received email.

Receiving emails contain the HTML and Plain Text body of the email, as well as the headers.

<Info>
  Webhooks do not include the email body, headers, or attachments, only their
  metadata. You must call the [Received emails
  API](/docs/api-reference/emails/retrieve-received-email) or the [Attachments
  API](/docs/api-reference/emails/list-received-email-attachments) to retrieve them.
  This design choice supports large attachments in serverless environments that
  have limited request body sizes.
</Info>

After receiving the webhook event, call the [Receiving API](/docs/api-reference/emails/retrieve-received-email).

Here are some examples:

<CodeGroup>
  ```ts Next.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  // app/api/events/route.ts
  import type { NextRequest } from 'next/server';
  import { NextResponse } from 'next/server';
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  export const POST = async (request: NextRequest) => {
    const event = await request.json();

    if (event.type === 'email.received') {
      const { data: email } = await resend.emails.receiving.get(
        event.data.email_id,
      );

      console.log(email.html);
      console.log(email.text);
      console.log(email.headers);

      return NextResponse.json(email);
    }

    return NextResponse.json({});
  };
  ```

  ```php Laravel theme={"theme":{"light":"github-light","dark":"vesper"}}
  // routes/api.php
  use Illuminate\Http\Request;
  use Illuminate\Support\Facades\Log;
  use Illuminate\Support\Facades\Route;
  use Resend\Laravel\Facades\Resend;

  Route::post('/events', function (Request $request) {
      $event = $request->json()->all();

      if ($event['type'] === 'email.received') {
          $email = Resend::emails()->receiving->get($event['data']['email_id']);

          Log::info($email->html);
          Log::info($email->text);
          Log::info($email->headers);

          return response()->json($email);
      }

      return response()->json([]);
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  // index.php
  // Include Composer autoload file to load Resend SDK classes...
  require __DIR__ . '/vendor/autoload.php';

  header('Content-Type: application/json');

  if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
      http_response_code(405);
      echo json_encode(['error' => 'Method Not Allowed']);
      exit;
  }

  $body = file_get_contents('php://input');
  $event = json_decode($body, true);

  if (json_last_error() !== JSON_ERROR_NONE) {
      http_response_code(400);
      echo json_encode(['error' => 'Invalid JSON']);
      exit;
  }

  if ($event['type'] === 'email.received') {
      $resend = Resend::client('re_xxxxxxxxx');

      $email = $resend->emails->receiving->get($event['data']['email_id']);

      echo json_encode($email);
      exit;
  }

  echo json_encode([]);
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use axum::{extract::State, response::Json};
  use resend_rs::Resend;
  use std::sync::Arc;

  #[derive(Serialize)]
  struct Empty {}

  async fn example(
      State(state): State<Arc<AppState>>,
      Json(event): Json<resend_rs::events::EmailEvent>,
  ) -> Response {
      if matches!(
          event.r#type,
          resend_rs::events::EmailEventType::EmailReceived
      ) {
          let email = state
              .resend
              .receiving
              .get(&event.data.email_id)
              .await
              .unwrap();

          dbg!(&email.html, &email.text, &email.headers);

          Json(email).into_response()
      } else {
          Json(Empty {}).into_response()
      }
  }
  ```
</CodeGroup>


# Receiving Emails
Source: https://resend.com/docs/dashboard/receiving/introduction

Learn how to receive emails via webhooks.

Resend supports receiving emails (commonly called inbound) in addition to sending emails. This is useful for:

* Receiving support emails from users
* Processing forwarded attachments
* Replying to emails from customers

## How does it work

Resend processes all incoming emails for your receiving domain, parses the contents and attachments, and then sends a `POST` request to an endpoint that you choose.

To receive emails, you can either use a domain managed by Resend, or [set up a custom domain](/docs/dashboard/receiving/custom-domains).

<img alt="Receiving email process" />

<Info>
  Importantly, *any email* sent to your receiving domain will be received by Resend and forwarded to your webhook. You can intelligently route based on the `to` field in the webhook event.

  For example, if your domain is `cool-hedgehog.resend.app`, you will receive
  emails sent to `anything@cool-hedgehog.resend.app`.

  The same applies to [custom domains](/docs/dashboard/receiving/custom-domains). If
  your domain is `yourdomain.tld`, you will receive emails sent to
  `anything@yourdomain.tld`.
</Info>

## Receive emails from your app with a webhook

Here's how to start receiving emails using a domain managed by Resend.

<Steps>
  <Step title="Get your .resend.app domain">
    Any emails sent to an `<anything>@<id>.resend.app` address will be received by Resend and forwarded to your webhook.

    To see your Resend domain:

    1. Go to the [emails page](https://resend.com/emails).
    2. Select the ["Receiving" tab](https://resend.com/emails/receiving).
    3. Click the three dots button and select "Receiving address."

    <img alt="Get your Resend domain" />
  </Step>

  <Step title="Configure webhooks">
    1. Go to the [Webhooks](https://resend.com/webhooks) page.
    2. Click `Add Webhook`.
    3. Enter the URL of your webhook endpoint.
    4. Select the event type `email.received`.
    5. Click `Add`.

    <Tip>
      For development, you can create a tunnel to your localhost server using a tool like
      [ngrok](https://ngrok.com/download) or [VS Code Port Forwarding](https://code.visualstudio.com/docs/debugtest/port-forwarding). These tools serve your local dev environment at a public URL you can use to test your local webhook endpoint.

      Example: `https://example123.ngrok.io/api/webhook`
    </Tip>

    <Tip>
      The [Resend CLI](/docs/cli) also has a built-in `emails receiving listen` command
      that polls for new inbound emails and displays them as they arrive. See the
      [CLI reference](/docs/cli#receiving) for setup instructions.
    </Tip>

    <img alt="Add Webhook for Receiving Emails" />
  </Step>

  <Step title="Receive email events">
    In your application, create a new route that can accept `POST` requests.

    Here's how you can implement this:

    <CodeGroup>
      ```js Next.js theme={"theme":{"light":"github-light","dark":"vesper"}}
      // app/api/events/route.ts
      import type { NextRequest } from 'next/server';
      import { NextResponse } from 'next/server';

      export const POST = async (request: NextRequest) => {
        const event = await request.json();

        if (event.type === 'email.received') {
          return NextResponse.json(event);
        }

        return NextResponse.json({});
      };
      ```

      ```php Laravel theme={"theme":{"light":"github-light","dark":"vesper"}}
      // routes/api.php
      use Illuminate\Http\Request;
      use Illuminate\Support\Facades\Route;

      Route::post('/events', function (Request $request) {
          $event = $request->json()->all();

          if ($event['type'] === 'email.received') {
              return response()->json($event);
          }

          return response()->json([]);
      });
      ```

      ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
      // index.php
      header('Content-Type: application/json');

      if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
          http_response_code(405);
          echo json_encode(['error' => 'Method Not Allowed']);
          exit;
      }

      $body = file_get_contents('php://input');
      $event = json_decode($body, true);

      if (json_last_error() !== JSON_ERROR_NONE) {
          http_response_code(400);
          echo json_encode(['error' => 'Invalid JSON']);
          exit;
      }

      if ($event['type'] === 'email.received') {
          echo json_encode($event);
          exit;
      }

      echo json_encode([]);
      ```

      ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
      #[derive(Serialize)]
      struct Empty {}

      async fn example(Json(event): Json<resend_rs::events::EmailEvent>) -> Response {
          if matches!(
              event.r#type,
              resend_rs::events::EmailEventType::EmailReceived
          ) {
              Json(event).into_response()
          } else {
              Json(Empty {}).into_response()
          }
      }
      ```
    </CodeGroup>

    Once you receive the email event, you can process the email body and attachments. You can also implement [webhook request verification](/docs/webhooks/verify-webhooks-requests) to secure your webhook endpoint.

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "type": "email.received",
      "created_at": "2026-02-22T23:41:12.126Z",
      "data": {
        "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
        "created_at": "2026-02-22T23:41:11.894Z",
        "from": "onboarding@resend.dev",
        "to": ["delivered@resend.dev"],
        "bcc": [],
        "cc": [],
        "received_for": ["forwarded@example.com"],
        "message_id": "<111-222-333@email.example.com>",
        "subject": "Sending this example",
        "attachments": [
          {
            "id": "2a0c9ce0-3112-4728-976e-47ddcd16a318",
            "filename": "avatar.png",
            "content_type": "image/png",
            "content_disposition": "inline",
            "content_id": "img001"
          }
        ]
      }
    }
    ```
  </Step>
</Steps>

## What can you do with Receiving emails

Once you receive an email, you can process it in a variety of ways. Here are some common actions you can take:

* [Get email content](/docs/dashboard/receiving/get-email-content)
* [Process attachments](/docs/dashboard/receiving/attachments)
* [Forward emails to another address](/docs/dashboard/receiving/forward-emails)
* [Reply to emails in the same thread](/docs/dashboard/receiving/reply-to-emails)

<Info>
  Webhooks do not include the email body, headers, or attachments, only their
  metadata. You must call the [Received emails
  API](/docs/api-reference/emails/retrieve-received-email) or the [Attachments
  API](/docs/api-reference/emails/list-received-email-attachments) to retrieve them.
  This design choice supports large attachments in serverless environments that
  have limited request body sizes.
</Info>

## FAQ

<AccordionGroup>
  <Accordion title="Will I receive emails for any address at my domain?">
    Yes. Once you add the MX record to your [custom domains](/docs/dashboard/receiving/custom-domains), you will receive emails for
    any address at that domain.

    For example, if your domain is `yourdomain.tld`, you will receive
    emails sent to `<anything>@yourdomain.tld`. You can then filter or
    route based on the `to` field in the webhook event.

    The same applies if you use the domain managed by Resend. If the domain given to you is `cool-hedgehog.resend.app`,
    you'll receive any email send to `<anything>@cool-hedgehog.resend.app`.
  </Accordion>

  <Accordion title="Can I receive emails on a subdomain?">
    Yes. You can add the MX record to any subdomain (e.g.
    `subdomain.yourdomain.tld`) and receive emails there.
  </Accordion>

  <Accordion title="Should I add the `MX` records for my root domain or a subdomain?">
    If you already have existing MX records for your root domain, we recommend
    that you create a subdomain (e.g. `subdomain.yourdomain.tld`) and add the MX
    record there. This way, you can use Resend for receiving emails without
    affecting your existing email service.

    If you still want to use the same domain both in for Resend and your day-to-day
    email service, you can also set up forwarding rules in your existing email service
    to forward emails to an address that's configured in Resend or forward them directly
    to the SMTP server address that appears in the receiving `MX` record.
  </Accordion>

  <Accordion title="Will I lose my emails if my webhook endpoint is down?">
    No, you will not lose your emails. Resend stores emails as soon as they come
    in.

    Even if your webhook endpoint is down, you can still see your emails in
    the dashboard and retrieve them using the [Receiving
    API](/docs/api-reference/emails/retrieve-received-email).

    Additionally, we will retry delivering the webhook event on the schedule
    described in our [webhooks documentation](/docs/webhooks/introduction#faq)
    and you can also replay individual webhook events from the
    [webhooks](/docs/webhooks/introduction) page in the dashboard.
  </Accordion>

  <Accordion title="How can I make sure that it's Resend who's sending me webhooks?">
    All of Resend's webhooks include a secret and headers that you can use to verify
    the authenticity of the request.

    In our SDKs, you can verify webhooks using
    `resend.webhooks.verify()`, as shown below.

    ```js theme={"theme":{"light":"github-light","dark":"vesper"}}
    // throws an error if the webhook is invalid
    // otherwise, returns the parsed payload object
    const result = resend.webhooks.verify({
      payload: JSON.stringify(req.body),
      headers: {
        id: req.headers['svix-id'],
        timestamp: req.headers['svix-timestamp'],
        signature: req.headers['svix-signature'],
      },
      webhookSecret: process.env.RESEND_WEBHOOK_SECRET,
    })
    ```

    You can find more code samples and instructions on how to verify webhooks in our
    [webhook verification documentation](/docs/webhooks/verify-webhooks-requests).
  </Accordion>
</AccordionGroup>

## Try it yourself

<CardGroup>
  <Card title="Next.js (TypeScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/inbound">
    See the full source code.
  </Card>

  <Card title="Next.js (JavaScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/inbound">
    See the full source code.
  </Card>

  <Card title="PHP" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/inbound">
    See the full source code.
  </Card>

  <Card title="Laravel" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/laravel-resend-examples">
    See the full source code.
  </Card>

  <Card title="Python" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/python-resend-examples/examples">
    See the full source code.
  </Card>

  <Card title="Ruby" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/examples">
    See the full source code.
  </Card>
</CardGroup>


# Reply to Receiving Emails
Source: https://resend.com/docs/dashboard/receiving/reply-to-emails

Reply to Receiving emails in the same thread.

Email clients thread emails by using the `message_id` metadata.

If you want to reply to an email, add the `In-Reply-To` header set to the `message_id` of the received email. To signal the threading, set the subject to start with `Re:` so that email clients can group the replies together.

## Get the message ID

The `message_id` is included in the [webhook event](/docs/webhooks/emails/received) payload when an email is received:

```json {5} theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "type": "email.received",
  "data": {
    "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
    "message_id": "<111-222-333@email.example.com>",
    "subject": "Sending this example",
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"]
  }
}
```

Use the `message_id` value from `event.data.message_id` as the `In-Reply-To` header when sending your reply.

## Send a reply in thread

Here's how you can reply in thread using each SDK:

<CodeGroup>
  ```ts Node.js {13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const messageId = event.data.message_id;

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: `Re: ${event.data.subject}`,
    html: '<p>Thanks for your email!</p>',
    headers: {
      'In-Reply-To': messageId,
    },
  });
  ```

  ```php PHP {11} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $messageId = $event['data']['message_id'];

  $data = $resend->emails->send([
      'from' => 'Acme <onboarding@resend.dev>',
      'to' => ['delivered@resend.dev'],
      'subject' => "Re: {$event['data']['subject']}",
      'html' => '<p>Thanks for your email!</p>',
      'headers' => [
          'In-Reply-To' => $messageId,
      ],
  ]);
  ```

  ```python Python {13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  message_id = event["data"]["message_id"]

  params: resend.Emails.SendParams = {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": f"Re: {event['data']['subject']}",
      "html": "<p>Thanks for your email!</p>",
      "headers": {
          "In-Reply-To": message_id,
      },
  }

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

  ```rb Ruby {13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  message_id = event["data"]["message_id"]

  params = {
      from: "Acme <onboarding@resend.dev>",
      to: ["delivered@resend.dev"],
      subject: "Re: #{event['data']['subject']}",
      html: "<p>Thanks for your email!</p>",
      headers: {
          "In-Reply-To": message_id,
      },
  }

  sent = Resend::Emails.send(params)
  ```

  ```go Go {20} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"fmt"
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
      ctx := context.TODO()
      client := resend.NewClient("re_xxxxxxxxx")

      messageId := event.Data.MessageId

      params := &resend.SendEmailRequest{
          From:    "Acme <onboarding@resend.dev>",
          To:      []string{"delivered@resend.dev"},
          Subject: fmt.Sprintf("Re: %s", event.Data.Subject),
          Html:    "<p>Thanks for your email!</p>",
          Headers: map[string]string{
              "In-Reply-To": messageId,
          },
      }

      sent, err := client.Emails.SendWithContext(ctx, params)

      if err != nil {
          panic(err)
      }
      fmt.Println(sent.Id)
  }
  ```

  ```rust Rust {17} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::CreateEmailBaseOptions;
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
      let resend = Resend::new("re_xxxxxxxxx");

      let message_id = &event.data.received.unwrap().message_id;
      let subject = format!("Re: {}", event.data.subject);

      let email = CreateEmailBaseOptions::new(
          "Acme <onboarding@resend.dev>",
          ["delivered@resend.dev"],
          &subject,
      )
      .with_html("<p>Thanks for your email!</p>")
      .with_header("In-Reply-To", message_id);

      let _email = resend.emails.send(email).await?;

      Ok(())
  }
  ```

  ```java Java {15} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          String messageId = event.getData().getMessageId();

          CreateEmailOptions params = CreateEmailOptions.builder()
                  .from("Acme <onboarding@resend.dev>")
                  .to("delivered@resend.dev")
                  .subject("Re: " + event.getData().getSubject())
                  .html("<p>Thanks for your email!</p>")
                  .headers(Map.of(
                      "In-Reply-To", messageId
                  ))
                  .build();

          CreateEmailResponse data = resend.emails().send(params);
      }
  }
  ```

  ```csharp .NET {16} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;
  using System.Collections.Generic;

  IResend resend = ResendClient.Create("re_xxxxxxxxx");

  var messageId = eventData.MessageId;

  var message = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = $"Re: {eventData.Subject}",
      HtmlBody = "<p>Thanks for your email!</p>",
      Headers = new Dictionary<string, string>()
      {
          { "In-Reply-To", messageId },
      },
  };

  var resp = await resend.EmailSendAsync(message);
  ```

  ```bash cURL {10} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Re: Sending this example",
    "html": "<p>Thanks for your email!</p>",
    "headers": {
      "In-Reply-To": "<111-222-333@email.example.com>"
    }
  }'
  ```

  ```bash CLI {6} theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails send \
    --from "Acme <onboarding@resend.dev>" \
    --to delivered@resend.dev \
    --subject "Re: Sending this example" \
    --html "<p>Thanks for your email!</p>" \
    --headers "In-Reply-To=<111-222-333@email.example.com>"
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  async fn example(
      State(state): State<Arc<AppState>>,
      Json(event): Json<resend_rs::events::EmailEvent>,
  ) -> Response {
      if matches!(
          event.r#type,
          resend_rs::events::EmailEventType::EmailReceived
      ) {
          let email = CreateEmailBaseOptions::new(
              "Acme <onboarding@resend.dev>",
              vec!["delivered@resend.dev"],
              format!("Re: {}", event.data.subject),
          )
          .with_html("<p>Thanks for your email!</p>")
          .with_header("In-Reply-To", &event.data.received.unwrap().message_id);

          let data = state.resend.emails.send(email).await.unwrap();
          Json(data).into_response()
      } else {
          Json(Empty {}).into_response()
      }
  }
  ```
</CodeGroup>

## Replying multiple times in a thread

If you're replying multiple times within the same thread, make sure to also append
the previous `message_id`s to the `References` header, separated by spaces.
This helps email clients maintain the correct threading structure.

<CodeGroup>
  ```ts Node.js {9-10} theme={"theme":{"light":"github-light","dark":"vesper"}}
  const previousReferences = ['<msg_id1@domain.com>', '<msg_id2@domain.com>'];

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: `Re: ${event.data.subject}`,
    html: '<p>Thanks for your email!</p>',
    headers: {
      'In-Reply-To': event.data.message_id,
      'References': [...previousReferences, event.data.message_id].join(' '),
    },
  });
  ```

  ```php PHP {9-10} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $previousReferences = ['<msg_id1@domain.com>', '<msg_id2@domain.com>'];

  $data = $resend->emails->send([
      'from' => 'Acme <onboarding@resend.dev>',
      'to' => ['delivered@resend.dev'],
      'subject' => "Re: {$event['data']['subject']}",
      'html' => '<p>Thanks for your email!</p>',
      'headers' => [
          'In-Reply-To' => $event['data']['message_id'],
          'References' => implode(' ', [...$previousReferences, $event['data']['message_id']]),
      ],
  ]);
  ```

  ```python Python {9-10} theme={"theme":{"light":"github-light","dark":"vesper"}}
  previous_references = ["<msg_id1@domain.com>", "<msg_id2@domain.com>"]

  params: resend.Emails.SendParams = {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": f"Re: {event['data']['subject']}",
      "html": "<p>Thanks for your email!</p>",
      "headers": {
          "In-Reply-To": event["data"]["message_id"],
          "References": " ".join([*previous_references, event["data"]["message_id"]]),
      },
  }

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

  ```rb Ruby {9-10} theme={"theme":{"light":"github-light","dark":"vesper"}}
  previous_references = ["<msg_id1@domain.com>", "<msg_id2@domain.com>"]

  params = {
      from: "Acme <onboarding@resend.dev>",
      to: ["delivered@resend.dev"],
      subject: "Re: #{event['data']['subject']}",
      html: "<p>Thanks for your email!</p>",
      headers: {
          "In-Reply-To": event["data"]["message_id"],
          "References": [*previous_references, event["data"]["message_id"]].join(" "),
      },
  }

  sent = Resend::Emails.send(params)
  ```

  ```go Go {11-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  previousReferences := []string{"<msg_id1@domain.com>", "<msg_id2@domain.com>"}

  allReferences := append(previousReferences, event.Data.MessageId)

  params := &resend.SendEmailRequest{
      From:    "Acme <onboarding@resend.dev>",
      To:      []string{"delivered@resend.dev"},
      Subject: fmt.Sprintf("Re: %s", event.Data.Subject),
      Html:    "<p>Thanks for your email!</p>",
      Headers: map[string]string{
          "In-Reply-To": event.Data.MessageId,
          "References":  strings.Join(allReferences, " "),
      },
  }

  sent, err := client.Emails.SendWithContext(ctx, params)
  ```

  ```rust Rust {13-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  let previous_references = vec!["<msg_id1@domain.com>", "<msg_id2@domain.com>"];

  let all_references = [previous_references, vec![&event.data.message_id]]
      .concat()
      .join(" ");

  let email = CreateEmailBaseOptions::new(
      "Acme <onboarding@resend.dev>",
      ["delivered@resend.dev"],
      &subject,
  )
  .with_html("<p>Thanks for your email!</p>")
  .with_header("In-Reply-To", &event.data.message_id)
  .with_header("References", &all_references);

  let _email = resend.emails.send(email).await?;
  ```

  ```java Java {12-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  List<String> previousReferences = List.of("<msg_id1@domain.com>", "<msg_id2@domain.com>");

  List<String> allReferences = new ArrayList<>(previousReferences);
  allReferences.add(event.getData().getMessageId());

  CreateEmailOptions params = CreateEmailOptions.builder()
          .from("Acme <onboarding@resend.dev>")
          .to("delivered@resend.dev")
          .subject("Re: " + event.getData().getSubject())
          .html("<p>Thanks for your email!</p>")
          .headers(Map.of(
              "In-Reply-To", event.getData().getMessageId(),
              "References", String.join(" ", allReferences)
          ))
          .build();

  CreateEmailResponse data = resend.emails().send(params);
  ```

  ```csharp .NET {12-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  var previousReferences = new List<string> { "<msg_id1@domain.com>", "<msg_id2@domain.com>" };
  previousReferences.Add(eventData.MessageId);

  var message = new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = $"Re: {eventData.Subject}",
      HtmlBody = "<p>Thanks for your email!</p>",
      Headers = new Dictionary<string, string>()
      {
          { "In-Reply-To", eventData.MessageId },
          { "References", string.Join(" ", previousReferences) },
      },
  };

  var resp = await resend.EmailSendAsync(message);
  ```

  ```bash cURL {10-11} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Re: Sending this example",
    "html": "<p>Thanks for your email!</p>",
    "headers": {
      "In-Reply-To": "<111-222-333@email.example.com>",
      "References": "<msg_id1@domain.com> <msg_id2@domain.com> <111-222-333@email.example.com>"
    }
  }'
  ```

  ```bash CLI {6-7} theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails send \
    --from "Acme <onboarding@resend.dev>" \
    --to delivered@resend.dev \
    --subject "Re: Sending this example" \
    --html "<p>Thanks for your email!</p>" \
    --headers "In-Reply-To=<111-222-333@email.example.com>" \
      "References=<msg_id1@domain.com> <msg_id2@domain.com> <111-222-333@email.example.com>"
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  let received = &event.data.received.unwrap();

  let previous_references = [
      "<msg_id1@domain.com>",
      "<msg_id2@domain.com>",
      &received.message_id,
  ];

  let email = CreateEmailBaseOptions::new(
      "Acme <onboarding@resend.dev>",
      vec!["delivered@resend.dev"],
      format!("Re: {}", event.data.subject),
  )
      .with_html("<p>Thanks for your email!</p>")
      .with_header("In-Reply-To", &received.message_id)
      .with_header("References", &previous_references.join(" "));

  let data = state.resend.emails.send(email).await.unwrap();
  ```
</CodeGroup>


# Managing Segments
Source: https://resend.com/docs/dashboard/segments/introduction

Learn how to create, retrieve, and delete segments.

Segments are used to group and manage your [Contacts](/docs/dashboard/audiences/contacts). Segments are not visible to your Contacts, but are used for your own internal Contact organization.

## Send emails to your Segment

Segments were designed to be used in conjunction with [Broadcasts](/docs/dashboard/broadcasts/introduction). You can send a Broadcast to an Segment from the Resend dashboard or from the Broadcast API.

### From Resend's no-code editor

You can send emails to your Segment by creating a new Broadcast and selecting the Segment you want to send it to.

<img alt="Send emails to your Segment" />

You can include the Unsubscribe Footer in your Broadcasts, which will be automatically replaced with the correct link for each Contact.

### From the Broadcast API

You can also use our [Broadcast API](/docs/api-reference/broadcasts/create-broadcast) to create and send a Broadcast to your Segment.

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.broadcasts.create({
    segmentId: '78261eea-8f8b-4381-83c6-79fa7120f1cf',
    from: 'Acme <onboarding@resend.dev>',
    subject: 'hello world',
    html: 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->broadcasts->create([
    'segment_id' => '78261eea-8f8b-4381-83c6-79fa7120f1cf',
    'from' => 'Acme <onboarding@resend.dev>',
    'subject' => 'hello world',
    'html' => 'Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}',
  ]);
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Broadcasts.CreateParams = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "Hello, world!",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
  }

  resend.Broadcasts.create(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "hello world",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
  }
  Resend::Broadcasts.create(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import "fmt"
  import 	"github.com/resend/resend-go/v3"

  client := resend.NewClient("re_xxxxxxxxx")

  params := &resend.CreateBroadcastRequest{
    SegmentId: "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    From:       "Acme <onboarding@resend.dev>",
    Html:       "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
    Subject:    "Hello, world!",
  }

  broadcast, _ := client.Broadcasts.Create(params)
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::CreateBroadcastOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let segment_id = "78261eea-8f8b-4381-83c6-79fa7120f1cf";
    let from = "Acme <onboarding@resend.dev>";
    let subject = "hello world";
    let html = "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}";

    let opts = CreateBroadcastOptions::new(segment_id, from, subject).with_html(html);

    let _broadcast = resend.broadcasts.create(opts).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend resend = new Resend("re_xxxxxxxxx");

  CreateBroadcastOptions params = CreateBroadcastOptions.builder()
      .segmentId("78261eea-8f8b-4381-83c6-79fa7120f1cf")
      .from("Acme <onboarding@resend.dev>")
      .subject("hello world")
      .html("Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}")
      .build();

  CreateBroadcastResponseSuccess data = resend.broadcasts().create(params);
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.BroadcastAddAsync(
      new BroadcastData()
      {
          DisplayName = "Example Broadcast",
          SegmentId = new Guid( "78261eea-8f8b-4381-83c6-79fa7120f1cf" ),
          From = "Acme <onboarding@resend.dev>",
          Subject = "Hello, world!",
          HtmlBody = "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}",
      }
  );
  Console.WriteLine( "Broadcast Id={0}", resp.Content );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/broadcasts' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
    "from": "Acme <onboarding@resend.dev>",
    "subject": "hello world",
    "html": "Hi {{{contact.first_name|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}"
  }'
  ```
</CodeGroup>

## How to customize the unsubscribe link in my Broadcast

Resend generates a unique link for each recipient and each Broadcast. You can use `{{{RESEND_UNSUBSCRIBE_URL}}}` as the link target.

<img alt="Unsubscribe Link" />

## Automatic Unsubscribes

When you send emails to your Segment, Resend will automatically handle the unsubscribe flow for you.

<img alt="Automatic Unsubscribes" />

If a Contact unsubscribes from your emails, they will be presented with a preference page.

* If you don't have any [Topics](/docs/dashboard/topics/introduction) configured, the Contact will be unsubscribed from all emails from your account.
* If you have [Topics](/docs/dashboard/topics/introduction) configured, the Contact will be presented with a preference page where they can subscribe or unsubscribe from specific types of emails (all `public` Topics will be shown).

Learn more about [managing your unsubscribe list](/docs/dashboard/audiences/managing-unsubscribe-list) or [customizing your unsubscribe page](/docs/dashboard/settings/unsubscribe-page).

<Info>
  Whenever possible, you should add a [Topic to your
  Broadcast](/docs/dashboard/topics/introduction), as this will allow your Contacts
  to unsubscribe from specific types of emails (instead of unsubscribing from
  all emails from your account). Learn more about [why and when to use
  Topics](/docs/knowledge-base/why-use-topics).
</Info>

## Export your data

Admins can download your data in CSV format for the following resources:

* Emails
* Broadcasts
* Contacts
* Segments
* Domains
* Logs
* API keys

<Info>Currently, exports are limited to admin users of your team.</Info>

To start, apply filters to your data and click on the "Export" button. Confirm your filters before exporting your data.

<video />

If your exported data includes 1,000 items or less, the export will download immediately. For larger exports, you'll receive an email with a link to download your data.

All admins on your team can securely access the export for 7 days. Unavailable exports are marked as "Expired."

<Note>
  All exports your team creates are listed in the
  [Exports](https://resend.com/exports) page under **Settings** > **Team** >
  **Exports**. Select any export to view its details page. All members of your
  team can view your exports, but only admins can download the data.
</Note>


# Migrating from Audiences to Segments
Source: https://resend.com/docs/dashboard/segments/migrating-from-audiences-to-segments

Learn how to migrate from Audiences to Segments

Contact segmentation at Resend has changed to simplify managing your contacts. Before, each Contact was part of one Audience and if you created another contact with the same email address in a different Audience, it would be a completely separate object.

In the new model, Contacts are now independent of Audiences, which are now called Segments. A Contact can be in zero, one or multiple Segments and still count as one when calculating your quota usage.

Contacts API endpoints that previously required an `audience_id` can now be used directly instead.

## What's changing

Resend now uses a **Global Contacts** model.

* **Before**: If a Contact with the same email appeared in multiple Segments, it was counted as multiple Contacts.
* **Now**: Each email address is treated as a single Contact across your team, even if it appears in multiple Segments.

The new model offers three concepts:

* **Contact**: a global entity linked to a specific email address.
* **Segment**: an internal segmentation tool for your team to organize sending.
* **Topic**: a user-facing tool for managing email preferences.

## Unsubscribing

Previously, when a contact clicked "unsubscribe," their contact status were marked was "Unsubscribed" only from the specific Audience used in that Broadcast.

From now on, contacts will see a preference page where they can:

* Unsubscribe from certain **Topics** (email's preference).
* Or unsubscribe from **everything** you send (update contact status).

## What to Do

If you've been using Audiences for both segmentation and unsubscribes, switch your unsubscribe logic to **Topics**:

1. Create a Topic for each type of email you send.
2. Assign the right users to each Topic.
3. Use Segments purely for your internal organization.

With this setup, when you send a Broadcast, your users can choose which Topics to unsubscribe from, or opt out completely.

For details on the new API endpoints view:

* [Contacts](/docs/api-reference/contacts/create-contact)
* [Topics](/docs/api-reference/topics/create-topic)
* [Segments](/docs/api-reference/segments/create-segment)

## Get more help

If you have a use case not covered here, [please reach out](https://resend.com/help) for a smooth transition.


# Managing Billing
Source: https://resend.com/docs/dashboard/settings/billing

Manage your account subscription and billing information

The [Billing](https://resend.com/settings/billing) page in the Settings section provides a clear view of your subscription details, billing email, payment method, and account invoices. From here, you can:

* View and manage your subscription - Upgrade, downgrade, or modify your current plan.
* Manage billing contacts - Ensure the right people receive billing-related notifications.
* Update payment information - Add or change your credit card or billing details.
* Add billing address - Provide your billing address for invoices.
* Add tax ID - Add your VAT number or tax ID for proper invoicing.
* Access invoices - Download past invoices for your records.

For any other billing inquiries, please [contact support](https://resend.com/help).

## How to cancel your subscription

1. Go to the [Billing](https://resend.com/settings/billing) page.
2. Click on the three dots <span><Icon icon="ellipsis" /></span> next to your plan.
3. Select **Cancel Subscription** from the dropdown menu.

<img alt="Cancel subscription" />


# Managing Teams
Source: https://resend.com/docs/dashboard/settings/team

Manage your account across multiple teams

Resend allows multiple teams to be managed under a single email address. Each team is distinct, with its own API keys, billing, and usage.

## Inviting new members to a team

1. Navigate to your [**Team Settings**](https://resend.com/settings/team).
2. Click **Invite**. Input an email address and select a role (**Admin** or **Member**).
   * **Members** have access to manage emails, domains and webhooks.
   * **Admins** have all Member permissions plus the ability to invite users, update payments, and delete the team.
3. The new member will receive an email invitation to join the team.

## Add a team avatar

1. Navigate to your [**Team Settings**](https://resend.com/settings/team).
2. Click **Upload Image** next to the avatar placeholders.
3. Upload an image file to use as the team avatar.

<video />

## Switching between teams

After accepting an invite from the account owner, users can switch between teams:

1. Click on the **team name** in the top left corner of any Resend page.
2. A dropdown menu will appear, listing all the teams you belong to.
3. Select a team to switch between them.

<img alt="image" />

## Change the team member roles

As an admin of your team, you can change the role of members in your team.

1. Navigate to your [**Team Settings**](https://resend.com/settings/team).
2. Find the user you want to change.
3. Select the more options button <span><Icon icon="ellipsis" /></span> and choose **Change role**.

<img alt="Change role popover visible for team member" />

Upon confirmation, your team member will be given the new role.

## Leave your Resend team

You can leave your team by following these steps:

1. Navigate to your [**Team Settings**](https://resend.com/settings/team).
2. Under members, click on <span><Icon icon="ellipsis" /></span> next to your name for more options.
3. Select the **Leave Team** button.

Upon confirmation, you will leave your team.

<Note>
  If you are the last member of the team, leaving will permanently delete the
  team and all its data. You will be prompted to confirm this action by typing
  **DELETE**. If the team still has other members, but you are the only admin,
  you will be prompted to promote another member to admin before leaving.
</Note>


# Custom Unsubscribe Page
Source: https://resend.com/docs/dashboard/settings/unsubscribe-page

Customize your unsubscribe page

When using Resend Broadcasts or Automations, Resend can [automatically handle the unsubscribe flow for you](/docs/dashboard/segments/introduction#automatic-unsubscribes).

You can customize your unsubscribe page to match your brand. Your unsubscribe page is used for every domain on your team.

1. Navigate to your [**Unsubscribe Page**](https://resend.com/settings/unsubscribe-page).
2. Click **Edit**.

You can customize the following:

* **Title**: The title of the unsubscribe page.
* **Description**: The description of the unsubscribe page.
* **Logo**: The logo of the unsubscribe page.
* **Background Color**: The background color of the unsubscribe page.
* **Text Color**: The text color of the unsubscribe page.
* **Accent Color**: The accent color of the unsubscribe page.

<video />

<Note>
  Pro plan users or higher can also remove the “Powered by Resend” footer.
</Note>


# Using Templates
Source: https://resend.com/docs/dashboard/templates/introduction

Learn how to use templates to send emails.

Templates are stored on Resend and can be referenced when you send transactional emails. With Templates, define the structure and layout of a message and optionally include custom variables which will be replaced with the actual values when sending the email.

Send only the Template `id` and `variables` (instead of sending the HTML), and Resend will render your final email and send it out.

<CodeGroup>
  ```ts Node.js {8-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: 'delivered@resend.dev',
    template: {
      id: 'order-confirmation',
      variables: {
        PRODUCT: 'Vintage Macintosh',
        PRICE: 499,
      },
    },
  });
  ```

  ```php PHP {7-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->send([
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'hello world',
    'template'=> [
      'id' => 'f3b9756c-f4f4-44da-bc00-9f7903c8a83f',
      'variables' => [
        'PRODUCT' => 'Vintage Macintosh',
        'PRICE' => 499,
      ]
    ]
  ]);
  ```

  ```python Python {8-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Emails.send({
    "from": "Acme <onboarding@resend.dev>",
    "to": "delivered@resend.dev",
    "template": {
      "id": "order-confirmation",
      "variables": {
        "PRODUCT": "Vintage Macintosh",
        "PRICE": 499
      }
    }
  })
  ```

  ```ruby Ruby {8-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Emails.send({
    from: "Acme <onboarding@resend.dev>",
    to: "delivered@resend.dev",
    template: {
      id: "order-confirmation",
      variables: {
        PRODUCT: "Vintage Macintosh",
        PRICE: 499
      }
    }
  })
  ```

  ```go Go {8-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import "github.com/resend/resend-go/v3"

  client := resend.NewClient("re_xxxxxxxxx")

  params := &resend.SendEmailRequest{
    From: "Acme <onboarding@resend.dev>",
    To: []string{"delivered@resend.dev"},
    Template: &resend.EmailTemplate{
      Id: "order-confirmation",
      Variables: map[string]interface{}{
        "PRODUCT": "Vintage Macintosh",
        "PRICE": 499,
      },
    },
  }

  email, err := client.Emails.Send(params)
  ```

  ```rust Rust {7-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::SendEmailOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let variables = serde_json::json!({
      "PRODUCT": "Vintage Macintosh",
      "PRICE": 499
    });

    let opts = SendEmailOptions::new("Acme <onboarding@resend.dev>", vec!["delivered@resend.dev"])
      .with_template("order-confirmation", variables);

    let _email = resend.emails.send(opts).await?;

    Ok(())
  }
  ```

  ```java Java {3-5,10-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend resend = new Resend("re_xxxxxxxxx");

  Map<String, Object> variables = new HashMap<>();
  variables.put("PRODUCT", "Vintage Macintosh");
  variables.put("PRICE", 499);

  SendEmailOptions params = SendEmailOptions.builder()
    .from("Acme <onboarding@resend.dev>")
    .to(Arrays.asList("customer@email.com"))
    .template(Template.builder()
      .id("order-confirmation")
      .variables(variables)
      .build())
    .build();

  SendEmailResponseSuccess data = resend.emails().send(params);
  ```

  ```csharp .NET {5-9,17-20} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create("re_xxxxxxxxx");

  var variables = new Dictionary<string, object>
  {
    { "PRODUCT", "Vintage Macintosh" },
    { "PRICE", 499 }
  };

  var resp = await resend.EmailSendAsync(
    new EmailMessage()
    {
      From = "Acme <onboarding@resend.dev>",
      To = new[] { "delivered@resend.dev" },
      Template = new EmailMessageTemplate()
      {
        TemplateId = new Guid( "b6d24b8e-af0b-4c3c-be0c-359bbd97381e" ),
        Variables = variables
      }
    }
  );

  Console.WriteLine($"Email Id={resp.Content}");
  ```

  ```bash cURL {7-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
    -H 'Authorization: Bearer re_xxxxxxxxx' \
    -H 'Content-Type: application/json' \
    -d $'{
      "from": "Acme <onboarding@resend.dev>",
      "to": "delivered@resend.dev",
      "template": {
        "id": "order-confirmation",
        "variables": {
          "PRODUCT": "Vintage Macintosh",
          "PRICE": 499
        }
      }
  }'
  ```
</CodeGroup>

Use Templates for transactional emails like:

* Login/Auth
* Onboarding
* Ecommerce
* Notifications
* Automations

## Add a Template

You can add a Template:

* [In the dashboard](#add-a-template-in-the-dashboard)
* [From an existing email](#add-a-template-from-an-existing-email)
* [Using the API](#create-a-template-by-using-the-api)

### Add a Template in the dashboard

The [Templates dashboard](https://resend.com/templates) shows all existing templates. Click **Create template** to start a new Template.

<img alt="Add a template" />

### Add a Template from an existing email

You can create a Template from an existing Broadcast. Locate your desired Broadcast in the [Broadcast dashboard](https://resend.com/broadcasts), click the more options button <span><Icon icon="ellipsis" /></span>, and choose **Clone as template**.

<img alt="Add a template from an existing email" />

You can also import an HTML or [React Email](https://react.email) file to create a Template from your existing code. Create a new Template, then paste or drag in your HTML or React Email content.

<Note>
  When pasting React Email code, only imports from `@react-email/components` and
  `react` are supported. Local file imports (e.g., `./components/Logo`) and
  other third-party packages are not supported in the editor.
</Note>

### Create a Template by using the API

You can also programmatically create a Template by using the API. The payload can optionally include variables to be used in the Template.

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  await resend.templates.create({
    name: 'order-confirmation',
    from: 'Resend Store <store@resend.com>',
    subject: 'Thanks for your order!',
    html: '<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>',
    variables: [
      {
        key: 'PRODUCT',
        type: 'string',
        fallbackValue: 'item',
      },
      {
        key: 'PRICE',
        type: 'number',
        fallbackValue: 20,
      },
    ],
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->templates->create([
    'name' => 'order-confirmation',
    'from' => 'Resend Store <store@resend.com>',
    'subject' => 'Thanks for your order!',
    'html' => '<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>',
    'variables' => [
      [
        'key' => 'PRODUCT',
        'type' => 'string',
        'fallback_value' => 'item'
      ],
      [
        'key' => 'PRICE',
        'type' => 'number',
        'fallback_value' => 49.99
      ]
    ]
  ]);
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Templates.CreateParams = {
      "name": "order-confirmation",
      "from": "Resend Store <store@resend.com>",
      "subject": "Thanks for your order!",
      "html": "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
      "variables": [
          {
              "key": "PRODUCT",
              "type": "string",
              "fallback_value": "item",
          },
          {
              "key": "PRICE",
              "type": "number",
              "fallback_value": 20,
          },
      ],
  }

  resend.Templates.create(params)
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Templates.create(
    name: "order-confirmation",
    from: "Resend Store <store@resend.com>",
    subject: "Thanks for your order!",
    html: "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
    variables: [
      {
        key: "PRODUCT",
        type: "string",
        fallback_value: "item"
      },
      {
        key: "PRICE",
        type: "number",
        fallback_value: 20
      }
    ]
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import "github.com/resend/resend-go/v3"

  client := resend.NewClient("re_xxxxxxxxx")

  template, err := client.Templates.Create(&resend.CreateTemplateRequest{
  	Name:    "order-confirmation",
  	From:    "Resend Store <store@resend.com>",
  	Subject: "Thanks for your order!",
  	Html:    "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
  	Variables: []*resend.TemplateVariable{
  		{
  			Key:           "PRODUCT",
  			Type:          resend.VariableTypeString,
  			FallbackValue: "item",
  		},
  		{
  			Key:           "PRICE",
  			Type:          resend.VariableTypeNumber,
  			FallbackValue: 20,
  		},
  	},
  })
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{
    types::{CreateTemplateOptions, Variable, VariableType},
    Resend, Result,
  };

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let name = "order-confirmation";
    let from = "Resend Store <store@resend.com>";
    let subject = "Thanks for your order!";
    let html = "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>";

    let variables = [
      Variable::new("PRODUCT", VariableType::String).with_fallback("item"),
      Variable::new("PRICE", VariableType::Number).with_fallback(20)
    ];

    let opts = CreateTemplateOptions::new(name, from, subject)
      .with_html(html)
      .with_variables(&variables);

    let template = resend.templates.create(opts).await?;

    let _published = resend.templates.publish(&template.id).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateTemplateOptions params = CreateTemplateOptions.builder()
                  .name("order-confirmation")
                  .from("Resend Store <store@resend.com>")
                  .subject("Thanks for your order!")
                  .html("<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>")
                  .addVariable(new Variable("PRODUCT", VariableType.STRING, "item"))
                  .addVariable(new Variable("PRICE", VariableType.NUMBER, 20))
                  .build();

          CreateTemplateResponseSuccess data = resend.templates().create(params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create("re_xxxxxxxxx");

  var variables = new List<TemplateVariable>
  {
    new TemplateVariable() {
      Key = "PRODUCT",
      Type = TemplateVariableType.String,
      Default = "item",
    },
    new TemplateVariable() {
      Key = "PRICE",
      Type = TemplateVariableType.Number,
      Default = 20,
    },
  };

  var resp = await resend.TemplateCreateAsync(
    new TemplateData()
    {
      Name = "order-confirmation",
      From = "Resend Store <store@resend.com>",
      Subject = "Thanks for your order!",
      HtmlBody = "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
      Variables = variables,
    }
  );

  Console.WriteLine($"Template Id={resp.Content}");
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/templates' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "name": "order-confirmation",
    "from": "Resend Store <store@resend.com>",
    "subject": "Thanks for your order!",
    "html": "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
    "variables": [
      {
        "key": "PRODUCT",
        "type": "string",
        "fallback_value": "item"
      },
      {
        "key": "PRICE",
        "type": "number",
        "fallback_value": 20
      }
    ]
  }'
  ```
</CodeGroup>

View the [API reference](/docs/api-reference/templates/create-template) for more details.

## Add Variables

Each Template may contain up to 20 variables.

To add a custom variable, select **Variable** in the commands palette or type `{{` in the editor. Define the `name`, `type`, and `fallback_value` (optional).

<img alt="variable dropdown" />

You can also define custom variables [via the API](/docs/dashboard/templates/template-variables).

<Info>
  The following variable names are reserved and cannot be used: `FIRST_NAME`,
  `LAST_NAME`, `EMAIL`, `RESEND_UNSUBSCRIBE_URL`, `contact`,`this`.
</Info>

[Learn more about working with variables](/docs/dashboard/templates/template-variables).

## Send Test Emails

You can send test emails to your inbox to preview your Template before sending it to your audience. Provide variable values to test the rendered Template in your inbox.

<video />

## Publish a Template

By default, Templates are in a **draft** state. To use a Template to send emails, you must first **publish** it via the dashboard or [via the API](/docs/api-reference/templates/publish-template).

<img alt="Publish a template" />

For a more streamlined flow, create and publish a template in a single step.

```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
await resend.templates.create({ ... }).publish();
```

Once a Template is published, you can continue to edit it without impacting existing emails sent using the Template. As you work, your changes are saved as a draft, although you can also manually save drafts by pressing <kbd>Cmd</kbd> + <kbd>S</kbd> (Mac) or <kbd>Ctrl</kbd> + <kbd>S</kbd> (Windows).

Only after publishing again will the changes be reflected in emails using the Template.

[Learn more about Template version history](/docs/dashboard/templates/version-history).

## Send Emails with Templates

When sending a transactional email, you can reference your Template and include your variables in the call. The Template variables will be replaced with the actual values.

<CodeGroup>
  ```ts Node.js {8-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: 'delivered@resend.dev',
    template: {
      id: 'order-confirmation',
      variables: {
        PRODUCT: 'Vintage Macintosh',
        PRICE: 499,
      },
    },
  });
  ```

  ```php PHP {7-12} theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->send([
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'hello world',
    'template'=> [
      'id' => 'f3b9756c-f4f4-44da-bc00-9f7903c8a83f',
      'variables' => [
        'PRODUCT' => 'Vintage Macintosh',
        'PRICE' => 499,
      ]
    ]
  ]);
  ```

  ```python Python {8-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Emails.send({
    "from": "Acme <onboarding@resend.dev>",
    "to": "delivered@resend.dev",
    "template": {
      "id": "order-confirmation",
      "variables": {
        "PRODUCT": "Vintage Macintosh",
        "PRICE": 499
      }
    }
  })
  ```

  ```ruby Ruby {8-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Emails.send({
    from: "Acme <onboarding@resend.dev>",
    to: "delivered@resend.dev",
    template: {
      id: "order-confirmation",
      variables: {
        PRODUCT: "Vintage Macintosh",
        PRICE: 499
      }
    }
  })
  ```

  ```go Go {8-14} theme={"theme":{"light":"github-light","dark":"vesper"}}
  import "github.com/resend/resend-go/v3"

  client := resend.NewClient("re_xxxxxxxxx")

  params := &resend.SendEmailRequest{
    From: "Acme <onboarding@resend.dev>",
    To: []string{"delivered@resend.dev"},
    Template: &resend.EmailTemplate{
      Id: "order-confirmation",
      Variables: map[string]interface{}{
        "PRODUCT": "Vintage Macintosh",
        "PRICE": 499,
      },
    },
  }

  email, err := client.Emails.Send(params)
  ```

  ```rust Rust {7-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::SendEmailOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let variables = serde_json::json!({
      "PRODUCT": "Vintage Macintosh",
      "PRICE": 499
    });

    let opts = SendEmailOptions::new("Acme <onboarding@resend.dev>", vec!["delivered@resend.dev"])
      .with_template("order-confirmation", variables);

    let _email = resend.emails.send(opts).await?;

    Ok(())
  }
  ```

  ```java Java {3-5,10-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend resend = new Resend("re_xxxxxxxxx");

  Map<String, Object> variables = new HashMap<>();
  variables.put("PRODUCT", "Vintage Macintosh");
  variables.put("PRICE", 499);

  SendEmailOptions params = SendEmailOptions.builder()
    .from("Acme <onboarding@resend.dev>")
    .to(Arrays.asList("customer@email.com"))
    .template(Template.builder()
      .id("order-confirmation")
      .variables(variables)
      .build())
    .build();

  SendEmailResponseSuccess data = resend.emails().send(params);
  ```

  ```csharp .NET {5-9,17-20} theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create("re_xxxxxxxxx");

  var variables = new Dictionary<string, object>
  {
    { "PRODUCT", "Vintage Macintosh" },
    { "PRICE", 499 }
  };

  var resp = await resend.EmailSendAsync(
    new EmailMessage()
    {
      From = "Acme <onboarding@resend.dev>",
      To = new[] { "delivered@resend.dev" },
      Template = new EmailMessageTemplate()
      {
        TemplateId = new Guid( "b6d24b8e-af0b-4c3c-be0c-359bbd97381e" ),
        Variables = variables,
      }
    }
  );

  Console.WriteLine($"Email Id={resp.Content}");
  ```

  ```bash cURL {7-13} theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
    -H 'Authorization: Bearer re_xxxxxxxxx' \
    -H 'Content-Type: application/json' \
    -d $'{
      "from": "Acme <onboarding@resend.dev>",
      "to": "delivered@resend.dev",
      "template": {
        "id": "order-confirmation",
        "variables": {
          "PRODUCT": "Vintage Macintosh",
          "PRICE": 499
        }
      }
  }'
  ```
</CodeGroup>

Learn more about [sending emails](/docs/api-reference/emails/send-email) or sending [batch emails](/docs/api-reference/emails/send-batch-emails) with Templates via the API.

## Duplicate a Template

You can also duplicate an existing Template in the dashboard or [via the API](/docs/api-reference/templates/duplicate-template).

<img alt="Duplicate a template" />

<Info>
  <p>
    You can create a Template from an existing Broadcast. Locate your desired
    Broadcast in the [Broadcast dashboard](https://resend.com/broadcasts), click
    the more options button

    <span>
      <Icon icon="ellipsis" />
    </span>

    , and choose **Clone as template**.
  </p>
</Info>

## Delete a Template

You can delete a Template via the dashboard by clicking on the **Delete** button or [via the API](/docs/api-reference/templates/delete-template).

<img alt="Delete a template" />

## Validation errors

When sending an email using a Template, the Template variables will be replaced with the actual values. If a variable is not provided, the fallback value will be used. If no fallback value is provided, the email will not be sent and a validation error will be returned.

[See the API reference for more details](/docs/api-reference/templates/create-template) or the [errors reference](/docs/api-reference/errors).


# Working with Variables
Source: https://resend.com/docs/dashboard/templates/template-variables

How to work with custom variables in Templates.

Custom Template variables provide your team flexibility when sending emails. Define custom variables for your Template with optional fallback values which will be replaced with the actual values when sending the email.

## Create custom variables

Each Template may contain up to 50 variables.

To add a custom variable, select **Variable** in the commands palette or type `{{` in the editor. Define the `name`, `type`, and `fallback_value` (optional).

<img alt="variable dropdown" />

<p>
  You can also define custom variables via the API. The payload can optionally
  include variables to be used in the Template.
</p>

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  await resend.templates.create({
    name: 'order-confirmation',
    html: '<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>',
    variables: [
      {
        key: 'PRODUCT',
        type: 'string',
        fallbackValue: 'item',
      },
      {
        key: 'PRICE',
        type: 'number',
        fallbackValue: 25,
      },
    ],
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->templates->create([
    'name' => 'order-confirmation',
    'html' => '<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>',
    'variables' => [
      [
        'key' => 'PRODUCT',
        'type' => 'string',
        'fallback_value' => 'item',
      ],
      [
        'key' => 'PRICE',
        'type' => 'number',
        'fallback_value' => 25,
      ]
    ],
  ]);
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  resend.Templates.create({
      "name": "order-confirmation",
      "html": "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
      "variables": [
          {
              "key": "PRODUCT",
              "type": "string",
              "fallback_value": "item",
          },
          {
              "key": "PRICE",
              "type": "number",
              "fallback_value": 25,
          }
      ],
  })
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  Resend::Templates.create(
    name: "order-confirmation",
    html: "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
    variables: [
      {
        key: "PRODUCT",
        type: "string",
        fallback_value: "item"
      },
      {
        key: "PRICE",
        type: "number",
        fallback_value: 25
      }
    ]
  )
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	template, err := client.Templates.CreateWithContext(context.TODO(), &resend.CreateTemplateRequest{
  		Name: "order-confirmation",
  		Html: "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
  		Variables: []*resend.TemplateVariable{
  			{
  				Key:           "PRODUCT",
  				Type:          resend.VariableTypeString,
  				FallbackValue: "item",
  			},
  			{
  				Key:           "PRICE",
  				Type:          resend.VariableTypeNumber,
  				FallbackValue: 25,
  			}
  		},
  	})
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{
    types::{CreateTemplateOptions, Variable, VariableType},
    Resend, Result,
  };

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let name = "order-confirmation";
    let html = "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>";

    let variables = [
      Variable::new("PRODUCT", VariableType::String).with_fallback("item"),
      Variable::new("PRICE", VariableType::Number).with_fallback(25)
    ];

    let opts = CreateTemplateOptions::new(name, html).with_variables(&variables);
    let template = resend.templates.create(opts).await?;

    let _published = resend.templates.publish(&template.id).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateTemplateOptions params = CreateTemplateOptions.builder()
                  .name("order-confirmation")
                  .html("<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>")
                  .addVariable(new Variable("PRODUCT", VariableType.STRING, "item"))
                  .addVariable(new Variable("PRICE", VariableType.NUMBER, 25))
                  .build();

          CreateTemplateResponseSuccess data = resend.templates().create(params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create("re_xxxxxxxxx");

  var variables = new List<TemplateVariable>()
  {
    new TemplateVariable() {
      Key = "PRODUCT",
      Type = TemplateVariableType.String,
      Default = "item",
    },
    new TemplateVariable() {
      Key = "PRICE",
      Type = TemplateVariableType.Number,
      Default = 25,
    }
  };

  var resp = await resend.TemplateCreateAsync(
    new TemplateData()
    {
      Name = "welcome-email",
      HtmlBody = "<strong>Hey, {{{PRODUCT}}}, you are {{{PRICE}}} years old.</strong>",
      Variables = variables,
    }
  );

  Console.WriteLine($"Template Id={resp.Content}");
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/templates' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "name": "order-confirmation",
    "html": "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
    "variables": [
      {
        "key": "PRODUCT",
        "type": "string",
        "fallback_value": "item"
      },
      {
        "key": "PRICE",
        "type": "number",
        "fallback_value": 25
      }
    ]
  }'
  ```
</CodeGroup>

<Info>
  The following variable names are reserved and cannot be used: `FIRST_NAME`,
  `LAST_NAME`, `EMAIL`, `UNSUBSCRIBE_URL`, `contact`,`this`.
</Info>

Each variable is an object with the following properties:

* `key`: The key of the variable, commonly uppercase (e.g., `PRODUCT_NAME`).
* `type`: The type of the variable (`'string'` or `'number'`).
* `fallback_value`: The fallback value of the variable. If no fallback value is provided, you must provide a value for the variable when sending an email using the template.

[See the API reference for more details](/docs/api-reference/templates/create-template).

## Fallback values

When you define a variable, you can optionally define a fallback value. This value will be used when sending the email if you fail to provide a value in your call.

<video />

In the editor, if you fail to provide a fallback value, a warning sign will show for the variable. To edit a variable's fallback value, click on the variable chip in your template and use the Inspector sidebar on the right to update the fallback value.

[As shown above](#create-custom-variables), you can also include fallback values when creating a Template via the API.

## Send Test Emails

You can send test emails to your inbox to preview your Template before sending it to your audience. Provide variable values to test the rendered Template in your inbox.

<video />

## Send a Template with Variables

When sending a transactional email, you can reference your Template and include your variables in the call. The Template variables will be replaced with the actual values.

* `id`: id of the published template
* `variables`: array of variable objects (if applicable)

Both the `/emails` and `/emails/batch` endpoints support Templates.

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'hello world',
    template: {
      id: 'f3b9756c-f4f4-44da-bc00-9f7903c8a83f',
      variables: {
        PRODUCT: 'Laptop',
      },
    },
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->send([
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'hello world',
    'template'=> [
      'id' => 'f3b9756c-f4f4-44da-bc00-9f7903c8a83f',
      'variables' => [
        'PRODUCT' => 'Laptop'
      ]
    ]
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Emails.SendParams = {
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "hello world",
      "template": {
          "id": "f3b9756c-f4f4-44da-bc00-9f7903c8a83f",
          "variables": {
              "PRODUCT": "Laptop",
          },
      },
  }

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

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require 'resend'

  Resend.api_key = 're_xxxxxxxxx'

  params = {
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'hello world',
    template: {
      id: 'f3b9756c-f4f4-44da-bc00-9f7903c8a83f',
      variables: {
        'PRODUCT': 'Laptop'
      }
    }
  }

  email = Resend::Emails.send(params)
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import (
  	"context"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
  	client := resend.NewClient("re_xxxxxxxxx")

  	params := &resend.SendEmailRequest{
  		From:    "Acme <onboarding@resend.dev>",
  		To:      []string{"delivered@resend.dev"},
  		Subject: "hello world",
  		Template: &resend.EmailTemplate{
  			ID: "f3b9756c-f4f4-44da-bc00-9f7903c8a83f",
  			Variables: map[string]interface{}{
  				"PRODUCT": "Laptop",
  			},
  		},
  	}

  	sent, err := client.Emails.SendWithContext(context.TODO(), params)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::CreateEmailBaseOptions, Resend, Result};
  use std::collections::HashMap;

  #[tokio::main]
  async fn main() -> Result<()> {
  	let resend = Resend::new("re_xxxxxxxxx");

  	let from = "Acme <onboarding@resend.dev>";
  	let to = ["delivered@resend.dev"];
  	let subject = "hello world";

  	let mut variables = HashMap::new();
  	variables.insert("PRODUCT".to_string(), "Laptop".to_string());

  	let email = CreateEmailBaseOptions::new(from, to, subject)
  		.with_template("f3b9756c-f4f4-44da-bc00-9f7903c8a83f", variables);

  	let _email = resend.emails.send(email).await?;

  	Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;
  import java.util.HashMap;
  import java.util.Map;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          Map<String, Object> variables = new HashMap<>();
          variables.put("PRODUCT", "Laptop");

          CreateEmailOptions params = CreateEmailOptions.builder()
                  .from("Acme <onboarding@resend.dev>")
                  .to("delivered@resend.dev")
                  .subject("hello world")
                  .template("f3b9756c-f4f4-44da-bc00-9f7903c8a83f", variables)
                  .build();

          CreateEmailResponse data = resend.emails().send(params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.EmailSendAsync( new EmailMessage()
  {
      From = "Acme <onboarding@resend.dev>",
      To = "delivered@resend.dev",
      Subject = "hello world",
      Template = new EmailMessageTemplate() {
        TemplateId = new Guid( "f3b9756c-f4f4-44da-bc00-9f7903c8a83f" ),
        Variables = new Dictionary<string, object>()
        {
          { "PRODUCT", "Laptop" },
          { "PRICE", 1.23 }
        }
      }
  } );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "hello world",
    "template": {
      "id": "f3b9756c-f4f4-44da-bc00-9f7903c8a83f",
      "variables": {
        "PRODUCT": "Laptop"
      }
    }
  }'
  ```
</CodeGroup>

<Info>
  If a `template` is provided, you cannot send `html`, `text`, or `react` in the payload, otherwise the API will return a validation error.

  When sending a template, the payload for `from`, `subject`, and `reply_to` take precedence over the template's defaults for these fields. If the template does not provide a default value for these fields, you must provide them in the payload.
</Info>

Learn more about [sending emails](/docs/api-reference/emails/send-email) or sending [batch emails](/docs/api-reference/emails/send-batch-emails) with Templates via the API.


# Version History
Source: https://resend.com/docs/dashboard/templates/version-history

Best practices for using templates in production environments.

Templates in production require a workflow that lets you make changes safely without disrupting active emails. As you build your Template, your entire team can collaborate on the content and design in real-time with full version history.

## Draft vs Published

Templates start in a **draft** state and must be published before they can be used to send emails.

This separation allows you to:

* Test templates thoroughly before going live
* Make changes without affecting active emails
* Maintain version control over your email content

Once you **publish** a template, this published version will be used to send emails until you publish again. You can continue to work on a template in draft state without affecting the published version and the editor will automaticalyl save your progress.

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  // Create template
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  await resend.templates.create({
    name: 'order-confirmation',
    from: 'Resend Store <store@resend.com>',
    subject: 'Thanks for your order!',
    html: "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
    variables: [
      {
        key: 'PRODUCT',
        type: 'string',
        fallbackValue: 'item'
      },
      {
        key: 'PRICE',
        type: 'number',
        fallbackValue: 20
      }
    ]
  });

  // Publish template
  await resend.templates.publish('template_id');

  // Or create and publish a template in one step
  await resend.templates.create({ ... }).publish();
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  // Create template
  $resend->templates->create([
    'name' => 'order-confirmation',
    'from' => 'Resend Store <store@resend.com>',
    'subject' => 'Thanks for your order!',
      'html' => "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
    'variables' => [
      [
        'key' => 'PRODUCT',
        'type' => 'string',
        'fallbackValue' => 'item'
      ],
      [
        'key' => 'PRICE',
        'type' => 'number',
        'fallbackValue' => 49.99
      ]
    ]
  ]);

  // Publish template
  $resend->templates->publish('template_id');
  ```

  ```py Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  // Create template
  params: resend.Templates.CreateParams = {
    "name": "order-confirmation",
    "from": "Resend Store <store@resend.com>",
    "subject": "Thanks for your order!",
    "html": "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
    "variables": [
      {
        "key": "PRODUCT",
        "type": "string",
        "fallbackValue": "item"
      },
      {
        "key": "PRICE",
        "type": "number",
        "fallbackValue": 20
      },
    ]
  }

  resend.Templates.create(params)

  // Publish template
  resend.Templates.publish('template_id');
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  // Create template
  params = {
    "name": 'order-confirmation',
    "from": 'Resend Store <store@resend.com>',
    "subject": 'Thanks for your order!',
    "html": "<p>Name: #{{{PRODUCT}}}</p><p>Total: #{{{PRICE}}}</p>",
    "variables": [{
        "key": 'PRODUCT',
        "type": 'string',
        "fallbackValue": 'item'
      },
      {
        "key": 'PRICE',
        "type": 'number',
        "fallbackValue": 20
      }
    ]
  }

  Resend::Templates.create(params)

  // Publish template
  Resend::Templates.publish('template_id');
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  import "github.com/resend/resend-go/v2"

  client := resend.NewClient("re_xxxxxxxxx")

  // Create template
  params := &resend.CreateTemplateRequest{
    Name: "order-confirmation",
    From: "Resend Store <store@resend.com>",
    Subject: "Thanks for your order!",
    Html: "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
    Variables: []resend.TemplateVariable{
      {
        Key: "PRODUCT",
        Type: "string",
        FallbackValue: "item",
      },
      {
        Key: "PRICE",
        Type: "number",
        FallbackValue: 20,
      },
    },
  }

  template, _ := client.Templates.Create(params)

  // Publish template
  client.Templates.Publish(template.Id)
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::{types::CreateTemplateOptions, Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    // Create template
    let name = "order-confirmation";
    let from = "Resend Store <store@resend.com>";
    let subject = "Thanks for your order!";
    let html = "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>";

    let variables = vec![
      TemplateVariable {
        key: "PRODUCT",
        type_: "string",
        fallback_value: Some("item"),
      },
      TemplateVariable {
        key: "PRICE",
        type_: "number",
        fallback_value: Some(20),
      },
    ];

    let opts = CreateTemplateOptions::new(name, from, subject)
      .with_html(html)
      .with_variables(variables);

    let _template = resend.templates.create(opts).await?;

    // Publish template
    resend.templates.publish(&template.id).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  Resend resend = new Resend("re_xxxxxxxxx");

  // Create template
  List<TemplateVariable> variables = Arrays.asList(
    new TemplateVariable("PRODUCT", "string", "item"),
    new TemplateVariable("PRICE", "number", 20),
  );

  CreateTemplateOptions params = CreateTemplateOptions.builder()
    .name("order-confirmation")
    .from("Resend Store <store@resend.com>")
    .subject("Thanks for your order!")
      .html("<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>")
    .variables(variables)
    .build();

  CreateTemplateResponseSuccess data = resend.templates().create(params);

  // Publish template
  resend.templates().publish(data.content);
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create("re_xxxxxxxxx");

  // Create template
  var variables = new List<TemplateVariable>
  {
    new TemplateVariable() {
      Key = "PRODUCT",
      Type = TemplateVariableType.String,
      Default = "item",
    },
    new TemplateVariable() {
      Key = "PRICE",
      Type = TemplateVariableType.Number,
      Default = 20,
    },
  };

  var resp = await resend.TemplateCreateAsync(
    new TemplateData()
    {
      Name = "order-confirmation",
      From = "Resend Store <store@resend.com>",
      Subject = "Thanks for your order!",
      HtmlBody = @"
        <p>Name: {{{PRODUCT}}}</p>
        <p>Total: {{{PRICE}}}</p>
      ",
      Variables = variables,
    }
  );

  // Publish template
  await resend.TemplatePublishAsync(resp.Content);

  Console.WriteLine($"Template Id={resp.Content}");
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  # Create template
  curl -X POST 'https://api.resend.com/templates' \
   -H 'Authorization: Bearer re_xxxxxxxxx' \
   -H 'Content-Type: application/json' \
   -d $'{
    "name": "order-confirmation",
    "from": "Resend Store <store@resend.com>",
    "subject": "Thanks for your order!",
    "html": "<p>Name: {{{PRODUCT}}}</p><p>Total: {{{PRICE}}}</p>",
    "variables": [
      {
        "key": "PRODUCT",
        "type": "string",
        "fallbackValue": "item"
      },
      {
        "key": "PRICE",
        "type": "number",
        "fallbackValue": 20
      }
    ]
  }'

  # Publish template
  curl -X POST 'https://api.resend.com/templates/{template_id}/publish' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json'
  ```
</CodeGroup>

After you publish a template, you can freely work on it through the editor or [via the API](/docs/api-reference/templates/update-template) without affecting the published version. This allows you to test and validate new edits before sending them to users.

## Version History

As you work on a Template, your changes are saved as a draft, although you can also manually save drafts by pressing <kbd>Cmd</kbd> + <kbd>S</kbd> (Mac) or <kbd>Ctrl</kbd> + <kbd>S</kbd> (Windows). Only after publishing again will the changes be reflected in emails using the Template.

Each template contains a version history that helps you track changes your team has made over time. You can view the version history by clicking the three dots in the top right corner of the template editor and selecting **Version History**.

Through the version history, you can preview each version, who made them, and when they were made. You can also revert to a previous version if needed.

<video />

Reverting creates a new draft based on the selected version's content, without affecting the published template.

## Iterating on a template

You can work on a new draft version of your published template, update the design and messaging, then test it thoroughly before publishing it again. Your email sending will continue to use the current published version until you're ready to make the switch, without the need to create a new separate template or risk leaking your new logo.

This behavior is also useful to avoid breaking changes when you need to edit a template that's in production. Add or remove variables, update the design, and more without affecting your existing emails or raising validation errors.


# Topics
Source: https://resend.com/docs/dashboard/topics/introduction

Give your users more control over their subscription preferences.

Managing subscribers and unsubscribers is a critical part of any email implementation. Topics are used by your contacts to manage their email preferences.

When you send [Broadcasts](/docs/dashboard/broadcasts/introduction), you can optionally scope sending to a particular Topic. Not only does scoping your sending help you send more precisely, but it also allows your users to manage their preferences with more control.

<Tip>
  New to Topics? Learn [why and when to use
  them](/docs/knowledge-base/why-use-topics), including how they improve
  deliverability and differ from Segments.
</Tip>

## Add a Topic

You can create a new Topic from the [dashboard](https://resend.com/audience/topics) or [via the API](/docs/api-reference/topics/create-topic).

1. Click **Create Topic**.
2. Give your Topic a name.
3. Give your Topic a description (optional).
4. Select **Opt-in** or **Opt-out** as the default subscription. This value **cannot** be changed later.
   * **Opt-in**: all Contacts will receive the email unless they have explicitly unsubscribed from that Topic.
   * **Opt-out**: subscribers will not receive the email unless they have explicitly subscribed to that Topic.
5. Select **Public** or **Private** as the visibility.
   * **Private**: only Contacts who are opted in to the Topic can see it on the unsubscribe page.
   * **Public**: all Contacts can see the Topic on the unsubscribe page.

<img alt="Add Topic" />

## View all Topics

The [dashboard](https://resend.com/audience/topics) shows you all the Topics you have created along with their details.

<img alt="View All Topics" />

You can also [retrieve a single Topic](/docs/api-reference/topics/get-topic) or [list all your Topics](/docs/api-reference/topics/list-topics) via the API.

## Edit Topic details

After creating a Topic, you can edit the following details:

* Name
* Description
* Visibility

To edit a Topic, click the **More options** <Icon icon="ellipsis" /> button and then **Edit Topic**.

<img alt="View edit topic" />

You can also [update a Topic](/docs/api-reference/topics/update-topic) via the API.

<Info>
  You cannot edit the default subscription value after it has been created.
</Info>

## Delete a Topic

You can delete a Topic by clicking the **More options** <Icon icon="ellipsis" /> button and then **Remove Topic**.

<img alt="Delete Topic" />

You can also [delete a Topic](/docs/api-reference/topics/delete-topic) via the API.

## Editing Topics for a Contact

As you receive [proper consent to email Contacts](/docs/knowledge-base/what-counts-as-email-consent), add the Contact to a given Topic. A Contact can belong to multiple Topics.

You can add a Contact to a Topic via the dashboard by expanding the **More options** <Icon icon="ellipsis" /> and then **Edit Contact**. Add or remove Topics for a given Contact.

<img alt="Add Contact to Topic" />

<Note>
  The **Subscribed** status is a global setting that enables or disables sending to a Contact for Broadcasts.

  * If a Contact's **Subscribed** status is
    **false**, they will not receive emails from your account, even if they have
    opted-in to a specific Topic.

  * If the **Subscribed** status is **true**, they
    can receive emails from your account.

  Learn more about [managing your unsubscribe list](/docs/dashboard/audiences/managing-unsubscribe-list).
</Note>

## Sending Broadcast with a Topic

You can send with a Topic in the Broadcast editor from the Topics dropdown menu.

<img alt="Send emails with a Topic" />

You can also send with a Topic via the [Broadcast API](/docs/api-reference/broadcasts/create-broadcast).

## Unsubscribing from a Topic

If a Contact clicks a Broadcast unsubscribe link, they will see a preference page where they can:

* Unsubscribe from certain **Topics** (types of email)
* Or unsubscribe from **everything** you send

If they unsubscribe from a Topic or several Topics, they will no longer receive emails for those Topics. If they unsubscribe from all emails from your account, Broadcasts will no longer send to them.

You can [customize your unsubscribe page with your branding](/docs/dashboard/settings/unsubscribe-page) from your team settings.

<img alt="See Topics on the Unsubscribe Page" />


# How to Store Webhooks Data
Source: https://resend.com/docs/dashboard/webhooks/how-to-store-webhooks-data

Storing your email event data matters. Learn how to set up your own data storage.

When you send emails with Resend, you can receive real-time notifications for each message:

* Was it delivered?
* Did the recipient open it?
* Did they click a link?
* Did it bounce?

These events contain valuable data, however, by default webhooks are ephemeral. To make the data persistent, you can store the data in your own datasource.

This guide explains [why storing your webhook data matters](#why-store-webhook-data) and [how to get started](#how-to-store-webhook-data).

## Why Store Webhook Data

Storing your own data offers several benefits.

### Meet Compliance Requirements

Many industries have regulations around data retention and audit trails:

* **GDPR** - You may need to demonstrate what communications were sent to users and when
* **SOC 2** - Audit requirements may include email delivery verification
* **Financial regulations** - Transaction-related emails may need to be retained for years

Storing your own webhook data gives you full control over retention periods and access controls.

### Enable Long-term Retention

Resend retains email data for 30 days across all plans (with flexible retention for Enterprise). If you need access to historical email data beyond that window, storing events in your own database ensures you never lose important information.

### Power Automated Workflows

With webhook data in your database, you can build powerful automations:

* Automatically suppress bounced addresses from future sends
* Trigger follow-up emails based on open/click behavior
* Alert your team when delivery issues spike
* Re-engage users who haven't opened recent emails

## How to Store Webhook Data

While you can always [build your own webhook handler](/docs/webhooks/introduction), it requires development resources.

You can get started quickly with the [Resend Webhook Ingester](/docs/webhooks/ingester). It's an open-source, ready-to-deploy solution that handles all the complexity for you:

* **One-click deployment** to Vercel, Railway, or Render
* **Signature verification** built-in using Svix
* **Idempotent storage** that handles duplicate deliveries
* **8 database connectors** including PostgreSQL, MySQL, MongoDB, and data warehouses

<Card title="Webhook Ingester" icon="database" href="/webhooks/ingester">
  Deploy a production-ready webhook storage solution in minutes
</Card>

## Data Storage Considerations

Whether using the Webhook Ingester or your own handler, you'll need to consider the following:

### Choosing a Database

The right database depends on your use case:

| Use Case                   | Recommended Database                                                                                     |
| -------------------------- | -------------------------------------------------------------------------------------------------------- |
| Already using Postgres     | [PostgreSQL](https://www.postgresql.org/) or [Supabase](https://supabase.com/)                           |
| Need simple setup          | [Supabase](https://supabase.com/) or [Neon](https://neon.com/)                                           |
| High-volume analytics      | [ClickHouse](https://clickhouse.com/) or [BigQuery](https://cloud.google.com/bigquery)                   |
| Data warehouse integration | [Snowflake](https://www.snowflake.com/) or [BigQuery](https://cloud.google.com/bigquery)                 |
| Serverless architecture    | [Neon](https://neon.com/), [PlanetScale](https://planetscale.com/), or [Supabase](https://supabase.com/) |

<Tip>
  If you're unsure, start with [Supabase](https://supabase.com/) which has a
  generous free tier.
</Tip>

### What Data to Store

At minimum, store these fields for each webhook event:

* **Event ID** - The unique `svix-id` for deduplication
* **Event type** - What happened (for example, delivered, bounced, or opened)
* **Timestamp** - When the event occurred
* **Email ID** - Links the event back to the original send

For deeper analytics, also consider storing:

* **Recipient addresses** - For per-user engagement tracking
* **Subject lines** - To analyze performance by content
* **Tags** - If you use tags to categorize emails
* **Bounce details** - To understand delivery issues
* **Click URLs** - To track which links perform best

<Info>
  The Webhook Ingester stores all available fields automatically, so you don't
  have to decide upfront what you might need later.
</Info>

## Data Retention Considerations

Before storing webhook data, consider your retention requirements:

### How Long to Keep Data

* **Operational use** - 30–90 days is often sufficient for debugging and recent analytics
* **Compliance requirements** - Check your industry regulations (often 1–7 years)
* **Historical analysis** - Consider aggregating old data rather than keeping raw events

### Privacy Considerations

Webhook data may contain personal information (email addresses, IP addresses from opens/clicks). Ensure your storage approach complies with privacy regulations:

* Implement appropriate access controls
* Consider data anonymization for long-term retention
* Have a process for handling data deletion requests

### Storage Costs

High-volume senders can generate significant data. Plan for:

* Database storage costs
* Query performance as data grows
* Archival strategies for old data

<Tip>
  Most databases support partitioning by date, making it easy to drop old
  partitions when data ages out of your retention window.
</Tip>

## FAQ

<AccordionGroup>
  <Accordion title="How much data will I generate?">
    Each email can generate multiple events (sent, delivered, opened, clicked).
    A rough estimate: if you send 10,000 emails/month with average engagement,
    expect 30,000-50,000 events/month. Each event is typically 1-2 KB, so about
    50-100 MB/month of raw data.
  </Accordion>

  <Accordion title="Will storing webhooks slow down my application?">
    No. Webhook processing happens asynchronously. Your email sending is not
    affected by how you handle webhooks. If you use the Webhook Ingester, it
    runs as a separate service.
  </Accordion>

  <Accordion title="What if I miss a webhook?">
    Resend automatically retries failed webhook deliveries for up to 24 hours.
    If your endpoint returns a 5xx error, we'll retry. If you need to recover
    older events, check the [Resend Dashboard](https://resend.com/webhooks)
    where you can manually replay recent events.
  </Accordion>

  <Accordion title="Can I store webhooks in multiple databases?">
    The Webhook Ingester supports one database per deployment. If you need to
    store in multiple databases, you can either deploy multiple instances or
    build a custom handler that writes to multiple destinations.
  </Accordion>
</AccordionGroup>

## Learn More

<CardGroup>
  <Card title="Webhook Ingester" icon="database" href="/webhooks/ingester">
    Deploy a production-ready webhook storage solution
  </Card>

  <Card title="Webhook Event Types" icon="list" href="/webhooks/event-types">
    See all available event types and their payloads
  </Card>

  <Card title="Verify Webhooks" icon="shield-check" href="/webhooks/verify-webhooks-requests">
    Learn about webhook signature verification
  </Card>

  <Card title="Webhook Introduction" icon="webhook" href="/webhooks/introduction">
    Get started with webhooks in your application
  </Card>
</CardGroup>


# DMARC Analyzer
Source: https://resend.com/docs/dmarc-analyzer

Analyze DMARC XML reports with a free, open-source tool built by Resend.

[DMARC Analyzer](https://github.com/resend/resend-dmarc-analyzer) is an open-source tool built by Resend that parses DMARC XML reports and turns them into human-readable dashboards. You can use it directly in your browser or deploy your own instance to receive automated email digests.

## What is DMARC?

DMARC (Domain-based Message Authentication, Reporting, and Conformance) is an email authentication protocol that builds on [SPF and DKIM](/docs/dashboard/domains/introduction). It lets domain owners specify how unauthenticated emails are handled and receive reports about authentication results.

When you [set up a DMARC policy](/docs/dashboard/domains/dmarc), mailbox providers send XML reports to the address you specify. These reports contain valuable data about who is sending email on behalf of your domain and whether those emails pass authentication, but the raw XML is difficult to read. The DMARC Analyzer helps you visualize these reports in a human-readable format.

## Features

* Parse and visualize DMARC XML reports instantly
* View SPF and DKIM alignment results per source
* Identify unauthorized senders using your domain
* Self-host with automated report ingestion via [Resend Receiving](/docs/dashboard/receiving/introduction)
* Receive email digests summarizing your DMARC reports

<Info>
  For more details on understanding DMARC reports, see our [guide on how to read
  a DMARC report](https://resend.com/blog/how-to-read-a-dmarc-report).
</Info>

## How to use

### Web interface

The quickest way to get started, with no setup required.

1. Go to [checkdmarc.email](https://checkdmarc.email/)
2. Paste your DMARC XML report (or upload the XML file)
3. View the parsed results instantly

<video />

### Self-hosted with automated reports

For ongoing monitoring, deploy your own instance. This connects to Resend Receiving webhooks so DMARC reports sent to your domain are automatically ingested and analyzed, with email digests delivered via Resend.

## Getting started (self-hosted)

<Steps>
  <Step title="Clone the repository">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    git clone https://github.com/resend/resend-dmarc-analyzer.git
    cd resend-dmarc-analyzer
    ```
  </Step>

  <Step title="Install dependencies">
    <Tabs>
      <Tab title="pnpm">`bash pnpm install `</Tab>
      <Tab title="npm">`bash npm install `</Tab>
      <Tab title="yarn">`bash yarn install `</Tab>
      <Tab title="bun">`bash bun install `</Tab>
    </Tabs>
  </Step>

  <Step title="Configure environment variables">
    Copy the example environment file and fill in the required values:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    cp .env.example .env.local
    ```

    | Variable                | Description                                                                                     |
    | ----------------------- | ----------------------------------------------------------------------------------------------- |
    | `RESEND_API_KEY`        | Your [Resend API key](https://resend.com/api-keys)                                              |
    | `RESEND_WEBHOOK_SECRET` | Signing secret from your [Resend webhook](https://resend.com/webhooks) endpoint set up below    |
    | `EMAIL_FROM`            | Sender address for digest emails (must be from a [verified domain](https://resend.com/domains)) |
    | `EMAIL_TO`              | Recipient address for digest emails                                                             |
  </Step>

  <Step title="Test the application">
    Start the development server:

    <Tabs>
      <Tab title="pnpm">`bash pnpm run dev `</Tab>
      <Tab title="npm">`bash npm run dev `</Tab>
      <Tab title="yarn">`bash yarn run dev `</Tab>
      <Tab title="bun">`bash bun run dev `</Tab>
    </Tabs>

    Register your publicly accessible HTTPS URL in the Resend dashboard and enable the `email.received` event.

    * For `rua` reports: `https://example123.ngrok.io/api/webhooks/dmarc/rua`
    * For `ruf` report: `https://example123.ngrok.io/api/webhooks/dmarc/ruf`

    Copy the signing secret from the webhook details page to the `RESEND_WEBHOOK_SECRET` environment variable.

    <Tip>
      For development, you can create a tunnel to your localhost server using a tool like
      [ngrok](https://ngrok.com/download) or [VS Code Port Forwarding](https://code.visualstudio.com/docs/debugtest/port-forwarding). These tools serve your local dev environment at a public URL you can use to test your local webhook endpoint.

      Example: `https://example123.ngrok.io/api/webhook`
    </Tip>
  </Step>

  <Step title="Deploy">
    Deploy the application to your preferred hosting platform and update the webhook endpoint(s) in the Resend dashboard.

    * For `rua` reports: `https://example.com/api/webhooks/dmarc/rua`
    * For `ruf` reports: `https://example.com/api/webhooks/dmarc/ruf`

    The project is built with [Next.js](https://nextjs.org) so it works with any platform that supports it (e.g., [Vercel](https://vercel.com)).
  </Step>
</Steps>

## Tech stack

DMARC Analyzer is built with [Next.js](https://nextjs.org), [React Email](https://react.email), and [Resend](https://resend.com). The full source code is available on [GitHub](https://github.com/resend/resend-dmarc-analyzer).


# Email Best Practices Skill
Source: https://resend.com/docs/email-best-practices-skill

Comprehensive guide for building production-ready email systems with AI agents.

The Email Best Practices skill provides AI agents with comprehensive knowledge for building production-ready email integrations in your applications. It covers authentication, compliance, deliverability, and operational best practices.

## Installation

Install the skill using the following command:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
npx skills add resend/email-best-practices
```

## Advantages

* **DNS authentication guidance**: Step-by-step instructions for setting up SPF, DKIM, and DMARC records.
* **Transactional and marketing email design**: Best practices for designing effective transactional and marketing emails.
* **Regional compliance**: Guidelines for CAN-SPAM, GDPR, CASL, and other regional email regulations.
* **Webhook event processing**: Patterns for handling delivery notifications, bounces, and complaints.
* **Suppression list management**: Strategies for maintaining healthy suppression lists and improving deliverability.

## Learn More

<Card title="View on GitHub" icon="arrow-up-right-from-square" href="https://github.com/resend/email-best-practices">
  See the full source code and documentation.
</Card>


# Sending emails with Resend
Source: https://resend.com/docs/email-types

Resend has a wide range of features for sending both transactional and marketing emails.

Resend provides an API, command-line interface (CLI), webhooks, and automations to support both types of emails you need to send:

* **Transactional emails:** personalized, event-driven communication
* **Marketing campaigns:** bulk email [Broadcasts](/docs/dashboard/broadcasts/introduction) distributed to a contact list

All of these email features and activities are also available through a user-friendly Dashboard and through AI tooling for agents. This allows your entire team to create and send emails, update automations, manage contacts, track performance, and more.

Get started with Resend's free plan, then choose from multiple [pricing plans and tiers](https://resend.com/pricing) depending on the number and type of emails you need to send as you grow.

## Send transactional emails

A **Transactional email** is a message triggered by a user action or required for legal compliance. Common examples include:

* Order confirmations
* Password reset emails
* Account notifications

Typically, transactional emails are **1-to-1** messages sent in response to a specific event.

With a Resend Transactional Plan, you can send transactional emails from your application using the [Resend API](/docs/api-reference/introduction), the [Resend CLI](/docs/cli), or with [SMTP](/docs/send-with-smtp). Resend also provides an [MCP server](/docs/mcp-server), [agent skills](/docs/react-email-skill), and more to work with your preferred [AI builder and tooling](/docs/ai-onboarding).

You can also trigger emails using [webhooks](/docs/webhooks/introduction), and even [create steps to automate emails](/docs/dashboard/automations/introduction) based on custom events from your application.

## Send bulk marketing emails

Marketing emails are **promotional**, **informative**, or **general communication** messages.

Marketing emails are regulated by laws like **CAN-SPAM** (US) and **CASL** (Canada), and **recipients must have the option to unsubscribe**.

Examples of marketing emails:

* Promotional offers and discounts
* Newsletters
* Product updates

Marketing emails are typically **1-to-many** messages, sent when you want to reach a larger audience (e.g., newsletters).

With a Resend Marketing Plan, you can send [Broadcasts](/docs/dashboard/broadcasts/introduction) to your subscribers using a no-code editor in your Resend Dashboard, or from the [Broadcast API](https://resend.com/docs/api-reference/broadcasts/create-broadcast).

When you use Broadcasts, you get tools for [managing your contacts](/docs/dashboard/audiences/introduction), [tracking performance](/docs/dashboard/broadcasts/performance-tracking), and [customizing your personal unsubscribe page](/docs/dashboard/settings/unsubscribe-page). Resend also handles all the queuing, throttling, and scheduling for you so that you don't have to roll your own infrastructure.

Marketing plans also allow you to create [Resend automations](/docs/dashboard/automations/introduction) for repeatable actions like welcoming new subscribers and updating your contact list. Resources such as the [Resend MCP server](/docs/mcp-server), [agent skills](/docs/react-email-skill), and more are all available to your preferred [AI builders and tooling](/docs/ai-onboarding) to help you send and manage your marketing emails.

## Send a combination of emails

It is common to need to send both transactional and marketing emails to your users. Your customers need personalized emails about their orders, but may also wish to subscribe to a newsletter that is delivered to your entire contact list.

Some emails do not fit neatly into one category:

* Marketing emails can be **1-to-1**, based on personalized user activity (e.g., abandoned cart reminders, drip marketing campaigns). You can use Resend's transactional APIs and automations to send these individual marketing emails, as long as proper consent and compliance regulations are followed.
* Resend's [batch sending API feature](/docs/dashboard/emails/batch-sending) can send multiple transactional emails at once (up to 100), even to different recipients with unique content, instead of making individual API requests for each email.

You can either go with Resend's opinionated, full-featured solutions or design your own architecture from the ground up. You can use all of Resend's features for any type of email sending that you can build. This includes APIs, CLI commands, webhooks, and automations, plus AI tools and Dashboard controls.

Resend allows you to choose both a Transactional and a Marketing plan, each at the tier that suits your specific use case for your email volume, and features needed. Update each plan individually at any time if your sending habits change, or add pay-as-you-go add-ons if you need a more flexible solution.

## Learn more

<CardGroup>
  <Card title="Send Email API" icon="tools" href="/api-reference/emails/send-email">
    Send, list, retrieve, update, and cancel transactional emails with the Send
    Email API.
  </Card>

  <Card title="Broadcasts" icon="megaphone" href="/dashboard/broadcasts/introduction">
    Create and send marketing emails with Resend's no-code editor or the
    Broadcasts API.
  </Card>
</CardGroup>

## Next steps

<CardGroup>
  <Card title="Import or add email contacts" icon="globe" href="/dashboard/audiences/contacts">
    Add existing subscribers to your Resend contact list programmatically,
    manually, or by uploading a `.csv` file.
  </Card>

  <Card title="Quickstart tutorials" icon="stopwatch" href="/introduction">
    Send your first transactional email with a quick tutorial for your language
    or framework.
  </Card>
</CardGroup>


# Examples
Source: https://resend.com/docs/examples

Explore sample apps for different use cases.

## Frameworks

<CardGroup>
  <Card title="Next.js (TypeScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript">
    Full-stack Next.js app with TypeScript
  </Card>

  <Card title="Next.js (JavaScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript">
    Full-stack Next.js app with JavaScript
  </Card>

  <Card title="Express" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/express-resend-examples">
    Express 5 examples (TypeScript and JavaScript)
  </Card>

  <Card title="Hono" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/hono-resend-examples">
    Hono examples (TypeScript and JavaScript)
  </Card>

  <Card title="Bun" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/bun-resend-examples">
    Bun examples (TypeScript and JavaScript)
  </Card>

  <Card title="Remix" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/remix-resend-examples">
    Remix examples (TypeScript and JavaScript)
  </Card>

  <Card title="Nuxt" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nuxt-resend-examples">
    Nuxt 3 examples (TypeScript and JavaScript)
  </Card>

  <Card title="SvelteKit" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples">
    SvelteKit examples (TypeScript and JavaScript)
  </Card>

  <Card title="Astro" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/astro-resend-examples">
    Astro examples (TypeScript and JavaScript)
  </Card>

  <Card title="RedwoodJS" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/redwoodjs-resend-examples">
    RedwoodJS examples (TypeScript and JavaScript)
  </Card>

  <Card title="TanStack Start" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/tanstack-resend-examples">
    TanStack Start examples (TypeScript and JavaScript)
  </Card>

  <Card title="PHP" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples">
    PHP examples with Slim and Symfony
  </Card>

  <Card title="Laravel" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/laravel-resend-examples">
    Laravel 11 examples
  </Card>

  <Card title="Python" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/python-resend-examples">
    Python examples with Flask, FastAPI, and Django
  </Card>

  <Card title="Ruby" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples">
    Ruby examples with Sinatra and Rails
  </Card>

  <Card title="Go" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples">
    Go examples with Chi and Gin
  </Card>

  <Card title="Java" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/java-resend-examples">
    Java examples with Javalin and Spring Boot
  </Card>

  <Card title=".NET (C#)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/dotnet-resend-examples">
    ASP.NET Minimal APIs and MVC
  </Card>

  <Card title="Rust" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/rust-resend-examples">
    Rust examples with Axum
  </Card>

  <Card title="Elixir" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/elixir-resend-examples">
    Elixir examples with Phoenix
  </Card>
</CardGroup>

## Next.js (TypeScript)

<CardGroup>
  <Card title="Send Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/send-email">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/attachments">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/cid-attachments">
    Embed inline images using CID
  </Card>

  <Card title="React Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/react-email">
    Send emails with React Email components
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/templates">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/scheduling">
    Schedule emails for future delivery
  </Card>

  <Card title="Contact Form" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/contact-form">
    Contact form with batch send via Server Actions
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/double-optin">
    Double opt-in subscription flow
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/inbound">
    Receive and process inbound emails
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/prevent-threading">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/domains">
    Create and manage sending domains
  </Card>

  <Card title="Better Auth" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/better-auth">
    Email authentication with Better Auth
  </Card>
</CardGroup>

## Next.js (JavaScript)

<CardGroup>
  <Card title="Send Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/send-email">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/attachments">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/cid-attachments">
    Embed inline images using CID
  </Card>

  <Card title="React Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/react-email">
    Send emails with React Email components
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/templates">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/scheduling">
    Schedule emails for future delivery
  </Card>

  <Card title="Contact Form" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/contact-form">
    Contact form with batch send via Server Actions
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/double-optin">
    Double opt-in subscription flow
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/inbound">
    Receive and process inbound emails
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/prevent-threading">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/domains">
    Create and manage sending domains
  </Card>

  <Card title="Better Auth" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/better-auth">
    Email authentication with Better Auth
  </Card>
</CardGroup>

## Express

TypeScript and JavaScript variants available. Links below point to the TypeScript examples.

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/basic-send.ts">
    Basic email sending
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/batch-send.ts">
    Send multiple emails at once
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/with-attachments.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/with-cid-attachments.ts">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/with-template.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/scheduled-send.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/prevent-threading.ts">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/audiences.ts">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/inbound.ts">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/double-optin-subscribe.ts">
    Double opt-in subscription flow
  </Card>
</CardGroup>

## Hono

TypeScript and JavaScript variants available. Links below point to the TypeScript examples.

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/basic-send.ts">
    Basic email sending
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/batch-send.ts">
    Send multiple emails at once
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/with-attachments.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/with-cid-attachments.ts">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/with-template.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/scheduled-send.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/prevent-threading.ts">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/audiences.ts">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/inbound.ts">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/double-optin-subscribe.ts">
    Double opt-in subscription flow
  </Card>
</CardGroup>

## Bun

TypeScript and JavaScript variants available. Links below point to the TypeScript examples.

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/basic-send.ts">
    Basic email sending
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/batch-send.ts">
    Send multiple emails at once
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/with-attachments.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/with-cid-attachments.ts">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/with-template.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/scheduled-send.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/prevent-threading.ts">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/audiences.ts">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/inbound.ts">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/double-optin-subscribe.ts">
    Double opt-in subscription flow
  </Card>
</CardGroup>

## Remix

TypeScript and JavaScript variants available. Links below point to the TypeScript examples.

<CardGroup>
  <Card title="Send Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.send.ts">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.send-attachment.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.send-cid.ts">
    Embed inline images using CID
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.send-batch.ts">
    Send multiple emails at once
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.send-template.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.send-scheduled.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.audiences.contacts.ts">
    Manage contacts and audiences
  </Card>

  <Card title="Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.webhook.ts">
    Handle webhook events
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/double-optin.tsx">
    Double opt-in subscription flow
  </Card>

  <Card title="Inbound" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/inbound.tsx">
    Receive and process inbound emails
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/prevent-threading.tsx">
    Prevent email threading on Gmail
  </Card>
</CardGroup>

## Nuxt

TypeScript and JavaScript variants available. Links below point to the TypeScript examples.

<CardGroup>
  <Card title="Send Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/send.post.ts">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/send-attachment.post.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/send-cid.post.ts">
    Embed inline images using CID
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/send-batch.post.ts">
    Send multiple emails at once
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/send-template.post.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/send-scheduled.post.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/domains.post.ts">
    Create and manage sending domains
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nuxt-resend-examples/typescript/server/api/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/webhook.post.ts">
    Handle webhook events
  </Card>
</CardGroup>

## SvelteKit

TypeScript and JavaScript variants available. Links below point to the TypeScript examples.

<CardGroup>
  <Card title="Send Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/send">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/send-attachment">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/send-cid">
    Embed inline images using CID
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/send-batch">
    Send multiple emails at once
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/send-template">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/send-scheduled">
    Schedule emails for future delivery
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/send-prevent-threading">
    Prevent email threading on Gmail
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/domains">
    Create and manage sending domains
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/double-optin">
    Double opt-in subscription flow
  </Card>

  <Card title="Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/webhook">
    Handle webhook events
  </Card>
</CardGroup>

## Astro

TypeScript and JavaScript variants available. Links below point to the TypeScript examples.

<CardGroup>
  <Card title="Send Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/send.ts">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/send-attachment.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/send-cid.ts">
    Embed inline images using CID
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/send-batch.ts">
    Send multiple emails at once
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/send-template.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/send-scheduled.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/astro-resend-examples/typescript/src/pages/api/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/webhook.ts">
    Handle webhook events
  </Card>
</CardGroup>

## RedwoodJS

TypeScript and JavaScript variants available. Links below point to the TypeScript examples.

<CardGroup>
  <Card title="Send Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/send.ts">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/sendAttachment.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/sendCid.ts">
    Embed inline images using CID
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/sendBatch.ts">
    Send multiple emails at once
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/sendTemplate.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/sendScheduled.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/audiencesContacts.ts">
    Manage contacts and audiences
  </Card>

  <Card title="Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/webhook.ts">
    Handle webhook events
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/doubleOptinSubscribe.ts">
    Double opt-in subscription flow
  </Card>
</CardGroup>

## TanStack Start

TypeScript and JavaScript variants available. Links below point to the TypeScript examples.

<CardGroup>
  <Card title="Send Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/send.ts">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/send-attachment.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/send-cid.ts">
    Embed inline images using CID
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/send-batch.ts">
    Send multiple emails at once
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/send-template.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/send-scheduled.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/tanstack-resend-examples/typescript/src/routes/api/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/webhook.ts">
    Handle webhook events
  </Card>
</CardGroup>

## PHP

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/send">
    Basic, batch, and prevent-threading send
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/attachments">
    File attachments and inline images (CID)
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/scheduling">
    Schedule emails for future delivery
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/templates">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/double-optin">
    Double opt-in subscription flow
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/inbound">
    Receive and process inbound emails
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/domains">
    Create and manage sending domains
  </Card>

  <Card title="Symfony App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/symfony_app">
    Full Symfony web application
  </Card>
</CardGroup>

## Laravel

<CardGroup>
  <Card title="Email Sending" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/EmailController.php">
    Basic, scheduled, attachments, CID, templates, and prevent threading
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/WebhookController.php">
    Handle webhook events
  </Card>

  <Card title="Inbound Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/InboundController.php">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/DoubleOptinController.php">
    Double opt-in subscription flow
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/AudienceController.php">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/DomainController.php">
    Create and manage sending domains
  </Card>
</CardGroup>

## Python

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/basic_send.py">
    Basic email sending
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/batch_send.py">
    Send multiple emails at once
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/with_attachments.py">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/with_cid_attachments.py">
    Embed inline images using CID
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/scheduled_send.py">
    Schedule emails for future delivery
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/with_template.py">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/prevent_threading.py">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/audiences.py">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/domains.py">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/inbound.py">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/double_optin_subscribe.py">
    Double opt-in subscription flow
  </Card>

  <Card title="Flask App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/flask_app.py">
    Full Flask web application
  </Card>

  <Card title="FastAPI App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/fastapi_app.py">
    Full FastAPI web application
  </Card>

  <Card title="Django App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/python-resend-examples/django_app">
    Full Django web application
  </Card>
</CardGroup>

## Ruby

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/basic_send.rb">
    Basic email sending
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/batch_send.rb">
    Send multiple emails at once
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/with_attachments.rb">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/with_cid_attachments.rb">
    Embed inline images using CID
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/scheduled_send.rb">
    Schedule emails for future delivery
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/with_template.rb">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/prevent_threading.rb">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/audiences.rb">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/domains.rb">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/inbound.rb">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/examples/double_optin">
    Double opt-in subscription flow
  </Card>

  <Card title="Sinatra App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/sinatra_app">
    Full Sinatra web application
  </Card>

  <Card title="Rails App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/rails_app">
    Full Rails web application
  </Card>
</CardGroup>

## Go

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/basic_send">
    Basic email sending
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/batch_send">
    Send multiple emails at once
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/with_attachments">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/with_cid_attachments">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/with_template">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/scheduled_send">
    Schedule emails for future delivery
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/prevent_threading">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/domains">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/inbound">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/double_optin">
    Double opt-in subscription flow
  </Card>

  <Card title="Chi App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/chi_app">
    Full Chi web framework application
  </Card>

  <Card title="Gin App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/gin_app">
    Full Gin web framework application
  </Card>
</CardGroup>

## Java

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/BasicSend.java">
    Basic email sending
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/BatchSend.java">
    Send multiple emails at once
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/WithAttachments.java">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/WithCidAttachments.java">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/WithTemplate.java">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/ScheduledSend.java">
    Schedule emails for future delivery
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/PreventThreading.java">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/Audiences.java">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/Domains.java">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/Inbound.java">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/DoubleOptinSubscribe.java">
    Double opt-in subscription flow
  </Card>

  <Card title="Javalin App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/java-resend-examples/javalin_app">
    Full Javalin web framework application
  </Card>

  <Card title="Spring Boot App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/java-resend-examples/spring_boot_app">
    Full Spring Boot application
  </Card>
</CardGroup>

## .NET (C#)

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/BasicSend.cs">
    Basic email sending
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/BatchSend.cs">
    Send multiple emails at once
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/WithAttachments.cs">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/WithCidAttachments.cs">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/WithTemplate.cs">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/ScheduledSend.cs">
    Schedule emails for future delivery
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/PreventThreading.cs">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/Audiences.cs">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/Domains.cs">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/Inbound.cs">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/DoubleOptinSubscribe.cs">
    Double opt-in subscription flow
  </Card>

  <Card title="Minimal API App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/dotnet-resend-examples/MinimalApiApp">
    ASP.NET Minimal API application
  </Card>

  <Card title="MVC App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/dotnet-resend-examples/MvcApp">
    ASP.NET MVC application
  </Card>
</CardGroup>

## Rust

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/basic_send.rs">
    Basic email sending
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/batch_send.rs">
    Send multiple emails at once
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/with_attachments.rs">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/with_cid_attachments.rs">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/with_template.rs">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/scheduled_send.rs">
    Schedule emails for future delivery
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/prevent_threading.rs">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/audiences.rs">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/domains.rs">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/inbound.rs">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/double_optin_subscribe.rs">
    Double opt-in subscription flow
  </Card>

  <Card title="Axum App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/rust-resend-examples/axum_app">
    Full Axum web framework application
  </Card>
</CardGroup>

## Elixir

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/basic_send.exs">
    Basic email sending
  </Card>

  <Card title="Batch Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/batch_send.exs">
    Send multiple emails at once
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/with_attachments.exs">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/with_cid_attachments.exs">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/with_template.exs">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/scheduled_send.exs">
    Schedule emails for future delivery
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/prevent_threading.exs">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/audiences.exs">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/domains.exs">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/inbound.exs">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/elixir-resend-examples/examples/double_optin">
    Double opt-in subscription flow
  </Card>

  <Card title="Phoenix App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/elixir-resend-examples/phoenix_app">
    Full Phoenix web framework application
  </Card>
</CardGroup>


# Building an OAuth client for Resend
Source: https://resend.com/docs/guides/building-a-resend-oauth-client

Implement an OAuth 2.1 + PKCE client against the Resend API, from scratch or with a library.

Resend implements OAuth 2.0 and 2.1, including Proof Key for Code Exchange (PKCE) for authorization code exchanges. A client's `client_id` comes from one of three places:

1. Pre-registration: Resend issues a fixed `client_id`, plus a `client_secret` if the client has a backend.
2. [Client ID Metadata Document](#client-id-metadata-documents) (CIMD): the `client_id` is the HTTPS URL of a JSON document you host, which Resend fetches to read the client's metadata.
3. Dynamic Client Registration (DCR): the client registers itself at runtime via POST /oauth/register and is issued a `client_id` then.

**Prefer CIMD over DCR:** it gives the client one identity across every install instead of a new registration each time, and the consent screen can name the host that published the document rather than a name the client picked for itself.

Resend supports both **public** and **confidential** clients. PKCE is required on every authorization code exchange regardless of type:

* **Public clients** authenticate with PKCE alone. Register them with `token_endpoint_auth_method: "none"` (the default), or declare that value in the metadata document. Use a public client when it can't keep a secret, such as native apps, CLIs, and single-page apps. A CIMD client is always public, since its document is world-readable and can't carry a secret.
* **Confidential clients** additionally present a `client_secret` at the token and revocation endpoints. Register them with `token_endpoint_auth_method: "client_secret_basic"` (or `client_secret_post`) to have Resend issue the secret. Use a confidential client when it has a backend that can store the secret privately, such as a server-side web app.

Because Resend does not offer self-service verification or domain-ownership checks yet, pre-register remote third-party clients rather than registering them dynamically, but you can register them with the same register endpoint.

The Resend dashboard hosts the login and consent screen. Your client only needs to open the authorization URL in a browser and handle the callback. You don't build any consent UI yourself.

## Recommended implementation paths

The standard case is registering beforehand, and the worked examples below use it. A metadata document is the next best thing for clients that can't predict their own deployment details ahead of time, like an MCP server: it works for hosted apps and local tools alike, and one document serves every install. Register dynamically only when the client can't host a document.

Also decide whether the client is public or confidential. A client running entirely on the user's machine, such as a native app, CLI, or single-page app, can't hide a secret, so register it as public (`none`). A client with a server-side backend should register as confidential (`client_secret_basic`) and keep the issued `client_secret` out of any user-facing code. That choice only applies to a registered client, since a CIMD client is always public. The [pre-registered remote client](#pre-registered-remote-client) section below covers the confidential path, and the [local client](#local-client) section covers the public one.

## Scopes

Use the smallest scope that works for your integration:

* `emails:send` is enough for send-only routes, such as `POST /emails`, `POST /email`, `POST /emails/sending`, `POST /email/sending`, and `POST /broadcasts/:broadcastId/send`.
* `full_access` is required for other API routes.

A client that omits `scope` gets both scopes by default, whether it registered dynamically or declared no `scope` in its metadata document. Pass `scope` explicitly during registration and authorization instead of relying on that default.

## Request encoding and `resource`

Dynamic client registration uses JSON, and so does a metadata document. The token and revocation endpoints accept both JSON and `application/x-www-form-urlencoded`, but prefer form encoding for `/oauth/token` and `/oauth/revoke`, since that's what most OAuth libraries send by default.

Resend does not support RFC 8707 resource indicators yet. Don't send or rely on `resource` in authorization or token requests. It's accepted but ignored.

## Generating PKCE values and state

Before starting the authorization request, generate three values:

* `code_verifier`: a high-entropy random string kept only by the client. See
  [Token](/docs/api-reference/oauth/token#pkce) for the length and character set it
  must use.
* `code_challenge`: the base64url-encoded SHA-256 hash of the `code_verifier`.
* `state`: a high-entropy random string used to bind the callback to the request that started the flow.

The `code_verifier` is sent only during the token exchange. The `code_challenge` is sent during authorization. The `state` is sent during authorization and must come back unchanged on the callback.

```javascript theme={"theme":{"light":"github-light","dark":"vesper"}}
import { createHash, randomBytes } from 'node:crypto';

function base64url(input) {
  return Buffer.from(input).toString('base64url');
}

const codeVerifier = base64url(randomBytes(64));
const codeChallenge = base64url(
  createHash('sha256').update(codeVerifier).digest(),
);
const state = base64url(randomBytes(24));
```

For a remote client, store `state` and `codeVerifier` server-side before redirecting the user to us. For a local client, keep them in memory while the temporary callback server is running.

## Client ID Metadata Documents

Instead of registering, host a JSON document that describes the client and pass its HTTPS URL as the `client_id`:

```
GET /oauth/authorize?client_id=https%3A%2F%2Fexample.com%2Foauth%2Fclient.json&response_type=code&...
```

Resend fetches that URL, reads the client metadata from it, and runs the rest of the flow exactly as it does for a registered client. There's no registration call and no issued `client_id` to store. The client hardcodes its own document URL, and sends the same value as `client_id` at `/oauth/token` and `/oauth/revoke`.

This follows the [OAuth Client ID Metadata Document](https://datatracker.ietf.org/doc/draft-ietf-oauth-client-id-metadata-document/) draft. The rules below are the parts specific to Resend.

Host the document on a site you control, whatever the client is. A hosted app serves it next to the app and lists its own `https` callback. A CLI or desktop app serves it on the vendor's website and lists loopback callbacks, since the document only has to name the client, not run it.

### The document

```json theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "client_id": "https://example.com/oauth/client.json",
  "client_name": "Example App",
  "client_uri": "https://example.com",
  "logo_uri": "https://example.com/logo.png",
  "redirect_uris": ["https://example.com/oauth/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none",
  "scope": "emails:send"
}
```

The fields are the [registration](/docs/api-reference/oauth/register) fields, with extra rules:

| Field                        | Rule                                                                                                                                   |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `client_id`                  | Required. Must equal the document's own URL, character for character.                                                                  |
| `client_name`                | Required, 1–200 characters.                                                                                                            |
| `redirect_uris`              | Required, 1 to 10 entries. An `https` URI must be on the same host as the document. See [Redirect URIs](#redirect-uris-in-a-document). |
| `token_endpoint_auth_method` | Must be `none`, or omitted. A document is public, so it can't authenticate with a secret.                                              |
| `client_secret`              | Must be absent.                                                                                                                        |
| `jwks`, `jwks_uri`           | Must be absent. Resend doesn't support `private_key_jwt`.                                                                              |
| `grant_types`                | Must include `authorization_code`. Values Resend doesn't support are ignored rather than rejected.                                     |
| `response_types`             | If present, `["code"]` only.                                                                                                           |
| `scope`                      | Space-delimited, and every value must be [supported](#scopes). Pass it explicitly: an omitted `scope` gives the client both scopes.    |
| `logo_uri`                   | Optional, `http` or `https`. Shown on the consent screen only when it's served from the same host as the document.                     |
| `client_uri`                 | Optional. Read but not otherwise used.                                                                                                 |

Apart from `grant_types`, a declaration Resend can't honor fails the whole document rather than being dropped from it. A client that declares `private_key_jwt`, for instance, gets an error rather than being downgraded to an unauthenticated one.

### The document URL

The URL is the client's identity, and it's compared as an exact string with no normalization. Serve the document at a URL that survives a parse-and-serialize round trip: lowercase host, no explicit `:443`, no `.` or `..` segments. It must use `https`, have a path (`https://example.com` alone won't do), and carry no fragment and no userinfo. Maximum 2048 characters.

Treat the URL as permanent. Moving the document makes a different client, and every user has to authorize again.

### Redirect URIs in a document

A document proves that you control its host, and nothing else:

* An `https` redirect URI must be on the same host as the document URL. A document at `https://example.com/oauth/client.json` can't name a callback on `app.example.net`.
* Loopback `http` URIs (`127.0.0.1`, `localhost`, `[::1]`) are exempt. A loopback address names the user's own machine rather than a publisher, so there's nothing to compare. Port variance works the same way it does for a registered client.
* Private-use URI schemes (e.g. `cursor://`) are exempt too, since they carry no web host at all.

### Hosting and caching

Resend fetches the document when a browser hits `/oauth/authorize`.

* Redirects aren't followed. Serve the document at the exact URL with a `2xx`.
* 5 KB maximum, 5 second timeout. A real document is a few hundred bytes.
* The document must be reachable. A fetch that fails, or a document that doesn't validate, fails the authorization with `invalid_client`. Resend won't fall back to an older copy, since a stale document can name a redirect URI you no longer control.
* `cache-control: max-age` is honored, clamped between 5 minutes and 24 hours. A document sent with `no-store` still gets the 5-minute floor.

Only `/oauth/authorize` fetches. Token, refresh, and revoke requests use the copy Resend already holds, so a document that's briefly unreachable doesn't break clients that already have a grant.

Because of the 5-minute floor, allow time for an edit to take effect. If a CDN caches the file too, the two windows stack.

### On the consent screen

Resend has no self-service verification yet, so a CIMD client is unverified. The consent screen headlines the document's host rather than `client_name`, since the host is the part Resend can check. `client_name` is shown as the client's own claim about itself.

Being unverified affects errors too. Once `client_id` and `redirect_uri` are validated, `/oauth/authorize` redirects an error back to the callback only when the target is a loopback address, a private-use scheme, or a verified client. An unverified `https` callback gets a JSON error instead, which stops the endpoint from being used as an open redirect. Handle both.

## Pre-registered remote client

A remote client must use an HTTPS redirect URI owned by the app, for example `https://example.com/oauth/callback`.

Because a remote client has a backend that can keep a secret, register it as confidential: pass `token_endpoint_auth_method: "client_secret_basic"` and store the `client_secret` Resend returns. That secret is shown only once at registration, so persist it securely and never expose it in browser or client-side code. It's then presented on every token and revocation call, in addition to PKCE.

For remote apps, you can still use [POST /oauth/register](/docs/api-reference/oauth/register) manually while we don't have a central place in the app to create clients.

```mermaid theme={"theme":{"light":"github-light","dark":"vesper"}}
sequenceDiagram
    autonumber
    participant C as App backend
    participant B as User browser
    participant AS as Resend OAuth API
    participant D as Resend dashboard

    Note over C: Generate PKCE values and state<br>Store alongside the user's session

    C->>B: 302 redirect to /oauth/authorize URL
    B->>AS: GET /oauth/authorize<br>client_id, redirect_uri, scope,<br>state, code_challenge
    AS-->>B: 302 redirect to dashboard consent URL
    B->>D: User reviews and approves request
    D-->>B: 302 redirect_uri with code + state
    B->>C: Callback with code + state

    Note over C: Verify state against the stored session value

    C->>AS: POST /oauth/token<br>Basic auth (client_id + client_secret)<br>grant_type=authorization_code<br>code, redirect_uri, code_verifier
    AS-->>C: access_token + refresh_token
```

<Steps>
  <Step title="Load the pre-issued client_id and client_secret" />

  <Step title="Generate PKCE and state">
    `code_verifier`, `code_challenge`, and `state`. See
    [above](#generating-pkce-values-and-state).
  </Step>

  <Step title="Store state and code_verifier server-side">
    Tie them to the user's session.
  </Step>

  <Step title="Redirect the user's browser to /oauth/authorize" />

  <Step title="Handle the callback on the app's backend" />

  <Step title="Reject invalid callbacks">
    A missing `code`, mismatched or missing `state`, or an `error` query
    parameter should all be treated as failures.
  </Step>

  <Step title="Exchange the code server-side">
    Use the original `code_verifier`, and present the `client_secret` via HTTP
    Basic auth.
  </Step>

  <Step title="Store the refresh token securely" />

  <Step title="Serialize refreshes">
    Atomically replace the stored refresh token after every refresh.
  </Step>
</Steps>

Example authorization URL:

```
GET /oauth/authorize?client_id=550e8400-e29b-41d4-a716-446655440000&response_type=code&redirect_uri=https%3A%2F%2Fexample.com%2Foauth%2Fcallback&scope=emails%3Asend&state=STATE_VALUE&code_challenge=CODE_CHALLENGE_VALUE&code_challenge_method=S256 HTTP/1.1
Host: api.resend.com
```

Example code exchange. The `-u` flag sends the `client_id` and `client_secret` as HTTP Basic auth, so `client_id` isn't repeated in the body:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X POST 'https://api.resend.com/oauth/token' \
     -H 'Content-Type: application/x-www-form-urlencoded' \
     -u '550e8400-e29b-41d4-a716-446655440000:CLIENT_SECRET' \
     -d 'grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=https%3A%2F%2Fexample.com%2Foauth%2Fcallback&code_verifier=CODE_VERIFIER_VALUE'
```

## Local client

A local client must use a loopback redirect URI or a private-use URI scheme, per RFC 8252. Prefer `127.0.0.1` with a random local port, for example `http://127.0.0.1:49152/oauth/callback`. A native app the operating system routes to can use its own scheme instead, such as `cursor://oauth/callback`.

Loopback redirect URIs allow port variance, whether they come from registration or from a metadata document. The host, path, and query string must still match, and `localhost` and `127.0.0.1` count as different hosts. For example, a client can declare `http://127.0.0.1/oauth/callback` and later authorize with `http://127.0.0.1:49152/oauth/callback`.

The sequence below registers dynamically. With a [metadata document](#client-id-metadata-documents), skip the registration step: the `client_id` is the document's URL, and the loopback redirect URI is listed in the document.

```mermaid theme={"theme":{"light":"github-light","dark":"vesper"}}
sequenceDiagram
    autonumber
    participant C as Local client
    participant B as User browser
    participant AS as Resend OAuth API
    participant D as Resend dashboard

    Note over C: Bind loopback callback server<br>Generate PKCE values and state

    C->>AS: POST /oauth/register<br>loopback redirect_uri, minimum scope
    AS-->>C: client_id

    C->>B: Open /oauth/authorize URL
    B->>AS: GET /oauth/authorize<br>client_id, redirect_uri, scope,<br>state, code_challenge
    AS-->>B: 302 redirect to dashboard consent URL
    B->>D: User reviews and approves request
    D-->>B: 302 redirect_uri with code + state
    B->>C: Callback with code + state

    Note over C: Verify state, then close the server

    C->>AS: POST /oauth/token<br>grant_type=authorization_code<br>code, redirect_uri, code_verifier
    AS-->>C: access_token + refresh_token
```

<Steps>
  <Step title="Bind a temporary callback server">
    Pick a random high port and bind it to `127.0.0.1` or `[::1]`, never
    `0.0.0.0`.
  </Step>

  <Step title="Generate PKCE and state">
    `code_verifier`, `code_challenge`, and `state`. See
    [above](#generating-pkce-values-and-state).
  </Step>

  <Step title="Get a client_id">
    Use the URL of a [metadata document](#client-id-metadata-documents) that
    lists the loopback redirect URI and the minimum required scope. If the
    client can't host one, register dynamically with the same values instead.
    See [Register Client](/docs/api-reference/oauth/register).
  </Step>

  <Step title="Open the authorize URL in the user's browser">
    Don't prefetch `/oauth/authorize` from your process and follow the redirect
    yourself. The user needs to see the consent screen.
  </Step>

  <Step title="Let the browser follow the redirect to the dashboard consent screen" />

  <Step title="Handle exactly one callback, then close the server" />

  <Step title="Reject invalid callbacks">
    A missing `code`, mismatched or missing `state`, or an `error` query
    parameter should all be treated as failures.
  </Step>

  <Step title="Exchange the code">
    Use the original `code_verifier`. See [Token](/docs/api-reference/oauth/token).
  </Step>

  <Step title="Store the newest refresh token after every token response" />
</Steps>

Close the loopback server after success or timeout.

### Dynamic client registration

Pass `scope` explicitly. If DCR omits `scope`, Resend registers the client with both scopes by default.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X POST 'https://api.resend.com/oauth/register' \
     -H 'Content-Type: application/json' \
     -d $'{
  "client_name": "Example Local OAuth Client",
  "redirect_uris": ["http://127.0.0.1/oauth/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none",
  "scope": "emails:send"
}'
```

The response returns a UUID `client_id`:

```json theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "client_id": "550e8400-e29b-41d4-a716-446655440000",
  "client_id_issued_at": 1750000000,
  "client_name": "Example Local OAuth Client",
  "redirect_uris": ["http://127.0.0.1/oauth/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none",
  "scope": "emails:send"
}
```

### Authorization request

Do not have a backend or CLI process prefetch `/oauth/authorize` and then open the returned dashboard URL. Instead, open the authorization URL in the user's browser and let the browser follow the redirect to the dashboard.

```javascript theme={"theme":{"light":"github-light","dark":"vesper"}}
const authorizationUrl = new URL('https://api.resend.com/oauth/authorize');
authorizationUrl.search = new URLSearchParams({
  client_id: '550e8400-e29b-41d4-a716-446655440000',
  response_type: 'code',
  redirect_uri: 'http://127.0.0.1:49152/oauth/callback',
  scope: 'emails:send',
  state,
  code_challenge: codeChallenge,
  code_challenge_method: 'S256',
}).toString();

openBrowser(authorizationUrl.toString());
```

After approval, Resend redirects back to the exact `redirect_uri` used in the authorization request:

```
GET /oauth/callback?code=AUTHORIZATION_CODE&state=STATE_VALUE HTTP/1.1
Host: 127.0.0.1:49152
```

Verify that the returned `state` matches the original `state` before exchanging the code.

### Authorization code exchange

The `redirect_uri` in the token request must match the `redirect_uri` from the authorization request.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X POST 'https://api.resend.com/oauth/token' \
     -H 'Content-Type: application/x-www-form-urlencoded' \
     -d 'grant_type=authorization_code&client_id=550e8400-e29b-41d4-a716-446655440000&code=AUTHORIZATION_CODE&redirect_uri=http%3A%2F%2F127.0.0.1%3A49152%2Foauth%2Fcallback&code_verifier=CODE_VERIFIER_VALUE'
```

The response includes a JWT access token and an opaque refresh token:

```json theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "access_token": "eyJhbGciOiJFUzI1NiIsImtpZCI6Im9hdXRoX2tleSIsInR5cCI6ImF0K2p3dCJ9...",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "JcL7aYfE7S9h3L4qv0o2e1w8m6n5b3x9RkP2tD4uV6Q",
  "scope": "emails:send"
}
```

### Refresh token exchange

Refresh tokens rotate on every successful refresh. Serialize refresh operations for a grant, and store the new refresh token atomically with the rest of the response. If refresh succeeds but the new refresh token isn't persisted, you'll need to reauthorize. Retrying an old token from multiple workers can revoke the whole grant: a replay fails with `invalid_grant` either way, and it also revokes the grant unless the rotation happened within the last minute. Don't rely on that window. See [Token](/docs/api-reference/oauth/token) for the reuse-detection details.

Each refresh resets the new token's 60-day lifetime, so a client that refreshes regularly never has to reauthorize.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X POST 'https://api.resend.com/oauth/token' \
     -H 'Content-Type: application/x-www-form-urlencoded' \
     -d 'grant_type=refresh_token&client_id=550e8400-e29b-41d4-a716-446655440000&refresh_token=JcL7aYfE7S9h3L4qv0o2e1w8m6n5b3x9RkP2tD4uV6Q'
```

## Revoking access

To disconnect a client, revoke the refresh token:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X POST 'https://api.resend.com/oauth/revoke' \
     -H 'Content-Type: application/x-www-form-urlencoded' \
     -d 'client_id=550e8400-e29b-41d4-a716-446655440000&token=JcL7aYfE7S9h3L4qv0o2e1w8m6n5b3x9RkP2tD4uV6Q&token_type_hint=refresh_token'
```

A confidential client must authenticate this request too, the same way it does at the token endpoint. For example, pass its `client_secret` with `curl -u 'CLIENT_ID:CLIENT_SECRET'` instead of sending `client_id` in the body.

Access tokens are JWTs and can't be revoked individually. Revoking the refresh token revokes the grant. See [Revoke Token](/docs/api-reference/oauth/revoke).


# Send emails with Devin and Resend
Source: https://resend.com/docs/guides/devin

Learn how to install the Resend MCP server in Devin.ai so your agent can send emails, manage contacts, and run broadcasts.

[Devin](https://devin.ai) is an autonomous AI software engineer that can connect to external services through MCP (Model Context Protocol) servers. Adding Resend's MCP server gives Devin native access to send emails, manage contacts and broadcasts, verify domains, and more.

For the full list of capabilities, see the [MCP Server overview](/docs/mcp-server).

## Prerequisites

Before you start, make sure you have:

* A Devin account with access to the Settings menu
* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Open Devin Settings">
    In Devin, open the **Settings** menu from your account dropdown.
  </Step>

  <Step title="Go to Connections > MCP Servers">
    In the Settings sidebar, click **Connections**, then select the **MCP Servers** tab. Click **Add a custom MCP**.

    <img alt="Selecting MCP Servers under Connections in Devin" />
  </Step>

  <Step title="Add the Resend MCP configuration">
    Click **Import JSON** and paste the following configuration into the modal.

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "mcpServers": {
        "resend": {
          "command": "npx",
          "args": ["-y", "resend-mcp"],
          "env": {
            "RESEND_API_KEY": "re_xxxxxxxxx",
            "SENDER_EMAIL_ADDRESS": "onboarding@resend.dev"
          }
        }
      }
    }
    ```

    <img alt="Pasting the Resend MCP configuration in Devin" />
  </Step>

  <Step title="Update the Environment Variables">
    Scroll down and update the environment variables:

    * `RESEND_API_KEY`: delete this and add it as a secret (see the next step).
    * `SENDER_EMAIL_ADDRESS`: update this with your sender email address you've verified in the [Resend Dashboard](https://resend.com/domains).

      <img alt="Update the environment variables" />
  </Step>

  <Step title="Add the Resend API key as a secret">
    Add the `RESEND_API_KEY` as a secret. Click **Save secret** to confirm.

    <img alt="Adding the Resend API key as a Devin secret" />

    <Info>
      You can create a new API key in the [Resend
      Dashboard](https://resend.com/api-keys).
    </Info>
  </Step>

  <Step title="Confirm and enable the MCP server">
    Add a description, click **Install and Enable**, and confirm in the dialog. Devin will install the server and mark it as connected.

    <img alt="Confirming the Resend MCP server in Devin" />
  </Step>

  <Step title="Test the connection">
    Ask Devin to send a test email. For example:

    ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
    Send a test email to delivered@resend.dev using the Resend MCP server. Subject: "Hello from Devin".
    ```

    Devin will call the Resend MCP server and confirm the send.
  </Step>
</Steps>


# Turn Paper designs into Resend emails
Source: https://resend.com/docs/guides/paper

Learn how to combine the Paper MCP server and the Resend MCP server so your agent can turn a Paper design into a template or broadcast in your Resend account.

[Paper](https://paper.design) is a design tool built for AI agents. Its MCP server lets agents read your canvas, including layout, styles, copy, and screenshots. Combined with the [Resend MCP server](/docs/mcp-server), your agent can take a design straight from Paper and turn it into a ready-to-send [Template](/docs/dashboard/templates/introduction) or [Broadcast](/docs/dashboard/broadcasts/introduction) in your Resend account.

The flow looks like this:

1. You design an email in Paper.
2. Your agent reads the design through the Paper MCP server.
3. Your agent converts the design into email-safe HTML using the [Resend MCP server](/docs/mcp-server) and [agent skills](/docs/resend-skill).
4. Your agent creates a Template or Broadcast in Resend

## Prerequisites

Before you start, make sure you have:

* The [Paper Desktop app](https://paper.design/downloads) installed with a file open (opening a file starts the Paper MCP server automatically)
* A [Resend account](https://resend.com/signup) with a [verified domain](/docs/add-a-domain)
* An MCP client like Claude Code, Cursor, or Claude Desktop

<Info>
  [See a full example](#example-end-to-end-prompt) for a complete end-to-end
  prompt.
</Info>

## Guide

<Steps>
  <Step title="Connect the Paper MCP server">
    Paper Desktop runs a local MCP server at `http://127.0.0.1:29979/mcp` whenever a file is open.

    <Tabs>
      <Tab title="Claude Code">
        Install the official Paper plugin (recommended):

        ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
        /plugin marketplace add paper-design/agent-plugins
        /plugin install paper-desktop@paper
        ```

        Or add the MCP server directly:

        ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
        claude mcp add paper --transport http http://127.0.0.1:29979/mcp --scope user
        ```
      </Tab>

      <Tab title="Codex">
        Install the official Paper plugin (recommended):

        ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
        codex plugin marketplace add paper-design/agent-plugins
        /plugins
        ```

        Select the `paper-design/agent-plugins` marketplace and install the `paper-desktop` plugin.
      </Tab>

      <Tab title="Cursor">
        Run `/add-plugin paper-desktop` in the agent panel, or search for "Paper" in the [Cursor Marketplace](https://cursor.com/marketplace/paper).
      </Tab>

      <Tab title="Claude Desktop">
        Open Claude Desktop settings > "Developer" tab > "Edit Config".

        ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
        {
          "mcpServers": {
            "paper": {
              "command": "npx",
              "args": ["mcp-remote", "http://127.0.0.1:29979/mcp"]
            }
          }
        }
        ```
      </Tab>
    </Tabs>

    See the [Paper MCP docs](https://paper.design/docs/mcp) for other clients.
  </Step>

  <Step title="Connect the Resend MCP server">
    Connect to Resend's hosted MCP server at `https://mcp.resend.com/mcp`. When you connect, your client opens a browser window to log in to Resend and approve access.

    <Tabs>
      <Tab title="Claude Code">
        ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
        claude mcp add --transport http resend https://mcp.resend.com/mcp
        ```

        Then run `/mcp` in Claude Code and select **resend** to complete the OAuth login.
      </Tab>

      <Tab title="Codex">
        ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
        codex mcp add resend --url https://mcp.resend.com/mcp
        ```
      </Tab>

      <Tab title="Cursor">
        Open the command palette and choose "Cursor Settings" > "MCP" > "Add new global MCP server".

        ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
        {
          "mcpServers": {
            "resend": {
              "url": "https://mcp.resend.com/mcp"
            }
          }
        }
        ```
      </Tab>

      <Tab title="Claude Desktop">
        Open **Settings** > **Connectors** > **Add custom connector** and enter:

        ```
        https://mcp.resend.com/mcp
        ```
      </Tab>
    </Tabs>

    For more clients and configuration options, including running the server locally, see the [MCP Server overview](/docs/mcp-server).
  </Step>

  <Step title="Design your email in Paper">
    Design your email as an artboard in Paper. A few tips for designs that translate well to email:

    * Use a single-column layout around 600px wide.
    * Use real copy instead of placeholder text.
    * Use web-safe fonts like `System Sans-Serif` or `System Serif`.
    * Use PNG or JPG images instead of SVGs (not supported in email).

    <Tip>
      Where you want personalization, write the variable directly into the design
      copy, like `Hi {{{NAME|there}}}`. Your agent will preserve it when
      creating the template or broadcast.
    </Tip>
  </Step>

  <Step title="Ask your agent to create an email">
    You can create either a [Template](/docs/dashboard/templates/introduction) or a [Broadcast](/docs/dashboard/broadcasts/introduction).

    To create a template, select an artboard in Paper and with both servers connected, prompt your agent with the following:

    ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
    Look at the selected artboard in Paper and recreate it as an email template
    in Resend. Convert the design to email-safe HTML (inline styles, table-based
    layout) using the Resend agent skills. Provide a name, subject, and preview text for the template that fits the content. Publish the template.
    ```

    Behind the scenes, the agent will:

    1. Call Paper's `get_selection` and `get_screenshot` to see the design.
    2. Call Paper's `get_jsx` or `get_computed_styles` to read the exact layout, colors, and copy.
    3. Convert the output into email-safe HTML.
    4. Call Resend's `create-template` with the HTML, name, and subject.
    5. Call Resend's `publish-template` to make it available for sending.

    Templates support variables using triple-brace syntax, like `{{{USERNAME}}}`. Once published, you can send the template via the [Emails API](/docs/api-reference/emails/send-email) or the dashboard.

    To create a Broadcast and go from design to a campaign instead:

    ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
    Look at the selected artboard in Paper and create a Resend broadcast from it.
    Convert the design to email-safe HTML using the Resend agent skills. Provide a name, subject, and preview text for the template that fits the content. Create it as a
    draft, don't send it yet.
    ```

    The agent reads the design the same way, then calls Resend's `create-broadcast` with the HTML, sender, subject, and segment. You can review the draft in the [Resend dashboard](https://resend.com/broadcasts) before sending it yourself.

    <Info>
      Before you can send a Broadcast, you must define which
      [Segment](/docs/dashboard/segments/introduction) should receive it. If you don't
      have one yet, your agent can create one.
    </Info>
  </Step>

  <Step title="Refine in the visual editor">
    Templates and Broadcasts created by your agent are editable in the Resend dashboard. If you want your agent's content to be fully editable in the visual editor, ask it to use `compose-template` or `compose-broadcast` instead of raw HTML. You'll see the agent appear as a named avatar in the editor while it works, and you can hand-tune the result afterwards.

    <img alt="Hold to confirm" />

    Alternatively, you can edit the Template or Broadcast in the Resend dashboard. Select the **Editor icon** in the top lefthand corner and **Hold to confirm** and convert the HTML to a visual template or broadcast.
  </Step>
</Steps>

## Example: end-to-end prompt

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
1. Read the "Launch Announcement" artboard from Paper.
2. Convert it to an email-safe HTML email. Preserve the colors, spacing, and
   copy as closely as email clients allow. Use the Resend agent skills.
3. Create it as a broadcast in Resend from announcements@example.com to the
   "Customers" segment, subject "We just launched".
4. Show me a summary and the dashboard link, but do not send it.
```

## Troubleshooting

* **Agent can't reach Paper**: make sure Paper Desktop is running with a file open, then restart your agent session.
* **Design looks different in the email**: email clients don't support modern CSS. Ensure you've installed the Resend's [agent skills](/docs/resend-skill). Then ask the agent to use table-based layout and inline styles, and to flag anything (like custom fonts or complex gradients) that won't survive the conversion.
* **`create-broadcast` fails**: check that the `from` address uses a [verified domain](https://resend.com/domains) and that the segment exists.


# Vercel Marketplace Integration
Source: https://resend.com/docs/guides/vercel-marketplace-integration

Create and connect a Resend account directly from Vercel using the dashboard or the CLI.

The Resend integration on the [Vercel Marketplace](https://vercel.com/marketplace/resend) lets you provision a Resend account without leaving Vercel. Once installed, Vercel connects the account to your project so you can start sending email right away.

## What you get

* A Resend account created and linked to your Vercel account.
* A connection between that account and the Vercel project you selected.
* Access to the full [Resend dashboard](https://resend.com), where you can add domains, manage API keys, and view logs.

## Prerequisites

Before you begin, make sure you have the following:

* A Vercel account with a project.
* A domain purchased in Vercel.

## Three surfaces

You can add Resend to a Vercel project from any of these surfaces:

* [**Vercel Dashboard**](#vercel-dashboard)
* [**Vercel CLI**](#vercel-cli)

<video aria-label="Demonstration of installing Resend from the Vercel Marketplace" />

### Vercel Dashboard

To install Resend from the Vercel Marketplace:

1. Log in to Vercel and go to the [Marketplace](https://vercel.com/resend/~/integrations/marketplace).
2. Search for "Resend" and click on the integration card.
3. Click on the "Install" button.
4. To create a new Resend account for your Vercel project, click on the "Create Account" option and **Continue**.
5. Click **Accept and Create** to continue the installation.
6. Select your custom domain associated with your Vercel project (or purchase a domain from Vercel).
7. Select the region your emails will be sent from (defaults to North Virginia).
8. Select a plan (free or paid).
9. Click **Continue** and **Create** to complete the installation.
10. Select your Vercel project to connect the domain to Resend and click **Connect**.

Vercel creates a new Resend account for your Vercel project, connects the domain to Resend, and provisions an API key.

### Vercel CLI

Add Resend to the linked project from your terminal. With the [Vercel CLI](https://vercel.com/docs/cli) installed:

1. Run `vc i resend -m domain=example.com`. To choose the region your emails will be sent from, pass it as metadata: `-m region=eu-west-1` (defaults to `us-east-1`). Supported regions: `us-east-1`, `eu-west-1`, `sa-east-1`, and `ap-northeast-1`.
2. Select your custom domain associated with your Vercel project (or purchase a domain from Vercel).
3. Select a plan (free or paid).
4. Click **Continue** and **Create** to complete the installation.
5. Select your Vercel project to connect the domain to Resend and click **Connect**.
6. Click **Complete onboarding** to view the domain in your new Resend account.
7. Click **Auto configure** to automatically add the DNS records to your Vercel domain.

Get more help adding a custom domain in [Resend's documentation](/docs/dashboard/domains/introduction).

## Next steps

* Send your first email with [Next.js](/docs/send-with-nextjs).
* Explore [receiving emails](/docs/dashboard/receiving/introduction) with Resend.
* Use Resend [Templates](/docs/dashboard/templates/introduction) to simplify your email sending and design.
* Create your first Resend [Automation](/docs/dashboard/automations/introduction).


# Integrations
Source: https://resend.com/docs/integrations

Integrate Resend with the tools you already use.

## AI

<CardGroup>
  <Card title="Lovable" href="https://docs.lovable.dev/integrations/resend" icon={<LovableIcon />}>
    Tell the Lovable AI to send emails
  </Card>

  <Card title="Anything" href="https://www.createanything.com/docs/integrations/resend" icon={<AnythingIcon />}>
    Add email to your Anything projects
  </Card>

  <Card title="Wildcard" href="https://github.com/wild-card-ai/agents-json/blob/master/examples/resend.ipynb" icon={<WildcardIcon />}>
    Send natural language emails using Wildcard
  </Card>

  <Card title="mcp.run" href="https://www.mcp.run/nilslice/resend" icon={<McpRunIcon />}>
    Build email AI agents using mcp.run
  </Card>

  <Card title="Rocket" href="https://docs.rocket.new/integrations/resend" icon={<RocketIcon />}>
    Send emails from apps built with Rocket
  </Card>

  <Card title="Base44" href="https://docs.base44.com/Integrations/Resend-integration" icon={<Base44Icon />}>
    Add email to your Base44 apps
  </Card>

  <Card title="Leap.new" href="https://docs.leap.new/integrations/resend" icon={<LeapNewIcon />}>
    Add email to your Leap apps
  </Card>

  <Card title="Parsley" href="https://www.parsley.id/integrations/resend" icon={<ParsleyIcon />}>
    Buyer intent into Resend Segments
  </Card>

  <Card title="Pica" href="https://www.picaos.com/integrations/resend" icon={<PicaIcon />}>
    Integrate Pica with Resend
  </Card>

  <Card title="camelAI" href="https://camelai.com/docs/getting-started/partners/resend" icon={<CamelAi />}>
    Add email to your camelAI apps
  </Card>
</CardGroup>

## No-code

<CardGroup>
  <Card title="n8n" href="https://n8n.io/integrations/resend" icon={<N8nIcon />}>
    Build email workflows using n8n
  </Card>

  <Card title="Zapier" href="https://zapier.com/apps/resend/integrations" icon={<ZapierIcon />}>
    Automate emails using Zapier
  </Card>

  <Card title="Email Element" href="https://docs.emailelement.com/en/SendIntegrations/Resend" icon={<EmailElementIcon />}>
    Send emails using Email Element
  </Card>

  <Card title="Pipedream" href="https://pipedream.com/apps/resend" icon={<PipedreamIcon />}>
    Build workflows using Pipedream
  </Card>

  <Card title="Activepieces" href="https://www.activepieces.com/pieces/resend" icon={<ActivepiecesIcon />}>
    Build workflows using Activepieces
  </Card>

  <Card href="https://docs.bunny.com/guide/advanced-guides/integrations/resend" icon={<BunnyIcon />}>
    Quote and bill customers from Bunny
  </Card>

  <Card title="Monkedo" href="https://monkedo.com/integrations/app/resend" icon={<MonkedoIcon />}>
    Automate emails using Monkedo
  </Card>

  <Card title="Make.com" href="https://www.make.com/en/integrations/resend" icon={<MakeComIcon />}>
    Build workflows using Make.com
  </Card>

  <Card title="Lindy" href="https://www.lindy.ai/integrations/resend" icon={<LindyIcon />}>
    Build workflows using Lindy
  </Card>

  <Card title="BuildShip" href="https://buildship.com/integrations/resend" icon={<BuildShipIcon />}>
    Build workflows using BuildShip
  </Card>

  <Card title="viaSocket" href="https://viasocket.com/integrations/resend?utm_source=resend&utm_medium=marketplace&utm_campaign=resend_listing" icon={<ViaSocketIcon />}>
    Build automations using viaSocket
  </Card>

  <Card title="Stacksync" href="https://www.stacksync.com/connectors/resend" icon={<StacksyncIcon />}>
    Build automations using Stacksync
  </Card>

  <Card href="https://apix-drive.com/en/integrations/resend" icon={<ApixDriveIcon />}>
    Use Resend as a data destination in ApiX-Drive
  </Card>

  <Card title="Post SMTP" href="https://postmansmtp.com/docs/mailers/how-to-setup-resend-with-post-smtp/" icon={<PostSmtpIcon />}>
    Send emails from WordPress with Post SMTP
  </Card>

  <Card title="Softr" href="https://docs.softr.io/workflows/integrations/resend" icon={<SoftrIcon />}>
    Send emails from Softr apps and workflows
  </Card>
</CardGroup>

## Notifications

<CardGroup>
  <Card title="Courier" href="https://www.courier.com/docs/guides/providers/email/resend/" icon={<CourierIcon />}>
    Trigger messages using Courier
  </Card>

  <Card title="Novu" href="https://docs.novu.co/platform/integrations/email/resend" icon={<NovuIcon />}>
    Send notifications using Novu
  </Card>

  <Card title="Knock" href="https://docs.knock.app/integrations/email/resend" icon={<KnockIcon />}>
    Send notifications using Knock
  </Card>

  <Card title="Engagespot" href="https://docs.engagespot.co/docs/features/channels/email/resend/" icon={<EngagespotIcon />}>
    Send notifications using Engagespot
  </Card>

  <Card title="Dittofeed" href="https://docs.dittofeed.com/integrations/channels/resend" icon={<DittofeedIcon />}>
    Send automated emails using Dittofeed
  </Card>

  <Card title="Suprsend" href="https://docs.suprsend.com/docs/resend" icon={<SuprsendIcon />}>
    Send notifications using Suprsend
  </Card>
</CardGroup>

## Content Management Systems

<CardGroup>
  <Card title="Payload CMS" href="https://payloadcms.com/docs/email/overview#resend-configuration" icon={<PayloadCmsIcon />}>
    Send emails using Payload CMS
  </Card>

  <Card title="Strapi CMS" href="https://strapi.io/integrations/resend" icon={<StrapiCmsIcon />}>
    Send emails using Strapi CMS
  </Card>
</CardGroup>

## Developer tools

<CardGroup>
  <Card title="Raycast" href="https://www.raycast.com/resend/resend" icon={<RaycastIcon />}>
    Manage emails, domains, and more
  </Card>

  <Card title="Convex" href="https://www.convex.dev/components/resend" icon={<ConvexIcon />}>
    Send emails with Convex's Resend Component
  </Card>

  <Card title="Inngest" href="https://www.inngest.com/docs/guides/resend-webhook-events" icon={<InngestIcon />}>
    Send drip campaigns using Inngest
  </Card>

  <Card title="Upstash" href="https://upstash.com/docs/qstash/integrations/resend" icon={<UpstashIcon />}>
    Send emails using Upstash
  </Card>

  <Card title="Encore" href="https://encore.cloud/integrations/resend" icon={<EncoreIcon />}>
    Send emails backed by Encore's observability and infrastructure
  </Card>

  <Card title="Trigger.dev" href="https://trigger.dev/docs/guides/examples/resend-email-sequence" icon={<TriggerDevIcon />}>
    Send drip campaigns using Trigger.dev
  </Card>

  <Card title="Infisical" href="https://infisical.com/docs/self-hosting/configuration/envars#resend" icon={<InfisicalIcon />}>
    Send email when self-hosting Infisical
  </Card>

  <Card title="Fastgen" href="https://docs.fastgen.com/actions/integrations/resend" icon={<FastgenIcon />}>
    Build workflows using Fastgen
  </Card>

  <Card title="Medusa" href="https://docs.medusajs.com/resources/integrations/guides/resend" icon={<MedusaIcon />}>
    Send e-commerce emails using Medusa
  </Card>

  <Card title="OpenMeter" href="https://openmeter.io/docs/reporting/email" icon={<OpenMeterIcon />}>
    Send usage emails using OpenMeter
  </Card>

  <Card title="Invopop" href="https://docs.invopop.com/guides/features/email" icon={<InvopopIcon />}>
    Send invoice emails using Invopop
  </Card>

  <Card title="Tinybird" href="https://www.tinybird.co/docs/get-data-in/guides/ingest-from-resend" icon={<TinybirdIcon />}>
    Analyze your email data in real time
  </Card>

  <Card title="PostHog" href="https://posthog.com/docs/cdp/sources/resend" icon={<PostHogIcon />}>
    Sync Resend data to the PostHog data warehouse
  </Card>

  <Card title="Coolify" href="https://coolify.io/docs/knowledge-base/notifications#resend-configuration" icon={<CoolifyIcon />}>
    Send email notifications using Coolify
  </Card>

  <Card title="Courrier" href="https://railsdesigner.com/courrier/" icon={<CourrierIcon />}>
    API-powered email delivery for Ruby apps
  </Card>

  <Card title="Auth0" href="https://auth0.com/docs/customize/email/smtp-email-providers/resend" icon={<Auth0Icon />}>
    Send Auth0 transactional emails using Resend
  </Card>

  <Card title="Kinde" href="https://docs.kinde.com/integrate/third-party-tools/kinde-resend-custom-smtp/" icon={<KindeIcon />}>
    Send auth and billing emails using Kinde
  </Card>

  <Card title="Pulsetic" href="https://help.pulsetic.com/article/492-setting-up-custom-email-for-status-page" icon={<PulseticIcon />}>
    Send status page notifications using Pulsetic
  </Card>

  <Card title="brin" href="https://brin.sh/docs/integrations/resend" icon={<BrinIcon />}>
    Scan inbound emails for phishing before your app processes them
  </Card>

  <Card title="Playrunner" href="https://playrunner.dev/docs/integration-packages/resend/" icon={<PlayrunnerIcon />}>
    Send and receive email in Playrunner workflows
  </Card>
</CardGroup>

## Build your own integration

Here's how to build your own integration with Resend:

1. Read the documentation on [how to send emails](/docs/api-reference/emails/send-email).
2. Integrate with your product offering.
3. [Reach out to us](https://resend.com/contact) to feature your product on this page.


# Introduction
Source: https://resend.com/docs/introduction

Resend is the email API for developers.

<div>
  For all documentation in an index, see
  [llms.txt](https://resend.com/docs/llms.txt). To view the full text of the
  documentation, see [llms-full.txt](https://resend.com/docs/llms-full.txt).
</div>

To get started with Resend, you'll need:

1. Your own domain, [verified with Resend](/docs/add-a-domain)
2. [A Resend API key](/docs/create-an-api-key)

Then, you'll be ready to send [both types of emails](/docs/explore-sending-features):

* **Transactional emails:** personalized, event-driven communication
* **Marketing campaigns:** bulk email Broadcasts distributed to a contact list

## Quickstart

Learn how to get Resend set up in your project.

<CardGroup>
  <Card title="Node.js Quickstart" icon={<NodejsIcon />} href="/send-with-nodejs" />

  <Card title="Next.js Quickstart" icon={<NextjsIcon />} href="/send-with-nextjs" />

  <Card title="Express Quickstart" icon={<ExpressIcon />} href="send-with-express/" />

  <Card title="PHP Quickstart" icon={<PhpIcon />} href="send-with-php/" />

  <Card title="Laravel Quickstart" icon={<LaravelIcon />} href="send-with-laravel/" />

  <Card title="Python Quickstart" icon={<PythonIcon />} href="/send-with-python" />

  <Card title="Ruby Quickstart" icon={<RubyIcon />} href="/send-with-ruby" />

  <Card title="Rails Quickstart" icon={<RailsIcon />} href="/send-with-rails" />

  <Card title="Go Quickstart" icon={<GoIcon />} href="/send-with-go" />

  <Card title="Rust Quickstart" icon={<RustIcon />} href="/send-with-rust" />

  <Card title="Elixir Quickstart" icon={<ElixirIcon />} href="/send-with-elixir" />

  <Card title="Java Quickstart" icon={<JavaIcon />} href="/send-with-java" />

  <Card title=".NET Quickstart" icon={<DotnetIcon />} href="/send-with-dotnet" />

  <Card title="CLI Quickstart" icon={<TerminalIcon />} href="/cli-quickstart" />
</CardGroup>

## Explore

Discover the full range of features and capabilities.

<CardGroup>
  <Card title="Emails" href="dashboard/emails">
    Visualize all the activity in your account.
  </Card>

  <Card title="Domains" href="dashboard/domains/introduction">
    Ensure deliverability of your emails.
  </Card>

  <Card title="Webhooks" href="/webhooks/introduction">
    Notify your application about email events.
  </Card>
</CardGroup>


# 403 Error with Error Code 1010
Source: https://resend.com/docs/knowledge-base/403-error-1010

Learn how to resolve a 403 error caused by a missing User-Agent header when sending requests to the Resend API.

You may receive a 403 error with error code 1010 (`Access denied`) when sending requests to the Resend API. This happens because requests without a `User-Agent` header are blocked before they reach the API.

## The Problem

The Resend API requires all HTTP requests to include a `User-Agent` header. When your HTTP client doesn't send one, the request is rejected with a 403 status code and error 1010 before it ever reaches the API.

This can be confusing because:

* The error doesn't come from the Resend API itself
* Tools like `curl` automatically include a `User-Agent` header, so requests from the command line work fine
* The error message doesn't clearly indicate that the missing header is the cause

## How to Identify This Issue

* You're getting a 403 error, but your API key and domain are correct
* The error response contains an error code of `1010`
* The same request works when using `curl` from the command line

## Solution

Add a `User-Agent` header to your HTTP requests.

**Example with Node.js `fetch`:**

```javascript theme={"theme":{"light":"github-light","dark":"vesper"}}
fetch('https://api.resend.com/emails', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer re_123456789',
    'Content-Type': 'application/json',
    'User-Agent': 'my-app/1.0',
  },
  body: JSON.stringify({
    from: 'you@example.com',
    to: 'user@example.com',
    subject: 'Hello World',
    html: '<p>Hello World</p>',
  }),
});
```

<Info>
  If you're using a [Resend SDK](/docs/sdks), the `User-Agent` header is already
  included automatically. This issue typically only affects direct HTTP requests
  made without an SDK.
</Info>

## Get more help

If you've added a `User-Agent` header and you're still getting a 403 error:

1. Verify that the header is being sent correctly by inspecting your outgoing request.
2. Ensure your API key is valid and has the necessary permissions.
3. Check that your domain is verified in the [Resend Domains page](https://resend.com/domains).
4. [Contact Resend support](https://resend.com/help) with details about your error.


# 403 Error Using Verified Domain
Source: https://resend.com/docs/knowledge-base/403-error-domain-mismatch

Learn how to resolve a 403 error caused by using a domain in your API request that doesn't match your verified domain.

A 403 error can occur when there's a mismatch between the domain you're using in your API request and the domain you've verified in Resend.

## The Problem

You've verified a domain (or subdomain) in Resend, but your API request is using a different domain.

**Example scenario:**

* You verified `sending.domain.com` in Resend
* Your API request is using `domain.com` (that is, without the `sending` subdomain)

## How to Identify This Issue

1. Check which domain you've verified in your [Resend Domains page](https://resend.com/domains).
2. Compare it with the domain you're using in [your API request's](https://resend.com/logs) `from` field.

## Solution

You have two options to resolve this:

**Option 1: Update your API request** (Recommended)

Update your API call to use the verified domain. For example, if you verified `sending.domain.com`, make sure your `from` field uses that exact domain:

```javascript theme={"theme":{"light":"github-light","dark":"vesper"}}
resend.emails.send({
  from: 'onboarding@sending.domain.com', // Use your verified domain
  to: 'user@example.com',
  subject: 'Hello World',
  html: '<p>Hello World</p>',
});
```

**Option 2: Delete and re-add the domain**

1. Delete the domain you've added in Resend
2. Add and verify the domain that matches what you're using in your API request

<Warning>
  Make sure the domain in your API request exactly matches the domain you've
  verified in Resend, including any subdomains.
</Warning>

## If You're Still Having Issues

If you've verified that your domain matches and you're still getting a 403 error:

1. Verify that your domain is fully verified in the [Resend Domains page](https://resend.com/domains).
2. Double-check that the domain in your API request's `from` field exactly matches your verified domain
3. Ensure your API key has the necessary permissions.
4. [Contact Resend support](https://resend.com/help) with details about your error


# 403 Error Using resend.dev Domain
Source: https://resend.com/docs/knowledge-base/403-error-resend-dev-domain

Learn how to resolve a 403 error when using the resend.dev domain to send emails to recipients other than your own.

You may receive a 403 error with the following message when trying to send emails:

```
You can only send testing emails to your own email address (your-email-address@domain.com).
To send emails to other recipients, please verify a domain at resend.com/domains, and change
the `from` address to an email using this domain.
```

## The Problem

You're using the default `resend.dev` domain while sending to email addresses other than your own.

**Example scenario:**

* Your API request uses `from: 'onboarding@resend.dev'`
* You're trying to send to recipients other than your own email address

## Why This Happens

The `resend.dev` domain is only available for testing purposes and can only send emails to the email address associated with your Resend account. This restriction helps protect domain reputation and ensures proper email deliverability.

## Solution

To send emails to recipients other than your own email address, you need to add and verify your own domain in Resend:

1. Go to the [Domains page](https://resend.com/domains) in your Resend dashboard
2. Click **Add Domain**
3. Enter your domain name
4. Follow the verification steps to add the required DNS records
5. Once verified, update your API request to use your verified domain

<Info>
  For detailed instructions on verifying your domain, check out our [domain
  verification guide](/docs/dashboard/domains/introduction) or the DNS guide for your
  specific provider.
</Info>

## If You're Still Having Issues

If you've verified your domain and updated your API request but you're still getting a 403 error:

1. Verify that your domain is fully verified in the [Resend Domains page](https://resend.com/domains).
2. Ensure the domain in your API request's `from` field uses your verified domain (not `resend.dev`).
3. Make sure you're not trying to send to your own email address when using `resend.dev`.
4. [Contact Resend support](https://resend.com/help) with details about your error.


# What are Resend account quotas and limits?
Source: https://resend.com/docs/knowledge-base/account-quotas-and-limits

Learn what quotas and limits apply to accounts.

Resend regulates email volume in three ways:

1. email volume (quota) - for [Transactional Email](/docs/knowledge-base/what-sending-feature-to-use#transactional-emails)
2. number of contacts - for [Marketing Email](/docs/knowledge-base/what-sending-feature-to-use#marketing-emails)
3. sending rate

These limits help improve your deliverability and likelihood of reaching your recipient's inbox.

<Info>
  Both **sent emails** and **received emails** (inbound) count towards your
  account's email quota. Each received email counts as 1 email against your
  daily and monthly limits, just like sent emails.
</Info>

## Free Account Quotas and Limits

Free accounts have the following:

* Transactional emails: daily email quota of 100 emails/day and 3,000 emails/month. This quota includes both sent and received emails. Multiple `To`, `CC`, or `BCC` recipients in sent emails count as separate emails towards this quota.

* Marketing emails: unlimited emails to up to 1,000 contacts per month.

## Paid Plan Quota

* Transactional Pro, Scale and Enterprise plans have no daily quota limits, though the plan tier will dictate the monthly email quota. Both sent and received emails count towards this monthly quota. To see your current month usage, view the [**Usage page**](https://resend.com/settings/usage). Multiple `To`, `CC`, or `BCC` recipients in sent emails count as separate emails towards the monthly quota.
* Marketing Pro, Enterprise plans have unlimited emails, though the plan tier will dictate the monthly contacts.

## Overage Limits

Paid plans include pay-as-you-go overages, which allow you to continue sending emails after you've reached your monthly quota. To prevent extreme overages and unexpected costs, a hard limit of 5x your monthly quota applies.

<Note>
  By default, overage usage is capped at **5x your plan's monthly quota**. Once you reach this limit, sending will be paused until the next billing cycle.

  If you need to adjust this limit, please [contact support](https://resend.com/help).
</Note>

<Tip>
  While overages provide flexibility for occasional spikes in email volume, they
  can be more expensive per email than upgrading your plan. If you consistently
  exceed your quota, consider [upgrading to a higher
  tier](https://resend.com/settings/billing) for better value and more
  predictable costs.
</Tip>

## Rate Limits

All accounts start with a rate limit of 10 requests per second. The [rate limits](/docs/api-reference/rate-limit) follow the [IETF standard](https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-ratelimit-headers) for stating the rate limit in the response header. If you have specific requirements, [contact support](https://resend.com/help) to request a rate increase.

The rate limit is enforced as a per-second window. There is no separate burst allowance above the stated limit. If your limit is 10 requests per second, an eleventh request in the same second window will receive a `429` response.

### Rate limit scope

The rate limit is **per team**, not per API key or per domain. All API keys associated with your team share the same rate limit pool. If you have multiple services or applications sending through the same Resend team, their requests count together toward the 10 req/sec limit.

For example, if Service A sends 6 requests and Service B sends 4 requests in the same second, you have hit your 10 req/sec limit for that window. Any additional requests from either service will receive a `429` response.

### High-volume workloads

If you have potential sending spikes or sustained high-volume workloads, consider these approaches:

* **Batch sending**: Use the [Batch Email API](/docs/api-reference/emails/send-batch-emails) to send up to 100 emails in a single API call. Each batch request counts as one request against your rate limit.
* **Client-side throttling**: Use the [rate Limit headers](/docs/api-reference/rate-limit) to configure client-side throttling.
* **Traffic spikes**: If you anticipate sustained traffic above your current limit, [contact support](https://resend.com/help) in advance to request a rate increase.

## Bounce Rate

All accounts must maintain a bounce rate of under **4%**. The [**Metrics page**](https://resend.com/metrics) within an account and/or [webhooks](https://resend.com/docs/webhooks/event-types#email-bounced) allow you to monitor your account bounce rates.

Maintaining a bounce rate above 4% may result in a temporary pause in sending until the bounce rate is reduced.

Tips to keep a bounce rate low:

* Remove inactive user email addresses from email lists.
* Only send to recipients who have given consent to receive email.
* When testing, avoid sending to fake email addresses. Use Resend's [test email addresses](/docs/dashboard/emails/send-test-emails) instead.
* If you are using open/click tracking, periodically remove recipients who are not engaging with your emails from your email lists.

## Spam Rate

All accounts must have a spam rate of under **0.08%**. The [**Metrics page**](https://resend.com/metrics) within an account and/or [webhooks](https://resend.com/docs/webhooks/event-types#email-complained) allow you to monitor your account spam rates.

Maintaining a spam rate over 0.08% may result in a temporary pause in sending until the spam rate is reduced.

Tips to keep a spam rate low:

* Give recipients a clear way to opt out of emails.
* Send relevant and timely emails.
* Only send to recipients who have given consent to receive email.


# Audience Hygiene: How to keep your Audiences in good shape?
Source: https://resend.com/docs/knowledge-base/audience-hygiene

Learn strategies for maintaining good audience hygiene and maximizing email deliverability.

Audience hygiene (*also known as list hygiene*) refers to the practice of keeping your email list clean, valid, and engaged.

Maintaining proper audience hygiene is crucial for ensuring that your emails reach their intended recipients, maximizing your deliverability, and improving your sender reputation.

By removing invalid, outdated, or disengaged contacts, you can improve the effectiveness of your email campaigns. You'll also avoid issues like high bounce rates, low engagement, and even being marked as spam.

***

# How to ensure emails are valid

To keep your list healthy, it's essential to ensure that the email addresses you collect are valid, accurate, and belong to recipients who are truly interested in hearing from you. Here are a few strategies to help you achieve this:

### Prevent undesired or bot signups with CAPTCHA

Bots can sign up for your emails with little friction, inflating your list with fake or low-quality contacts. To help protect against bot signups, implement CAPTCHA systems during the sign-up process. CAPTCHA challenges help ensure that sign-ups come from human users and not bots or automated scripts.

Some popular CAPTCHA services include:

* **[Google reCAPTCHA](https://developers.google.com/recaptcha)**: One of the most widely used CAPTCHA services, offering both simple and advanced protection options.
* **[hCaptcha](https://www.hcaptcha.com/)**: An alternative to Google reCAPTCHA, providing similar protection but with a different user experience.
* **[Friendly Captcha](https://friendlycaptcha.com/)**: A privacy-focused CAPTCHA solution that doesn’t require users to click on anything, reducing friction in the sign-up process.

Using these tools will help reduce bot sign-ups and ensure your email list consists of real users.

### Ensure the recipient is consenting with Double Opt-In

Double opt-in is the process of confirming a user's subscription after they’ve signed up for your emails.

When a user submits their email address, you send them a confirmation email with a link they must click to complete the subscription process.

This step ensures that the person who entered the email address is the one who actually wants to receive your communications.

This is important to ensure:

* **Compliance with local regulations**: Double opt-in helps ensure that you comply with email marketing regulations such as the **CAN-SPAM Act** (U.S.) and **CASL** (Canada). Both of these laws require clear consent from subscribers before you can send them marketing emails.
* **Improved deliverability**: Double opt-in helps you maintain a clean list of genuinely interested users. This reduces bounce rates and prevents spam complaints, which in turn helps maintain your sender reputation with ISPs and inbox providers.
* **Verification of accuracy**: Double opt-in ensures the email addresses you collect are valid, accurate, and up to date, reducing the risk of sending to invalid addresses and impacting your deliverability.

### Use a third-party service to verify an address' deliverability

While you can verify that an email address follows the correct syntax (e.g., [user@example.com](mailto:user@example.com)) (also known as RFC 5322), you also need to ensure that the address is deliverable, that is, it’s an active inbox that can receive emails.

Third-party email verification services can help you identify whether an email address is valid, reachable, or likely to result in a bounce.

This reduces the risk of sending to addresses that won’t receive your emails and improves your overall deliverability.

Some email verification services include:

* **[Emailable](https://emailable.com/partners/resend)**
* **ZeroBounce**
* **Kickbox**

By using these services, you can clean up your existing email lists or prevent undeliverable emails to be added to them. This helps prevent unnecessary deliverability issues.

***

# How to proactively remove emails from your Segments

Over time, certain recipients may become disengaged with your content. It's important to manage your segments by removing inactive or unengaged users.

Regularly filtering your segments ensures that you're sending to only those who are actively interested, which in turn boosts engagement and deliverability.

A healthy email list is one that is continuously nurtured with relevant and timely content. Instead of sporadic communication, maintain consistent engagement with your audience to keep them interested.

### Filter on engagement

To keep your email list in top shape, focus on sending to engaged users. Major inbox providers like Gmail and Microsoft expect you to send emails to recipients who have recently opened or clicked on your emails.

As a best practice, limit non-transactional email sends to recipients who have opened or clicked an email in the past 6 months.

<Info>
  The exact timeframe may vary depending on your industry, sending frequency,
  and audience behavior, but 6 months is a generally accepted standard.
</Info>

Regularly cleaning your list of disengaged recipients helps maintain a positive sender reputation and boosts your chances of landing in the inbox instead of the spam folder.

### Automatically remove bounced recipients

Using our [Webhooks](/docs/webhooks/introduction), you can be notified when a delivery bounces or gets marked as spam by the recipient.

This allows you to proactively unsubscribe the recipient and prevent further sending. Resend will automatically suppress further deliveries to that email address but will not automatically unsubscribe it for you.

### Sunset unengaged recipients

If certain recipients have not engaged with your emails over an extended period (e.g., 6+ months), consider removing them from your Marketing sends.

Continuing to send to these unengaged users can harm your deliverability by increasing bounce rates and decreasing your open rates.

To re-engage these users, you may want to send a re-engagement campaign or offer an incentive for them to stay on your list. If they don't respond, it's often best to remove them to keep your list healthy and avoid wasting resources on inactive contacts.

***

Audience hygiene involves validating email addresses, ensuring consent, verifying deliverability, and removing unengaged recipients. By maintaining these practices, you'll improve your email deliverability and foster better relationships with your subscribers.

This will help you achieve better engagement rates and a healthier sender reputation with inbox providers.


# Cloudflare
Source: https://resend.com/docs/knowledge-base/cloudflare

Verify your domain on Cloudflare with Resend.

## Add Domain to Resend

First, log in to your [Resend Account](https://resend.com/login) and [add a domain](https://resend.com/domains).

<img alt="Domain Details" />

<Tip>
  It is [best practice to use a
  subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain)
  (updates.example.com) instead of the root domain (example.com). Using a
  subdomain allows for proper reputation segmentation based on topics or purpose
  (e.g. marketing) and is especially important if receiving emails with Resend.
</Tip>

## Automatic Setup (Recommended)

The fastest way to verify your domain on Cloudflare is using the **Sign in to Cloudflare** button on Resend. This uses Domain Connect to automatically configure your DNS records.

1. Go to your [Domains page](https://resend.com/domains) in Resend.
2. (Optional) If you want to receive emails, select `Manual setup` and toggle the "Receiving" switch on the domain details page. ([Learn more below](#receiving-emails))
3. Click **Sign in to Cloudflare** button.
4. Authorize Resend to access your Cloudflare DNS settings.
5. The DNS records will be added automatically.

<video aria-label="Cloudflare Domain Connect Setup" />

That's it. Your domain will be verified within a few minutes.

## Manual Setup

If you prefer to add DNS records manually, follow these steps.

### Log in to Cloudflare

Log in to your [Cloudflare account](https://cloudflare.com) and go to the DNS Records of your domain.

<img alt="Domain Details" />

### Add MX SPF Record

Click "Add Record" on Cloudflare:

1. Set the Type to `MX`.
2. Type `send` for the `Name` of the record.
3. Copy the MX Value from Resend into the `Mail Server` field.
4. Use the default `Auto` for `TTL`.
5. Add `10` for the `Priority`.
6. Select `Save`.

<img alt="Domain Details" />

<br />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Cloudflare:

| Cloudflare  | Resend   | Example Value                           |
| ----------- | -------- | --------------------------------------- |
| Type        | Type     | `MX`                                    |
| Name        | Name     | `send`                                  |
| Mail Server | Content  | `feedback-smtp.us-east-1.amazonses.com` |
| Priority    | Priority | `10`                                    |

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<Info>
  Do not use the same priority for multiple records. If Priority `10` is already
  in use, try a higher value `20` or `30`.
</Info>

### Add TXT SPF Record

Click "Add Record" on Cloudflare:

1. Set the Type to `TXT`.
2. Type `send` for the `Name` of the record.
3. Copy the TXT Value Resend into `Content` field.
4. Use the default `Auto` for `TTL`.
5. Select `Save`.

<img alt="Domain Details" />

<br />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Cloudflare:

| Cloudflare | Resend  | Example Value                         |
| ---------- | ------- | ------------------------------------- |
| Type       | Type    | `TXT`                                 |
| Name       | Name    | `send`                                |
| Content    | Content | `"v=spf1 include:amazonses.com ~all"` |
| TTL        | -       | `Auto`                                |

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

### Add TXT DKIM Records

Click "Add Record" on Cloudflare:

1. Set the Type to `TXT`.
2. Type `resend._domainkey` for the `Name` of the record.
3. Copy the TXT Value Resend into `Content` field.
4. Use the default `Auto` for `TTL`.
5. Select `Save`.

<img alt="Domain Details" />

<br />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Cloudflare:

| Cloudflare   | Resend  | Example Value                |
| ------------ | ------- | ---------------------------- |
| Type         | Type    | `TXT`                        |
| Name         | Name    | `resend._domainkey`          |
| Target       | Content | `p=example_domain_key_value` |
| Proxy Status | -       | `DNS Only (disabled)`        |
| TTL          | -       | `Auto`                       |

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `resend._domainkey.example.com`, paste only `resend._domainkey` (or
  `resend._domainkey.subdomain` if you're using a subdomain).
</Info>

### Receiving Emails

If you want to receive emails at your domain, toggle the "Receiving" switch on the domain details page.

<img alt="Enable Receiving Emails for a verified domain" />

<Warning>
  When you enable Inbound on a domain, Resend receives *all emails* sent to that
  specific domain depending on the priority of the MX record. For this reason,
  we strongly recommend verifying a subdomain (`subdomain.example.com`) instead
  of the root domain (`example.com`). Learn more about [avoiding conflicts with
  your existing MX
  records](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
</Warning>

Click “Add Record” on Cloudflare:

1. Set the Type to `MX`.
2. Type `inbound` (or whatever your subdomain is) for the `Name` of the record.
3. Copy the MX Value from Resend into the `Mail Server` field.
4. Use the default `Auto` for `TTL`.
5. Add `10` for the `Priority`.
6. Select `Save`.

Below is a mapping of the record fields from Resend to Cloudflare:

| Cloudflare  | Resend   | Example Value                          |
| ----------- | -------- | -------------------------------------- |
| Type        | Type     | `MX`                                   |
| Name        | Name     | `inbound`                              |
| Mail Server | Content  | `inbound-smtp.us-east-1.amazonaws.com` |
| Priority    | Priority | `10`                                   |

After verifying your domain, create a webhook to process incoming emails. For help setting up a webhook, how to access email data and attachments, forward emails, and more, see [our guide on receiving emails with Resend](/docs/dashboard/receiving/introduction).

### Complete Verification

Now click [Verify DNS Records](https://resend.com/domains) on your Domain in Resend. It may take up to 72 hours to complete the verification process (often much faster).

## Troubleshooting

If your domain is not successfully verified, these are some common troubleshooting methods.

<AccordionGroup>
  <Accordion title="Cloudflare returns 'Code: 1004' when adding CNAME Records.">
    Confirm your proxy settings are set to `DNS Only` on the record you are adding.
  </Accordion>

  <Accordion title="Resend shows my domain verification failed.">
    Review the records you added to Cloudflare to rule out copy and paste errors.
  </Accordion>

  <Accordion title="It has been longer than 72 hours and my domain is still Pending.">
    [Review our guide on a domain not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying).
  </Accordion>
</AccordionGroup>


# Do You Need 2048-bit DKIM?
Source: https://resend.com/docs/knowledge-base/do-i-need-2048-dkim

Learn why 1024-bit DKIM is enough for transactional and marketing mail, and how it compares to 2048-bit keys.

**For almost every sender, you do not need 2048-bit DKIM.** This additional level of security can result in performance and compatibility issues with some systems.

To balance these concerns, Resend signs outbound mail with 1024-bit DKIM keys, which are RFC-compliant, accepted by every major mailbox provider, and satisfy the bulk sender requirements that inbox service providers enforce. Resend does not support 2048-bit DKIM keys.

## 1024-bit is RFC-compliant

[RFC 8301 §3.2](https://datatracker.ietf.org/doc/html/rfc8301#section-3.2) establishes 1024 bits as the minimum length verifiers must support and recommends signers use keys of at least 1024 bits. Mailbox providers including Gmail, Outlook, Yahoo, and Apple all accept 1024-bit DKIM signatures, and 1024-bit keys remain widely used across the industry for transactional and marketing mail.

## 1024-bit meets bulk sender requirements

The 2024 bulk sender requirements from Google, Yahoo, and Microsoft (which apply to anyone sending more than 5,000 messages per day to their users) require DKIM authentication alongside SPF and DMARC. **None of them mandate a specific DKIM key length**. 1024-bit DKIM signing fully satisfies these requirements, and Resend's domain setup gives you DKIM out of the box.

## 1024-bit vs 2048-bit keys

|                       | 1024-bit                                                        | 2048-bit                                                                                   |
| --------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| **Security**          | Meets current RFC recommendations for email signing             | Stronger cryptographic margin, better future-proofing                                      |
| **Performance**       | Faster signing and verification                                 | More system resources required, can add latency                                            |
| **DNS compatibility** | Fits comfortably in a single TXT record                         | Longer public key. Some DNS providers require splitting the record or hit character limits |
| **Setup**             | Straightforward, works with every DNS provider you'll encounter | Requires careful setup. Misconfigured records can fail verification                        |

## Trade-offs of 2048-bit

* **Delivery latency.** Larger keys take longer to sign and verify on every message, which can add delay at scale.
* **DNS friction.** Most DNS providers now support the longer TXT record length needed for 2048-bit public keys, but some still impose character limits or require the value to be split into multiple strings. That's a common source of broken DKIM records and failed verifications.
* **No deliverability upside.** Inbox providers do not reward 2048-bit signatures with better placement.

## Our stance

For transactional and marketing mail, **1024-bit DKIM is the right choice.** It meets the RFC, satisfies bulk sender requirements from every major inbox provider, and keeps DNS setup simple and reliable.

<Note>
  If your security or compliance team has a specific requirement for 2048-bit
  DKIM, [let us know](https://resend.com/help).
</Note>


# Does Resend require production approval?
Source: https://resend.com/docs/knowledge-base/does-resend-require-production-approval

Learn about production access and account limitations on Resend.

No, Resend does not require production approval. All accounts, including free accounts, have immediate production access from the moment you sign up.

## Free accounts have production access

Free accounts on Resend have full production access immediately. There is no sandbox mode, no approval process, and no waiting period. You can start sending transactional emails to your customers right away.

<Info>
  Resend does not limit free accounts or require authorization to send
  production emails. All accounts have the same production capabilities from day
  one.
</Info>

## Common misconceptions

Some users may think they need production approval if:

* **DNS records aren't generated yet**: If you've added a domain but haven't completed DNS verification, the domain will show as "Pending" until you add the required DNS records. Once you add and verify your DNS records, the domain will show as verified and you can send from that domain.

* **Coming from other email services**: Some email service providers do require production approval or have sandbox modes. Resend does not have these restrictions.

## Getting started

To start sending emails with Resend:

1. [Sign up for a Resend account](https://resend.com/signup)
2. [Add and verify your domain](https://resend.com/domains)
3. [Create an API key](https://resend.com/api-keys)
4. Start sending emails immediately

If you're having trouble with domain verification or DNS records, see our [domain verification troubleshooting guide](/docs/knowledge-base/what-if-my-domain-is-not-verifying) or check our [DNS setup guides](/docs/knowledge-base/introduction) for your specific DNS provider.


# Domain Already Registered by Another Account
Source: https://resend.com/docs/knowledge-base/domain-already-registered

Resolve the 403 domain already registered error by verifying domain ownership or starting a self-serve claim.

## Overview

When you add a domain to Resend, you may see this error: `The example.com domain has been registered already`.

This means the domain is associated with a different Resend account. A domain can only be active on one Resend account at a time.

## Why This Happens

Common reasons a domain may already be registered:

* A team member or contractor added it to a separate account.
* You are logged in to a different account than the one where the domain was originally added.

## How to Resolve It

### Check your existing accounts first

1. Check with your team to see if someone is already using Resend.
2. Make sure you're logged in to the right account.

### Claim the domain

If the domain belongs to a different team and you can prove ownership, you can claim it through a self-serve process:

1. Go to [Domains](https://resend.com/domains) and click **Add Domain**.
2. Enter the domain name and submit the form.
3. A prompt will appear explaining that the domain is in use by another Resend team. Click **Start claim** to begin.
4. Add the DNS TXT record provided to your domain's DNS settings to prove ownership.

The claim expires in 7 days. If you started a claim previously, you can pick up where you left off by submitting the same domain name again and clicking **Continue claim**.

If you cannot add DNS records or need further assistance, contact [Resend support](https://resend.com/help).

## Related Resources

* [What if my domain is not verifying?](/docs/knowledge-base/what-if-my-domain-is-not-verifying)
* [DNS provider setup guides](/docs/knowledge-base/introduction)


# Where to find Resend documents like DPA or W-9
Source: https://resend.com/docs/knowledge-base/downloading-documents

How to download compliance and tax documents from your Resend account.

Resend keeps your account's compliance and tax documents in one place: [Settings → Documents](https://resend.com/settings/documents).

<Info>
  You must be logged in to your Resend account to access the
  [Documents](https://resend.com/settings/documents) page.
</Info>

## What's on the page

* **Penetration test**: Penetration testing is performed at least annually by third-party cybersecurity company Oneleet. The Letter of Attestation is available to download.
* **SOC 2**: Resend is SOC 2 Type II compliant under the framework developed by the AICPA. This audit was completed by Vanta & Advantage Partners and covers the period of February 1, 2025 to February 1, 2026. The full report is available to download.
* **DPA**: The Data Processing Agreement governs how Resend processes data on your behalf. The version on this page is pre-signed by Resend and is considered fully executed once you sign up for an account, so no counter-signature is required.
* **Form W-9**: The W-9 provides Resend's U.S. taxpayer identification number for vendor onboarding and accounts payable.

## Related pages

* [Sub-processors](https://resend.com/legal/subprocessors)
* [Unsigned DPA](https://resend.com/legal/dpa)


# DreamHost
Source: https://resend.com/docs/knowledge-base/dreamhost

Verify your domain on DreamHost with Resend.

## Add Domain to Resend

First, log in to your [Resend Account](https://resend.com/login) and [add a domain](https://resend.com/domains).

<img alt="Domain Details" />

<Tip>
  It is [best practice to use a
  subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain)
  (updates.example.com) instead of the root domain (example.com). Using a
  subdomain allows for proper reputation segmentation based on topics or purpose
  (e.g. marketing) and is especially important if receiving emails with Resend.
</Tip>

## Log in to DreamHost

1. Log in to your [DreamHost panel](https://panel.dreamhost.com).

2. Go to **Websites > Manage Websites**.

3. Select **Manage** on the domain you want to verify.
   <img alt="DreamHost DNS TXT Record" />

## Add TXT SPF Record

1. Navigate to the **DNS** tab.
2. Enter `send` as Host.
3. Enter `v=spf1 include:amazonses.com ~all` as TXT Value.
4. Click **Add Record**.

Below is a mapping of the record fields from Resend to DreamHost:

| DreamHost | Resend  | Example Value                       |
| --------- | ------- | ----------------------------------- |
| Type      | Type    | `TXT Record`                        |
| Host      | Name    | `send`                              |
| TXT Value | Content | `v=spf1 include:amazonses.com ~all` |

<img alt="DreamHost DNS Dashboard" />

## Add TXT DKIM Records

1. In the same window, add another TXT record.

2. Add `resend._domainkey` as Host.

3. Copy the value from your domain configuration page in Resend and paste it into DreamHost.

   <img alt="Domain Details" />

4. Click **Add Record**.
   <img alt="DreamHost DNS Dashboard" />
   Below is a mapping of the record fields from Resend to DreamHost:

| DreamHost | Resend  | Example Value                |
| --------- | ------- | ---------------------------- |
| Type      | Type    | `TXT Record`                 |
| Host      | Name    | `resend._domainkey`          |
| TXT Value | Content | `p=example_domain_key_value` |

## Add MX SPF Record

1. Create a subdomain with the custom path name. Return to **Manage Websites** page. Click **Add Website**.
   <img alt="DreamHost Website" />
2. Click **Manage** on the subdomain.
3. **Add Record** > Select **MX** > **Manage Customer MX**.
4. Copy and paste the MX value replacing the default record.
   <img alt="Domain Details" />

<img alt="DreamHost Website" />

Below is a mapping of the record fields from Resend to DreamHost:

| DreamHost | Resend   | Example Value                           |
| --------- | -------- | --------------------------------------- |
| Type      | Type     | `MX Record`                             |
| Host      | Name     | `send`                                  |
| Points to | Content  | `feedback-smtp.us-east-1.amazonses.com` |
| Priority  | Priority | `10`                                    |

<Info>MX record will differ depending on your selected sending region.</Info>

<Info>
  Do not use the same priority for multiple MX records. If Priority `10` is
  already in use, try a higher value such as `20` or `30`.
</Info>

## Receiving Emails

If you want to receive emails at your domain, toggle the "Receiving" switch on the domain details page.

<img alt="Enable Receiving Emails for a verified domain" />

<Warning>
  When you enable Inbound on a domain, Resend receives *all emails* sent to that
  specific domain depending on the priority of the MX record. For this reason,
  we strongly recommend verifying a subdomain (`subdomain.example.com`) instead
  of the root domain (`example.com`). Learn more about [avoiding conflicts with
  your existing MX
  records](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
</Warning>

Add an MX record for receiving:

1. Click the **Add Record** button.
2. Hover over the **MX Record** section and click **ADD**.
3. Enter `inbound` (or your receiving subdomain) in the **Host** field.
4. Copy the MX Value from Resend into the **Points to** field.
5. Enter `10` for **Priority**.
6. Click **Add Record** to save.

Below is a mapping of the record fields from Resend to DreamHost:

| DreamHost | Resend   | Example Value                          |
| --------- | -------- | -------------------------------------- |
| Type      | Type     | `MX Record`                            |
| Host      | Name     | `inbound`                              |
| Points to | Content  | `inbound-smtp.us-east-1.amazonaws.com` |
| Priority  | Priority | `10`                                   |

After verifying your domain, create a webhook to process incoming emails. For help setting up a webhook, how to access email data and attachments, forward emails, and more, see [our guide on receiving emails with Resend](/docs/dashboard/receiving/introduction).

## Complete Verification

Now click [Verify DNS Records](https://resend.com/domains) on your Domain in Resend. It may take up to 72 hours to complete the verification process (often much faster). DNS updates at DreamHost can take several hours to propagate.

## Troubleshooting

If your domain is not successfully verified, these are some common troubleshooting methods.

<AccordionGroup>
  <Accordion title="Resend shows my domain verification failed.">
    Review the records you added to DreamHost to rule out copy and paste errors.
    Ensure the **Host** field uses only the subdomain (e.g., `send` or
    `resend._domainkey`) and that you did not include the full domain name.
  </Accordion>

  <Accordion title="It has been longer than 72 hours and my domain is still Pending.">
    [Review our guide on a domain not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying).
  </Accordion>
</AccordionGroup>


# Embed the React Email editor in your app
Source: https://resend.com/docs/knowledge-base/embed-react-email-editor

Add the open-source React Email editor to your application: base component, styling, Inspector sidebar, and custom extensions.

The [React Email editor](https://react.email/docs/editor/overview) is an open-source visual editor that lets your users author email templates inside your own product. It ships with bubble menus, slash commands, an Inspector sidebar, and extensible nodes. It also exports email-ready HTML you can hand straight to Resend.

This guide walks through embedding the editor in a React app, styling it to match your brand, customizing the Inspector Sidebar, and adding your own custom node.

<YouTube />

## Prerequisites

* A React 18+ application (for example, Vite, Next.js, or Remix)
* A bundler with [package exports](https://nodejs.org/api/packages.html#exports) support (the defaults for the frameworks above)

<Steps>
  <Step title="Install the editor">
    Install `@react-email/editor` and import the bundled theme stylesheet once at your app root.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install @react-email/editor
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add @react-email/editor
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add @react-email/editor
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add @react-email/editor
      ```
    </CodeGroup>

    ```tsx app/layout.tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
    import '@react-email/editor/themes/default.css';
    ```

    The bundled theme covers the bubble menus, slash commands, and Inspector. If you only use a subset, you can [import individual stylesheets](https://react.email/docs/editor/getting-started#import-css) instead.
  </Step>

  <Step title="Mount the base editor">
    The fastest path is the standalone `EmailEditor` component. It comes with the default extensions, bubble menus, slash commands, and theming wired up.

    ```tsx app/components/Editor.tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
    'use client';

    import { EmailEditor } from '@react-email/editor';

    const initialContent = `
      <h1>Welcome</h1>
      <p>Type "/" for a command, or select text to format it.</p>
    `;

    export function Editor() {
      return <EmailEditor content={initialContent} />;
    }
    ```

    `content` accepts an HTML string or a TipTap JSON document. See the [`EmailEditor` API reference](https://react.email/docs/editor/api-reference/email-editor) for the full prop list.

    <Tip>
      If you need full control over which extensions load, the provider layout, or
      the UI overlays, drop down to the [lower-level
      setup](https://react.email/docs/editor/getting-started#lower-level-setup) with
      `EditorProvider` from `@tiptap/react`.
    </Tip>
  </Step>

  <Step title="Style the editor">
    The editor exposes two layers of styling:

    1. **Editor chrome** (bubble menus, slash command palette, Inspector controls) — driven by CSS custom properties (`--re-*`) and `data-re-*` attribute selectors.
    2. **Editor content** (what the user is typing) — uses TipTap's `.tiptap` root class. Note that styling here only affects the in-editor preview; the exported HTML is styled by the [theming system](https://react.email/docs/editor/features/theming).

    Override the CSS variables on a wrapper class to apply your brand:

    ```css app/styles/editor.css theme={"theme":{"light":"github-light","dark":"vesper"}}
    .brand-editor {
      --re-bg: #fafaf9;
      --re-border: #d6d3d1;
      --re-text: #1c1917;
      --re-text-muted: #78716c;
      --re-hover: rgba(28, 25, 23, 0.04);
      --re-active: rgba(28, 25, 23, 0.08);
      --re-radius: 0.5rem;
      --re-radius-sm: 0.25rem;
    }

    /* Target a specific bubble menu button */
    [data-re-bubble-menu-item][data-active] {
      background: #2563eb;
      color: #fff;
    }

    /* Style the user's content area inside the editor */
    .tiptap h1 {
      font-size: 1.75rem;
      letter-spacing: -0.025em;
    }
    ```

    ```tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
    <div className="brand-editor">
      <EmailEditor content={initialContent} />
    </div>
    ```

    The default theme also responds to `prefers-color-scheme: dark` and to a `.dark` class on any ancestor — so it works with libraries like `next-themes` out of the box. See the [Styling reference](https://react.email/docs/editor/features/styling) for the complete list of variables, `data-re-*` selectors, and content classes.
  </Step>

  <Step title="Add the Inspector Sidebar">
    The Inspector is a contextual sidebar that swaps panels based on the user's current selection — document defaults when nothing is focused, node properties when a block is selected, text formatting when text is selected.

    Pass `Inspector.Root` as a child of `EmailEditor` so it shares the editor's context:

    ```tsx app/components/Editor.tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
    'use client';

    import { EmailEditor } from '@react-email/editor';
    import { Inspector } from '@react-email/editor/ui';

    export function Editor() {
      return (
        <div className="flex" style={{ height: '600px' }}>
          <EmailEditor
            content="<h1>Hello</h1><p>Click any element to inspect it.</p>"
            className="flex-1 min-w-0 overflow-y-auto p-4"
          >
            <Inspector.Root className="w-72 shrink-0 border-l p-4 overflow-y-auto">
              <Inspector.Breadcrumb />
              <Inspector.Document />
              <Inspector.Node />
              <Inspector.Text />
            </Inspector.Root>
          </EmailEditor>
        </div>
      );
    }
    ```

    See the [Inspector reference](https://react.email/docs/editor/features/inspector) for every render-prop helper, the full list of reusable section components (`Inspector.Size`, `Inspector.Padding`, `Inspector.Border`, `Inspector.Typography`, `Inspector.Background`, `Inspector.Link`), and runnable examples.
  </Step>

  <Step title="Add a custom extension">
    Custom blocks use `EmailNode`, which extends TipTap's `Node` with the `renderToReactEmail` method so the same node renders correctly inside the editor and in the exported email.

    <Info>
      See [Custom
      Extensions](https://react.email/docs/editor/advanced/custom-extensions) for
      the full API and a worked example.
    </Info>
  </Step>

  <Step title="Send the result with Resend">
    If you use the standalone `EmailEditor` component, you can access the email HTML and plain text through ref methods. In your handler, send the HTML to Resend using the [Send Email](/docs/api-reference/emails/send-email) or [Send Batch Emails](/docs/api-reference/emails/send-batch-emails) API.

    ```tsx theme={"theme":{"light":"github-light","dark":"vesper"}} theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { EmailEditor, type EmailEditorRef } from '@react-email/editor';
    import { useRef, useState } from 'react';

    export function MyEditor() {
      const ref = useRef<EmailEditorRef>(null);

      const handleExport = async () => {
        if (!ref.current) return;
        const html = await ref.current.getEmailHTML();
        // Send email using Resend using a server-side API endpoint/action
        const response = await fetch('/api/send-email', {
          method: 'POST',
          body: JSON.stringify({ html }),
        });
      };

      return (
        <div>
          <EmailEditor ref={ref} content="<p>Edit me</p>" />
          <button onClick={handleExport}>Export HTML</button>
        </div>
      );
    }
    ```

    The ref exposes three export methods:

    | Method           | Returns                   | Description           |
    | ---------------- | ------------------------- | --------------------- |
    | `getEmailHTML()` | `Promise<string>`         | Email-ready HTML      |
    | `getEmailText()` | `Promise<string>`         | Plain text version    |
    | `getEmail()`     | `Promise<{ html, text }>` | Both in a single call |

    All three use [composeReactEmail](https://react.email/docs/editor/api-reference/compose-react-email) under the hood.

    <Info>
      See [Email Export docs](https://react.email/docs/editor/features/email-export)
      for more information on the export methods.
    </Info>
  </Step>
</Steps>

## Next steps

<CardGroup>
  <Card title="React Email editor reference" icon="book" href="https://react.email/docs/editor/overview">
    The complete API surface — extensions, UI components, theming, and image
    upload.
  </Card>

  <Card title="Editor styling reference" icon="palette" href="https://react.email/docs/editor/features/styling">
    Every CSS variable and `data-re-*` selector you can target.
  </Card>

  <Card title="Custom extensions" icon="code" href="https://react.email/docs/editor/advanced/custom-extensions">
    Wrap existing TipTap extensions or build new email-safe nodes and marks.
  </Card>

  <Card title="Template emails with React Email" icon="pen-to-square" href="/knowledge-base/template-emails-with-react-email">
    Author templates as `.tsx` files and upload them to Resend with the CLI.
  </Card>
</CardGroup>


# How to set up E2E testing with Playwright
Source: https://resend.com/docs/knowledge-base/end-to-end-testing-with-playwright

End to end testing ensures your entire app flow is fully functioning.

Below is a basic guide on setting up E2E testing with NextJS, Resend, and Playwright.

Prefer watching a video? Check out our video walkthrough below.

<YouTube />

## Guide

<Steps>
  <Step title="Create an endpoint">
    For simplicity, we'll create a GET endpoint that sends an email to the testing account, `delivered@resend.dev` on fetch.

    ```ts app/api/send/route.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { Resend } from 'resend';
    const resend = new Resend(process.env.RESEND_API_KEY);

    export async function GET() {
      try {
        const { data, error } = await resend.emails.send({
          from: 'Acme <onboarding@resend.dev>',
          to: ['delivered@resend.dev'],
          subject: 'Hello world',
          html: '<h1>Hello world</h1>',
        });

        if (error) {
          return Response.json({ error }, { status: 500 });
        }

        return Response.json({ data });
      } catch (error) {
        return Response.json({ error }, { status: 500 });
      }
    }
    ```
  </Step>

  <Step title="Write the test spec file">
    Create a test spec file at `e2e/app.spec.ts`. You can test in two ways: by calling the Resend API or by mocking a response.

    Calling the Resend API tests the entire API flow, including Resend's API responses, but counts towards your account's sending quota.

    ```ts e2e/app.spec.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { test, expect } from '@playwright/test';

    test('does not mock the response and calls the Resend API', async ({
      page,
    }) => {
      // Go to the page
      await page.goto('http://localhost:3000/api/send');

      // Assert that the response is visible
      await expect(page.getByText('id')).toBeVisible();
    });
    ```

    Mocking the response lets you test your app's flow without calling the Resend API and impacting your account's sending quota.

    ```ts e2e/app.spec.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { test, expect } from '@playwright/test';

    test("mocks the response and doesn't call the Resend API", async ({ page }) => {
      // Sample response from Resend
      const body = JSON.stringify({
        data: {
          id: '621f3ecf-f4d2-453a-9f82-21332409b4d2',
        },
      });

      // Mock the api call before navigating
      await page.route('*/**/api/send', async (route) => {
        await route.fulfill({
          body,
          contentType: 'application/json',
          status: 200,
        });
      });
    });
    ```

    <Note>
      However you test, it's important to test using a test email address (e.g.,
      [delivered@resend.dev](mailto:delivered@resend.dev)) so your tests don't impact your deliverability. Resend's
      [test accounts](/docs/dashboard/emails/send-test-emails) run through the entire API
      flow without harming your reputation.
    </Note>
  </Step>

  <Step title="Create a Playwright config file">
    Write your config file, paying special attention to a few properties:

    * `testDir`: the directory containing your test files
    * `outputDir`: the directory to store test results
    * `webServer`: provide instructions for Playwright to run your app before starting the tests
    * `projects`: an array of the browsers you want to test

    ```ts playwright.config.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { defineConfig, devices } from '@playwright/test';
    import path from 'path';

    const baseURL = 'http://localhost:3000';

    export default defineConfig({
      timeout: 30 * 1000,
      testDir: path.join(__dirname, 'e2e'),
      retries: 2,
      outputDir: 'test-results/',
      webServer: {
        command: 'npm run dev',
        url: baseURL,
        timeout: 120 * 1000,
        reuseExistingServer: !process.env.CI,
      },

      use: {
        baseURL,
        // Retry a test if its failing with enabled tracing. This allows you to analyze the DOM, console logs, network traffic etc.
        trace: 'retry-with-trace',
      },

      projects: [
        // Test against desktop browsers.
        {
          name: 'Desktop Chrome',
          use: {
            ...devices['Desktop Chrome'],
          },
        },
        {
          name: 'Desktop Firefox',
          use: {
            ...devices['Desktop Firefox'],
          },
        },
        {
          name: 'Desktop Safari',
          use: {
            ...devices['Desktop Safari'],
          },
        },
        // Test against mobile viewports.
        {
          name: 'Mobile Chrome',
          use: {
            ...devices['Pixel 5'],
          },
        },
        {
          name: 'Mobile Safari',
          use: devices['iPhone 12'],
        },
      ],
    });
    ```

    [See the Playwright docs](https://playwright.dev/docs/intro) for more help.
  </Step>

  <Step title="Run the test">
    You can run the test by installing Playwright and running the tests.

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    npx playwright install
    npx playwright test
    ```

    Playwright will run the tests in the browsers of your choice and show you the results.
  </Step>
</Steps>

## Examples

<Card title="Example repo" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-nextjs-playwright-example">
  See the full source code.
</Card>


# Forward emails with Resend Inbound
Source: https://resend.com/docs/knowledge-base/forward-emails-with-resend-inbound

Learn how to forward receiving emails to another email address with Resend Inbound.

Inbound enables you to receive emails with Resend.

This guide demonstrates how to forward received emails using [NextJS](https://nextjs.org/), although you can use any framework you prefer.

<Steps>
  <Step title="Verify a domain with Inbound">
    [Verify a domain](https://resend.com/domains) and enable receiving emails for that domain. We strongly recommend verifying a subdomain (`subdomain.example.com`) instead of the root domain (`example.com`).

    <img alt="Verify a domain with Inbound" />

    Add the records in your DNS provider and wait for verification to finish in Resend. Learn more about [adding Domains in Resend](/docs/dashboard/domains/introduction).

    <Warning>
      When you enable Inbound on a domain, Resend receives *all emails* sent to that
      specific domain depending on the priority of the MX record. For this reason,
      we strongly recommend verifying a subdomain (`subdomain.example.com`) instead
      of the root domain (`example.com`). Learn more about [avoiding conflicts with
      your existing MX
      records](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
    </Warning>
  </Step>

  <Step title="Create a POST route">
    Resend can send a webhook to your application's endpoint every time you receive an email.

    Add a new POST route to your application's endpoint.

    ```ts app/api/inbound-webhook/route.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import type { NextRequest } from 'next/server';
    import { NextResponse } from 'next/server';

    export const POST = async (request: NextRequest) => {
      try {
        const payload = await request.text();

        return NextResponse.json(payload);
      } catch (error) {
        console.error(error);
        return new NextResponse(`Error: ${error}`, { status: 500 });
      }
    };
    ```
  </Step>

  <Step title="Create a webhook in Resend">
    Go to the [Webhooks page](https://resend.com/webhooks) and click **Add Webhook**.

    1. Add your publicly accessible HTTPS URL.
    2. Select all events you want to observe (e.g., `email.received`).
    3. Click **Add**.

    <img alt="Create a webhook in Resend" />

    <Tip>
      For development, you can create a tunnel to your localhost server using a tool like
      [ngrok](https://ngrok.com/download) or [VS Code Port Forwarding](https://code.visualstudio.com/docs/debugtest/port-forwarding). These tools serve your local dev environment at a public URL you can use to test your local webhook endpoint.

      Example: `https://example123.ngrok.io/api/webhook`
    </Tip>
  </Step>

  <Step title="Add Resend to your project">
    Add the Resend Node.js SDK to your project using your preferred package manager.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install resend
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add resend
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add resend
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add resend
      ```
    </CodeGroup>

    Create an [API key with "Full access" permission](/docs/dashboard/api-keys/introduction) in Resend and add it to your project's .env file.

    ```env .env theme={"theme":{"light":"github-light","dark":"vesper"}}
    RESEND_API_KEY=re_xxxxxxxxx
    ```
  </Step>

  <Step title="Verify the webhook request">
    Webhook signing secrets are used to validate the payload data sent to your application from Resend.

    Update your POST route to verify the webhook request using the webhook secret. First, copy the webhook secret from the webhook details page.

    <img alt="Webhook Secret" />

    Then, add it to your project's .env file.

    ```env .env theme={"theme":{"light":"github-light","dark":"vesper"}}
    RESEND_WEBHOOK_SECRET=whsec_xxxxxxxxxx
    ```

    Update the POST route to verify the webhook request using the webhook secret.

    <Tip>
      Make sure that you’re using the raw request body when verifying webhooks. The cryptographic signature is sensitive to even the slightest change. Some frameworks parse the request as JSON and then stringify it, and this will also break the signature verification.
    </Tip>

    ```ts app/api/inbound-webhook/route.ts {3, 5, 12-32} theme={"theme":{"light":"github-light","dark":"vesper"}}
    import type { NextRequest } from 'next/server';
    import { NextResponse } from 'next/server';
    import { Resend } from 'resend';

    const resend = new Resend(process.env.RESEND_API_KEY);

    export async function POST(req: NextRequest) {
      try {
        // we need raw request text to verify the webhook
        const payload = await req.text();

        const id = req.headers.get('svix-id');
        const timestamp = req.headers.get('svix-timestamp');
        const signature = req.headers.get('svix-signature');

        if (!id || !timestamp || !signature) {
          return new NextResponse('Missing headers', { status: 400 });
        }

        // Throws an error if the webhook is invalid
        // Otherwise, returns the parsed payload object
        const result = resend.webhooks.verify({
          payload,
          headers: {
            id,
            timestamp,
            signature,
          },
          webhookSecret: process.env.RESEND_WEBHOOK_SECRET!,
        });

        return NextResponse.json(result);
      } catch (error) {
        console.error(error);
        return new NextResponse(`Error: ${error}`, { status: 500 });
      }
    }
    ```
  </Step>

  <Step title="Process incoming emails">
    Once you verify the webhook, it returns the webhook payload as a JSON object. You can use this payload to forward the email to another email address. Note the following steps:

    1. Add a guard clause to ensure the event type is `email.received`.
    2. Get the incoming email's content
    3. Download and encode any attachments
    4. Forward the email (remember to update the `from` and `to` addresses below)

    <Info>
      Webhooks do not include the email body, headers, or attachments, only their
      metadata. You must call the [Received emails
      API](/docs/api-reference/emails/retrieve-received-email) or the [Attachments
      API](/docs/api-reference/emails/list-received-email-attachments) to retrieve them.
      This design choice supports large attachments in serverless environments that
      have limited request body sizes.
    </Info>

    ```ts app/api/inbound-webhook/route.ts {29, 34, 42, 67} theme={"theme":{"light":"github-light","dark":"vesper"}}
    import type { NextRequest } from 'next/server';
    import { NextResponse } from 'next/server';
    import { Resend, type ListAttachmentsResponseSuccess } from 'resend';

    const resend = new Resend(process.env.RESEND_API_KEY);

    export async function POST(req: NextRequest) {
      try {
        const payload = await req.text();

        const id = req.headers.get('svix-id');
        const timestamp = req.headers.get('svix-timestamp');
        const signature = req.headers.get('svix-signature');

        if (!id || !timestamp || !signature) {
          return new NextResponse('Missing headers', { status: 400 });
        }

        const result = resend.webhooks.verify({
          payload,
          headers: {
            id,
            timestamp,
            signature,
          },
          webhookSecret: process.env.RESEND_WEBHOOK_SECRET!,
        });

        // 1. Add a guard clause to ensure the event type is `email.received`.
        if (result.type !== 'email.received') {
          return NextResponse.json({ message: 'Invalid event' }, { status: 200 });
        }

        // 2. Get the incoming email's content
        const { data: email, error: emailError } =
          await resend.emails.receiving.get(result.data.email_id);

        if (emailError) {
          throw new Error(`Failed to fetch email: ${emailError.message}`);
        }

        // 3. Download and encode any attachments
        const { data: attachmentsData, error: attachmentsError } =
          await resend.emails.receiving.attachments.list({
            emailId: result.data.email_id,
          });

        if (attachmentsError) {
          throw new Error(
            `Failed to fetch attachments: ${attachmentsError.message}`,
          );
        }

        const attachments =
          attachmentsData?.data as ListAttachmentsResponseSuccess['data'] &
            { content: string }[];

        if (attachments && attachments.length > 0) {
          // download the attachments and encode them in base64
          for (const attachment of attachments) {
            const response = await fetch(attachment.download_url);
            const buffer = Buffer.from(await response.arrayBuffer());
            attachment.content = buffer.toString('base64');
          }
        }

        // 4. Forward the email
        const { data, error: sendError } = await resend.emails.send({
          from: 'onboarding@resend.dev', // replace with an email address from your verified domain
          to: ['delivered@resend.dev'], // replace with the email address you want to forward the email to
          subject: result.data.subject,
          html: email.html,
          text: email.text,
          attachments,
        });

        if (sendError) {
          throw new Error(`Failed to forward email: ${sendError.message}`);
        }

        return NextResponse.json({ message: 'Email forwarded successfully', data });
      } catch (error) {
        console.error(error);
        return new NextResponse(`Error: ${error}`, { status: 500 });
      }
    }
    ```
  </Step>

  <Step title="Test the endpoint">
    You can test the endpoint by sending an email to the domain you verified.

    For example, if you verified `marketing.example.com`, send an email to `test@marketing.example.com`.

    * Try a simple HTML email with a subject and a body.
    * Try an email with an attachment or multiple attachments.

    You can view the received email in the [Emails page](https://resend.com/emails/receiving) and see the webhook payload in the [Webhooks page](https://resend.com/webhooks).
  </Step>

  <Step title="Go to Production">
    Once you've tested the endpoint:

    1. Publish your application to your production environment.
    2. Add your production POST endpoint as a new webhook in Resend.
  </Step>
</Steps>


# Gandi
Source: https://resend.com/docs/knowledge-base/gandi

Verify your domain on Gandi with Resend.

## Add Domain to Resend

First, log in to your [Resend Account](https://resend.com/login) and [add a domain](https://resend.com/domains).

<img alt="Domain Details" />

<Tip>
  It is [best practice to use a
  subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain)
  (updates.example.com) instead of the root domain (example.com). Using a
  subdomain allows for proper reputation segmentation based on topics or purpose
  (e.g. marketing) and is especially important if receiving emails with Resend.
</Tip>

## Log in to Gandi

Log in to your [Gandi account](https://admin.gandi.net/domain/):

1. Choose your Domain from the `Domain` list.
2. Select the `DNS Records` tab to get to the page to manage DNS records.

<img alt="Domain Details" />

## Add MX SPF Record

Select “Add record” on Gandi to copy and paste the values MX from Resend.

1. On the `Type` page, choose `MX`.
2. Use the default TTL of `10800`.
3. Type `send` for the `Name` of the record.
4. Use the default `Priority` of `10`.
5. Copy the MX Value from Resend into the `Hostname` field.
6. Select `Create`.

<Info>
  Gandi requires your MX record to have a trailing period when adding. Resend
  will include the trailing period when copying. Removing the period will cause
  the verification to fail.
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Gandi:

| Gandi    | Resend   | Example Value                            |
| -------- | -------- | ---------------------------------------- |
| Type     | Type     | `MX Record`                              |
| Name     | Name     | `send`                                   |
| Hostname | Content  | `feedback-smtp.us-east-1.amazonses.com.` |
| TTL      | -        | `10800`                                  |
| Priority | Priority | `10`                                     |

<Info>
  Do not use the same priority for multiple records. If Priority `10` is already
  in use on another record, try a higher value `20` or `30`.
</Info>

## Add TXT SPF Record

In the same section, select “Add record” again.

1. On the `Type` page, choose `TXT`.
2. Use the default TTL of `10800`.
3. Type `send` for the `Name` of the record.
4. Copy the TXT Value Resend into the `Text value` field.
5. Select `Create`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Gandi:

| Gandi      | Resend  | Example Value                         |
| ---------- | ------- | ------------------------------------- |
| Type       | Type    | `TXT Record`                          |
| Name       | Name    | `send`                                |
| Text value | Content | `"v=spf1 include:amazonses.com ~all"` |
| TTL        | -       | `10800`                               |

## Add TXT DKIM Records

In the same section, select “Add record” again.

1. On the `Type` page, choose `TXT`.
2. Use the default TTL of `10800`.
3. Type `resend._domainkey` for the `Host name` of the record.
4. Copy the record value from Resend into the `TXT value` field.
5. Select `Create`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `resend._domainkey.example.com`, paste only `resend._domainkey` (or
  `resend._domainkey.subdomain` if you're using a subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Gandi:

| Gandi      | Resend  | Example Value                |
| ---------- | ------- | ---------------------------- |
| Type       | Type    | `TXT Record`                 |
| Name       | Name    | `send`                       |
| Text value | Content | `p=example_domain_key_value` |
| TTL        | -       | `1 hour`                     |

## Receiving Emails

If you want to receive emails at your domain, toggle the "Receiving" switch on the domain details page.

<img alt="Enable Receiving Emails for a verified domain" />

<Warning>
  When you enable Inbound on a domain, Resend receives *all emails* sent to that
  specific domain depending on the priority of the MX record. For this reason,
  we strongly recommend verifying a subdomain (`subdomain.example.com`) instead
  of the root domain (`example.com`). Learn more about [avoiding conflicts with
  your existing MX
  records](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
</Warning>

Select “Add record” on Gandi:

1. On the `Type` page, choose `MX`.
2. Use the default TTL of `10800`.
3. Type `inbound` (or whatever your subdomain is) for the `Name` of the record.
4. Use the default `Priority` of `10`.
5. Copy the MX Value from Resend into the `Hostname` field.
6. Select `Create`.

Below is a mapping of the record fields from Resend to Gandi:

| Gandi    | Resend   | Example Value                           |
| -------- | -------- | --------------------------------------- |
| Type     | Type     | `MX Record`                             |
| Name     | Name     | `inbound`                               |
| Hostname | Content  | `inbound-smtp.us-east-1.amazonaws.com.` |
| TTL      | -        | `10800`                                 |
| Priority | Priority | `10`                                    |

After verifying your domain, create a webhook to process incoming emails. For help setting up a webhook, how to access email data and attachments, forward emails, and more, see [our guide on receiving emails with Resend](/docs/dashboard/receiving/introduction).

## Complete Verification

Now click [Verify DNS Records](https://resend.com/domains) on your Domain in Resend. It may take a few hours to complete the verification process (often much faster).

## Troubleshooting

If your domain is not successfully verified, these are some common troubleshooting methods.

<AccordionGroup>
  <Accordion title="Resend shows my domain verification failed.">
    Review the records you added to Gandi to rule out copy and paste errors.
  </Accordion>

  <Accordion title="It has been longer than 72 hours and my domain is still Pending.">
    [Review our guide on a domain not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying).
  </Accordion>
</AccordionGroup>


# Get Started with Resend and Supabase
Source: https://resend.com/docs/knowledge-base/getting-started-with-resend-and-supabase

A quick jumpstart to using Resend with Supabase.

This guide helps you get started with Resend by:

* [Setting up Resend](#set-up-resend)
* [Send Auth Emails with Resend](#send-auth-emails-with-resend)
* [Send Emails with Supabase Edge Functions](#send-emails-with-supabase-edge-functions)

## Set up Resend

To send emails with your Supabase project, you'll need to first verify it in Resend.

Go to [the Domains page](https://resend.com/domains) and click on **Add Domain**.

1. Add your domain name. We recommend [using a subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain) like `updates.example.com` instead of the root domain.
2. Add the DNS records to your DNS provider ([learn more about these records](/docs/dashboard/domains/introduction)).
   <img alt="Resend Domains page" />
3. Click on **Verify DNS Records** to begin the verification process.
4. Wait for the verification to complete (usually takes 5–10 minutes)

<Info>
  Resend requires you own your domain (i.e., not a shared or public domain).
  Adding DNS records gives Resend the authority to send emails on your behalf
  and signals to the inbox providers that you're a legitimate sender.
</Info>

## Send Auth Emails with Resend

If you want to use Resend to send your Supabase Auth Emails, you have three options:

1. [Using the Resend Integration](#send-with-the-resend-integration): simplest, but less customizable email templates.
2. [Custom Auth Functions](#send-with-custom-auth-functions): more customizable email templates, but requires more setup.
3. [Self-hosted with custom SMTP](#send-with-custom-smtp-server-for-self-hosting): only for those self-hosting Supabase.

### Send with the Resend Integration

Resend includes a pre-built integration with Supabase. Connecting Resend as your email provider will allow you to send your Supabase emails (for example, password resets and email confirmations) through Resend.

<YouTube />

1. Open the [Resend Integrations settings](https://resend.com/settings/integrations).
2. Click **Connect to Supabase** and login to your Supabase account if prompted.
   <img alt="Resend Integrations settings" />
3. Select a project and click **Select Project**, then select your domain and click **Add API Key**. Resend will create an API key for you. Add a sender name and click **Configure SMTP Integration**.
   <img alt="Resend Integrations settings" />

Click on **Supabase Dashboard** to confirm the integration.

<img alt="Resend Integrations settings" />

<Info>
  Supabase has a rate limit on the number of emails you can send per hour and
  requires you to [connect a custom email provider for more than 2
  emails/hour](https://supabase.com/docs/guides/auth/rate-limits). Once you set
  Resend as your email provider, you can send additional emails (by default, 25
  emails/hour, although you can change the rate limit in your project's
  [authentication
  settings](https://supabase.com/docs/guides/deployment/going-into-prod#rate-limiting-resource-allocation--abuse-prevention)).
</Info>

### Send with custom auth functions

Benefit of using custom auth functions:

* More control over the email sending process since you control the sending function.
* More control over the email template using React Email or Resend Templates.

Note that this requires enabling [Supabase Auth Hooks](https://supabase.com/docs/guides/auth/auth-hooks).

<YouTube />

<Card title="Supabase Auth Hooks with Resend Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/supabase-auth-hooks-with-resend-templates">
  See the full source code.
</Card>

### Send with a custom SMTP server for self-hosting

If you're self-hosting Supabase, you can use a custom SMTP server to send your emails. [Learn more here](/docs/send-with-smtp).

## Send Emails with Supabase Edge Functions

If you're using Supabase Edge Functions, you can add email sending to your function by using the Resend Node.js SDK. You can use these functions for Auth Emails ([as shown above](#custom-auth-functions)) or for other emails (for example, app notifications and account activity).

First, make sure you have the latest version of the [Supabase CLI](https://supabase.com/docs/guides/cli#installation) installed.

<Steps>
  <Step title="Create Supabase function">
    Create a new function locally:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    supabase functions new resend
    ```
  </Step>

  <Step title="Edit the handler function">
    Paste the following code into the `index.ts` file:

    ```js index.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { serve } from "https://deno.land/std@0.168.0/http/server.ts";

    const RESEND_API_KEY = 're_xxxxxxxxx';

    const handler = async (_request: Request): Promise<Response> => {
        const res = await fetch('https://api.resend.com/emails', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${RESEND_API_KEY}`
            },
            body: JSON.stringify({
                from: 'Acme <onboarding@resend.dev>',
                to: ['delivered@resend.dev'],
                subject: 'hello world',
                html: '<strong>it works!</strong>',
            })
        });

        const data = await res.json();

        return new Response(JSON.stringify(data), {
            status: 200,
            headers: {
                'Content-Type': 'application/json',
            },
        });
    };

    serve(handler);
    ```
  </Step>

  <Step title="Deploy and send email">
    Run function locally:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    supabase functions start
    supabase functions serve resend --no-verify-jwt
    ```

    Deploy function to Supabase:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    supabase functions deploy resend
    ```

    Open the endpoint URL to send an email:

    <img alt="Supabase Edge Functions - Deploy Function" />
  </Step>
</Steps>

## Examples

<Card title="Supabase Edge Functions Example" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-supabase-edge-functions-example">
  See the full source code.
</Card>

## Get more help

If you have any questions, please let us know at [support@resend.com](mailto:support@resend.com).


# GoDaddy
Source: https://resend.com/docs/knowledge-base/godaddy

Verify your domain on GoDaddy with Resend.

## Add Domain to Resend

First, log in to your [Resend Account](https://resend.com/login) and [add a domain](https://resend.com/domains).

<img alt="Domain Details" />

<Tip>
  It is [best practice to use a
  subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain)
  (updates.example.com) instead of the root domain (example.com). Using a
  subdomain allows for proper reputation segmentation based on topics or purpose
  (e.g. marketing) and is especially important if receiving emails with Resend.
</Tip>

## Automatic Setup (Recommended)

The fastest way to verify your domain on GoDaddy is using the **Auto Configure** button on Resend. This uses Domain Connect to automatically configure your DNS records.

1. Go to your [Domains page](https://resend.com/domains) in Resend.
2. (Optional) If you want to receive emails, select `Manual setup` and toggle the "Receiving" switch on the domain details page. ([Learn more below](#receiving-emails))
3. Click **Auto Configure**.
4. Authorize Resend to access your GoDaddy DNS settings.
5. The DNS records will be added automatically.

<video aria-label="GoDaddy Domain Connect Setup" />

That's it. Your domain will be verified within a few minutes.

## Manual Setup

If you prefer to add DNS records manually, follow these steps.

### Log in to GoDaddy

Log in to your [GoDaddy account](https://sso.godaddy.com):

1. Select `DNS` from the left navigation
2. Find your domain in the list and select the domain
3. This will take you to the DNS management page for the domain

<img alt="Domain Details" />

## Add MX SPF Record

Copy and paste the values MX in Resend to GoDaddy.

1. Click `Add New Record` to create a new record
2. Set the Type to `MX`.
3. Type `send` for the `Name` of the record.
4. Copy the MX Value from Resend into the `Value` field.
5. Add `10` for the `Priority`.
6. Set the TTL to `600` (or use the default).
7. Click `Save`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to GoDaddy:

| GoDaddy  | Resend   | Example Value                           |
| -------- | -------- | --------------------------------------- |
| Type     | Type     | `MX Record`                             |
| Name     | Name     | `send`                                  |
| Value    | Content  | `feedback-smtp.us-east-1.amazonses.com` |
| TTL      | -        | `600` (or use default)                  |
| Priority | Priority | `10`                                    |

<Info>
  Do not use the same priority for multiple records. If Priority `10` is already
  in use on another record, try a higher value `20` or `30`.
</Info>

## Add TXT SPF Record

In the same section, add another record in GoDaddy.

1. Click `Add New Record` to create a new record
2. Set the Type to `TXT`.
3. Type `send` for the `Name` of the record.
4. Copy the TXT Value from Resend into the `Value` field.
5. Set the TTL to `600` (or use the default).
6. Click `Save`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to GoDaddy:

| GoDaddy | Resend  | Example Value                         |
| ------- | ------- | ------------------------------------- |
| Type    | Type    | `TXT Record`                          |
| Name    | Name    | `send`                                |
| Value   | Content | `"v=spf1 include:amazonses.com ~all"` |
| TTL     | -       | `600` (or use default)                |

## Add TXT DKIM Records

In the same section, add another record in GoDaddy.

1. Click `Add New Record` to create a new record
2. Set the Type to `TXT`.
3. Type `resend._domainkey` for the `Name` of the record.
4. Copy the record value from Resend into the `Value` field.
5. Set the TTL to `600` (or use the default).
6. Click `Save`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `resend._domainkey.example.com`, paste only `resend._domainkey` (or
  `resend._domainkey.subdomain` if you're using a subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to GoDaddy:

| GoDaddy | Resend  | Example Value                |
| ------- | ------- | ---------------------------- |
| Type    | Type    | `TXT Record`                 |
| Name    | Name    | `resend._domainkey`          |
| Value   | Content | `p=example_domain_key_value` |
| TTL     | -       | `600` (or use default)       |

## Receiving Emails

If you want to receive emails at your domain, toggle the "Receiving" switch on the domain details page.

<img alt="Enable Receiving Emails for a verified domain" />

<Warning>
  When you enable Inbound on a domain, Resend receives *all emails* sent to that
  specific domain depending on the priority of the MX record. For this reason,
  we strongly recommend verifying a subdomain (`subdomain.example.com`) instead
  of the root domain (`example.com`). Learn more about [avoiding conflicts with
  your existing MX
  records](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
</Warning>

Click `Add New Record` to create a new record:

1. Set the Type to `MX`.
2. Type `inbound` (or whatever your subdomain is) for the `Name` of the record.
3. Copy the MX Value from Resend into the `Value` field.
4. Add `10` for the `Priority`.
5. Set the TTL to `600` (or use the default).
6. Click `Save`.

Below is a mapping of the record fields from Resend to GoDaddy:

| GoDaddy  | Resend   | Example Value                          |
| -------- | -------- | -------------------------------------- |
| Type     | Type     | `MX Record`                            |
| Name     | Name     | `inbound`                              |
| Value    | Content  | `inbound-smtp.us-east-1.amazonaws.com` |
| TTL      | -        | `600` (or use default)                 |
| Priority | Priority | `10`                                   |

After verifying your domain, create a webhook to process incoming emails. For help setting up a webhook, how to access email data and attachments, forward emails, and more, see [our guide on receiving emails with Resend](/docs/dashboard/receiving/introduction).

## Complete Verification

Now click [Verify DNS Records](https://resend.com/domains) on your Domain in Resend. It may take a few hours to complete the verification process (often much faster).

## Troubleshooting

If your domain is not successfully verified, these are some common troubleshooting methods.

<AccordionGroup>
  <Accordion title="Resend shows my domain verification failed.">
    Review the records you added to GoDaddy to rule out copy and paste errors.
  </Accordion>

  <Accordion title="It has been longer than 72 hours and my domain is still Pending.">
    [Review our guide on a domain not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying).
  </Accordion>
</AccordionGroup>


# Hetzner
Source: https://resend.com/docs/knowledge-base/hetzner

Verify your domain on Hetzner with Resend.

## Add Domain to Resend

First, log in to your [Resend Account](https://resend.com/login) and [add a domain](https://resend.com/domains).

<img alt="Domain Details" />

<Tip>
  It is [best practice to use a
  subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain)
  (updates.example.com) instead of the root domain (example.com). Using a
  subdomain allows for proper reputation segmentation based on topics or purpose
  (e.g. marketing) and is especially important if receiving emails with Resend.
</Tip>

## Log in to Hetzner Console

This section covers accessing the new Hetzner Console for managing DNS records. If your domain is still using the legacy Hetzner DNS console, please skip to the [Log in to Hetzner DNS Console](#log-in-to-hetzner-dns-console) section below.

Log in to [Hetzner Console](https://console.hetzner.com/):

1. Choose your project from the `Projects` list.
2. Click on the `DNS` link from the `Networking` section of the side navigation.
3. Choose your Domain from the `DNS zones` list.

<img alt="Domain Details" />

## Log in to Hetzner DNS Console

This section covers accessing the legacy Hetzner DNS Console. Hetzner recently created the new Hetzner Console for managing DNS records. If your domain is using the new Hetzner console, please go to the [Log in to Hetzner Console](#log-in-to-hetzner-console) section above then skip to the [Add MX SPF Record](#add-mx-spf-record) section.

Log in to [Hetzner DNS Console](https://dns.hetzner.com):

1. Choose your Domain from the `Your Zones` list.
2. Select the `Records` tab to get to the page to manage DNS records.

<img alt="Domain Details" />

## Add MX SPF Record

In the `Add Record` section on Hetzner copy and paste the values MX from Resend:

1. For the `Type` field, choose `MX`.
2. For the `Name` field, type `send` (or `send.subdomain` if you're using a subdomain).
3. For the `Priority` field, set the value to `10`.
4. For the `Value` field, add the MX SPF Record `Content` from Resend.
5. For the `TTL` field, set the value to `1800`.
6. Select `Add`.

<Info>
  Hetzner requires your MX record to have a trailing period when adding. Resend
  will include the trailing period when copying. Removing the period will cause
  the verification to fail.
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Hetzner Console:

| Hetzner  | Resend   | Example Value                            |
| -------- | -------- | ---------------------------------------- |
| Type     | Type     | `MX Record`                              |
| Name     | Name     | `send.subdomain`                         |
| Value    | Content  | `feedback-smtp.us-east-1.amazonses.com.` |
| TTL      | TTL      | `1800`                                   |
| Priority | Priority | `10`                                     |

<Info>
  Do not use the same priority for multiple records. If Priority `10` is already
  in use on another record, try a higher value `20` or `30`.
</Info>

## Add TXT SPF Record

On the same `Add Record` section:

1. For the `Type` field, choose `TXT`.
2. For the `Name` field, type `send` (or `send.subdomain` if you're using a subdomain).
3. For the `Value` field, add the TXT SPF Record `Content` from Resend.
4. For the `TTL` field, set the value to `1800`.
5. Select `Add`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Hetzner:

| Hetzner | Resend  | Example Value                         |
| ------- | ------- | ------------------------------------- |
| Type    | Type    | `TXT Record`                          |
| Name    | Name    | `send.subdomain`                      |
| Value   | Content | `"v=spf1 include:amazonses.com ~all"` |
| TTL     | TTL     | `10800`                               |

## Add TXT DKIM Records

On the same `Add Record` section:

1. For the `Type` field, choose `TXT`.
2. For the `Name` field, type `resend._domainkey` (or `resend._domainkey.subdomain` if you're using a subdomain).
3. For the `Value` field, add the TXT DKIM Record `Content` from Resend.
4. For the `TTL` field, set the value to `1800`.
5. Select `Add`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `resend._domainkey.example.com`, paste only `resend._domainkey` (or
  `resend._domainkey.subdomain` if you're using a subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Hetzner:

| Hetzner | Resend  | Example Value                |
| ------- | ------- | ---------------------------- |
| Type    | Type    | `TXT Record`                 |
| Name    | Name    | `send.subdomain`             |
| Value   | Content | `p=example_domain_key_value` |
| TTL     | TTL     | `1 hour`                     |

## Receiving Emails

If you want to receive emails at your domain, toggle the "Receiving" switch on the domain details page.

<img alt="Enable Receiving Emails for a verified domain" />

<img alt="Domain Details" />

<Warning>
  When you enable Inbound on a domain, Resend receives *all emails* sent to that
  specific domain depending on the priority of the MX record. For this reason,
  we strongly recommend verifying a subdomain (`subdomain.example.com`) instead
  of the root domain (`example.com`). Learn more about [avoiding conflicts with
  your existing MX
  records](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
</Warning>

In the `Add Record` section on Hetzner:

1. For the `Type` field, choose `MX`.
2. For the `Name` field, type `@` for the base domain or the name of the subdomain if you're using a subdomain.
3. For the `Priority` field, set the value to `10`.
4. For the `Value` field, add the Receiving MX Record `Content` from Resend.
5. For the `TTL` field, set the value to `1800`.
6. Select `Add`.

Below is a mapping of the record fields from Resend to Hetzner:

| Hetzner     | Resend   | Example Value                           |
| ----------- | -------- | --------------------------------------- |
| Type        | Type     | `MX Record`                             |
| Name        | Name     | `subdomain`                             |
| Mail server | Content  | `inbound-smtp.us-east-1.amazonaws.com.` |
| TTL         | TTL      | `1800`                                  |
| Priority    | Priority | `10`                                    |

After verifying your domain, create a webhook to process incoming emails. For help setting up a webhook, how to access email data and attachments, forward emails, and more, see [our guide on receiving emails with Resend](/docs/dashboard/receiving/introduction).

## Complete Verification

Now click [Verify DNS Records](https://resend.com/domains) on your Domain in Resend. It may take a few hours to complete the verification process (often much faster).

## Troubleshooting

If your domain is not successfully verified, these are some common troubleshooting methods.

<AccordionGroup>
  <Accordion title="Resend shows my domain verification failed.">
    Review the records you added to Hetzner to rule out copy and paste errors.
  </Accordion>

  <Accordion title="It has been longer than 72 hours and my domain is still Pending.">
    [Review our guide on a domain not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying).
  </Accordion>
</AccordionGroup>


# Hostinger
Source: https://resend.com/docs/knowledge-base/hostinger

Verify your domain on Hostinger with Resend.

## Add Domain to Resend

First, log in to your [Resend Account](https://resend.com/login) and [add a domain](https://resend.com/domains).

<img alt="Domain Details" />

<Tip>
  It is [best practice to use a
  subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain)
  (updates.example.com) instead of the root domain (example.com). Using a
  subdomain allows for proper reputation segmentation based on topics or purpose
  (e.g. marketing) and is especially important if receiving emails with Resend.
</Tip>

## Log in to Hostinger

Log in to your [Hostinger account](https://auth.hostinger.com/login):

1. Select the `Domains` tab
2. Choose your Domain from the `Domain portfolio` list.
3. Select the `DNS / Nameservers` to get to the page to manage DNS records.

<img alt="Domain Details" />

## Add MX SPF Record

Copy and paste the values MX in Resend to Hostinger.

1. Set the Type to `MX`.
2. Type `send` for the `Name` of the record.
3. Copy the MX Value from Resend into the `Mail Server` field.
4. Add `10` for the `Priority`.
5. Set the TTL to `3600`.
6. Select `Add Record`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Hostinger:

| Hostinger   | Resend   | Example Value                           |
| ----------- | -------- | --------------------------------------- |
| Type        | Type     | `MX Record`                             |
| Name        | Name     | `send`                                  |
| Mail Server | Content  | `feedback-smtp.us-east-1.amazonses.com` |
| TTL         | -        | `Set to 3660`                           |
| Priority    | Priority | `10`                                    |

<Info>
  Do not use the same priority for multiple records. If Priority `10` is already
  in use on another record, try a higher value `20` or `30`.
</Info>

## Add TXT SPF Record

In the same section, add another record in Hostinger.

1. Set the Type to `TXT`.
2. Type `send` for the `Name` of the record.
3. Copy the TXT Value Resend into the `TXT value` field.
4. Set the TTL to `3600`.
5. Select `Add Record`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Hostinger:

| Hostinger | Resend  | Example Value                         |
| --------- | ------- | ------------------------------------- |
| Type      | Type    | `TXT Record`                          |
| Name      | Name    | `send`                                |
| TXT value | Content | `"v=spf1 include:amazonses.com ~all"` |
| TTL       | -       | `Set to 3600`                         |

## Add TXT DKIM Records

In the same section, add another record in Hostinger.

1. Set the Type to `TXT`.
2. Type `resend._domainkey` for the `Name` of the record.
3. Copy the record value from Resend into the `TXT value` field.
4. Set the TTL to `3600`.
5. Select `Add Record`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `resend._domainkey.example.com`, paste only `resend._domainkey` (or
  `resend._domainkey.subdomain` if you're using a subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Hostinger:

| Hostinger | Resend  | Example Value                |
| --------- | ------- | ---------------------------- |
| Type      | Type    | `TXT Record`                 |
| Name      | Name    | `send`                       |
| TXT value | Content | `p=example_domain_key_value` |
| TTL       | -       | `Set to 3600`                |

## Receiving Emails

If you want to receive emails at your domain, toggle the "Receiving" switch on the domain details page.

<img alt="Enable Receiving Emails for a verified domain" />

<Warning>
  When you enable Inbound on a domain, Resend receives *all emails* sent to that
  specific domain depending on the priority of the MX record. For this reason,
  we strongly recommend verifying a subdomain (`subdomain.example.com`) instead
  of the root domain (`example.com`). Learn more about [avoiding conflicts with
  your existing MX
  records](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
</Warning>

Copy and paste the values MX in Resend to Hostinger:

1. Set the Type to `MX`.
2. Type `inbound` (or whatever your subdomain is) for the `Name` of the record.
3. Copy the MX Value from Resend into the `Mail Server` field.
4. Add `10` for the `Priority`.
5. Set the TTL to `3600`.
6. Select `Add Record`.

Below is a mapping of the record fields from Resend to Hostinger:

| Hostinger   | Resend   | Example Value                          |
| ----------- | -------- | -------------------------------------- |
| Type        | Type     | `MX Record`                            |
| Name        | Name     | `inbound`                              |
| Mail Server | Content  | `inbound-smtp.us-east-1.amazonaws.com` |
| TTL         | -        | `Set to 3660`                          |
| Priority    | Priority | `10`                                   |

After verifying your domain, create a webhook to process incoming emails. For help setting up a webhook, how to access email data and attachments, forward emails, and more, see [our guide on receiving emails with Resend](/docs/dashboard/receiving/introduction).

## Complete Verification

Now click [Verify DNS Records](https://resend.com/domains) on your Domain in Resend. It may take a few hours to complete the verification process (often much faster).

## Troubleshooting

If your domain is not successfully verified, these are some common troubleshooting methods.

<AccordionGroup>
  <Accordion title="Resend shows my domain verification failed.">
    Review the records you added to Hostinger to rule out copy and paste errors.
  </Accordion>

  <Accordion title="It has been longer than 72 hours and my domain is still Pending.">
    [Review our guide on a domain not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying).
  </Accordion>
</AccordionGroup>


# How to change your Resend email address
Source: https://resend.com/docs/knowledge-base/how-can-i-change-my-email-address

How to change the email address associated with your Resend account.

To change the email address associated with your Resend account:

1. Navigate to your [**Profile**](https://resend.com/profile) page.
2. Under **Your email**, enter your new email address in the **Email address** field.
3. Click the **Update email** button.

After clicking **Update email**, you will be signed out and two confirmation emails will be sent:

* **To your new email address**: An email with the subject "Confirm email change for Resend" asking you to confirm the update.
* **To your current email address**: An email with the subject "Request to change your email" asking you to confirm the request.

Click the confirmation link in both emails to complete the email change. Once both confirmations are complete, you can log in with your new email address.


# How to delete your Resend account
Source: https://resend.com/docs/knowledge-base/how-can-i-delete-my-resend-account

How to request your Resend account and data to be deleted.

To delete your Resend account, navigate to your [Profile Settings](https://resend.com/profile) and scroll to the **Delete account** section.

If you're associated with any teams, you'll be automatically prompted to leave or delete them before you can delete your account. Once all teams are removed, you can proceed with account deletion.

After confirmation, your account and all associated data will be queued for permanent deletion.

<Warning>
  This action is not reversible, so please proceed with caution.
</Warning>

## Understanding Accounts vs Teams

A **Resend Account** is your login method (email address) used to access Resend. A **Resend Team** is the environment where your API keys, domains, and email data are stored.

* You can only have one Account, but you can be part of multiple Teams
* To delete your Account, you must first leave or delete all Teams you're associated with

## Deleting a Team

If you want to delete a team (rather than leaving it), see [How to delete your Resend team](/docs/knowledge-base/how-can-i-delete-my-team).


# How to delete your Resend team
Source: https://resend.com/docs/knowledge-base/how-can-i-delete-my-team

How to request your Resend team and team data to be deleted.

To request your Resend team and team data to be deleted:

1. Navigate to your [**Team Settings**](https://resend.com/settings/team).
2. Select the **Delete Team** button.

Upon confirmation, Resend will delete your team and all your team data.

<Note>
  If you are the last member of a team, you can also delete it by selecting
  **Leave Team** instead. The system will automatically delete the team when the
  last member leaves.
</Note>

<Warning>
  Please note that this action is not reversible, so please proceed with
  caution.
</Warning>


# Can You Receive Emails with Resend?
Source: https://resend.com/docs/knowledge-base/how-can-i-receive-emails-with-resend

Receive emails with webhooks and process content, attachments, forwarding, and replies.

Yes. Resend supports receiving emails (inbound) via webhooks.

With Receiving, you can:

* Receive incoming emails and get notified with the `email.received` webhook event.
* Retrieve full email content (HTML, text, headers) using the Receiving API.
* Process attachments using attachment metadata and temporary download URLs.

You can receive emails at:

* A Resend-managed `*.resend.app` receiving domain, or
* Your own custom domain by adding the required `MX` record.

See the full guide: [Receiving Emails](/docs/dashboard/receiving/introduction).


# Sender email addresses in Resend
Source: https://resend.com/docs/knowledge-base/how-do-I-create-an-email-address-or-sender-in-resend

Learn how sending from an email address works on Resend.

Resend does not require you to “create an email address”, “set up a sender identity”, or “add a from-address” before sending.

Once a domain is verified in your Resend account, you can send from any email address at that domain.

<Info>
  The email address you send from does not need to exist in another system.
  However, we recommend using addresses that can receive replies.
</Info>

## How to add the sender address

You add the sender address in the `from` field when you send the email.

To include a friendly name, use the format `"Your Name <sender@example.com>"`.

<CodeGroup>
  ```ts Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('re_xxxxxxxxx');

  await resend.emails.send({
    from: 'Acme <onboarding@example.com>',
    to: ['customer@example.com'],
    subject: 'Welcome to Acme',
    html: '<p>Thanks for signing up!</p>',
  });
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  $resend = Resend::client('re_xxxxxxxxx');

  $resend->emails->send([
    'from' => 'Acme <onboarding@example.com>',
    'to' => ['customer@example.com'],
    'subject' => 'Welcome to Acme',
    'html' => '<p>Thanks for signing up!</p>'
  ]);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import resend

  resend.api_key = "re_xxxxxxxxx"

  params: resend.Emails.SendParams = {
    "from": "Acme <onboarding@example.com>",
    "to": ["customer@example.com"],
    "subject": "Welcome to Acme",
    "html": "<p>Thanks for signing up!</p>"
  }

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

  ```rb Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "resend"

  Resend.api_key = "re_xxxxxxxxx"

  params = {
    "from": "Acme <onboarding@example.com>",
    "to": ["customer@example.com"],
    "subject": "Welcome to Acme",
    "html": "<p>Thanks for signing up!</p>"
  }

  sent = Resend::Emails.send(params)
  puts sent
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/resend/resend-go/v3"
  )

  func main() {
    ctx := context.TODO()
    client := resend.NewClient("re_xxxxxxxxx")

    params := &resend.SendEmailRequest{
        From:    "Acme <onboarding@example.com>",
        To:      []string{"customer@example.com"},
        Subject: "Welcome to Acme",
        Html:    "<p>Thanks for signing up!</p>",
    }

    sent, err := client.Emails.SendWithContext(ctx, params)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Id)
  }
  ```

  ```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
  use resend_rs::types::CreateEmailBaseOptions;
  use resend_rs::{Resend, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let resend = Resend::new("re_xxxxxxxxx");

    let from = "Acme <onboarding@example.com>";
    let to = ["customer@example.com"];
    let subject = "Welcome to Acme";
    let html = "<p>Thanks for signing up!</p>";

    let email = CreateEmailBaseOptions::new(from, to, subject)
      .with_html(html);

    let _email = resend.emails.send(email).await?;

    Ok(())
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import com.resend.*;

  public class Main {
      public static void main(String[] args) {
          Resend resend = new Resend("re_xxxxxxxxx");

          CreateEmailOptions params = CreateEmailOptions.builder()
                  .from("Acme <onboarding@example.com>")
                  .to("customer@example.com")
                  .subject("Welcome to Acme")
                  .html("<p>Thanks for signing up!</p>")
                  .build();

          CreateEmailResponse data = resend.emails().send(params);
      }
  }
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using Resend;

  IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

  var resp = await resend.EmailSendAsync( new EmailMessage()
  {
      From = "Acme <onboarding@example.com>",
      To = "customer@example.com",
      Subject = "Welcome to Acme",
      HtmlBody = "<p>Thanks for signing up!</p>",
  } );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST 'https://api.resend.com/emails' \
       -H 'Authorization: Bearer re_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@example.com>",
    "to": ["customer@example.com"],
    "subject": "Welcome to Acme",
    "html": "<p>Thanks for signing up!</p>"
  }'
  ```

  ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
  resend emails send \
    --from "Acme <onboarding@example.com>" \
    --to customer@example.com \
    --subject "Welcome to Acme" \
    --html "<p>Thanks for signing up!</p>"
  ```
</CodeGroup>

In this example, `onboarding@example.com` is the sender address. As long as `example.com` is verified in Resend, you can use that address in `from` without creating it first.

## Common misconceptions

Some platforms require you to create, register, or pre-approve a sending address.\
Resend does not. After verifying your domain, you’re free to send from any address at that domain, such as `notifications@example.com` or `updates@example.com`. No extra setup, creation, or configuration of that address is needed.

## Getting started

To start sending emails with Resend:

1. [Sign up for a Resend account](https://resend.com/signup)
2. [Add and verify your domain](https://resend.com/domains)
3. [Create an API key](https://resend.com/api-keys)
4. Start sending emails immediately from any address at the domain you verified

If you're having trouble with domain verification or DNS records, see our [domain verification troubleshooting guide](/docs/knowledge-base/what-if-my-domain-is-not-verifying) or check our [DNS setup guides](/docs/knowledge-base/introduction) for your specific DNS provider.


# How do Dedicated IPs work?
Source: https://resend.com/docs/knowledge-base/how-do-dedicated-ips-work

When are Dedicated IPs helpful, and how can they be requested.

## What is a Dedicated IP?

In email delivery, the sending IP address serves as a key identifier. Inbox Providers like Gmail track the reputation of these IPs based on the quality and quantity of emails sent from them, factoring this information into filtering and inbox placement decisions.

By default, all Resend users use our shared IPs, which are a collection of IPs shared across many senders. Optionally, you can purchase a dedicated IP pool so a range of IPs are exclusively assigned to your sending.

Resend goes one step further and exclusively provisions "Managed Dedicated IP Pools". These managed pools handle multiple delicate and time consuming aspects of dedicated IPs:

* **Automatic warmup**: New IPs have no reputation and are therefore under scrutiny by inbox providers. Resend carefully migrates your sending over from the shared pool to your dedicated pool.
* **Automatic scaling**: IPs can only send at a certain rate based on the specifications of each inbox provider. Resend scales your pool dynamically based on the inbox provider feedback, without you lifting a finger.
* **Continuous monitoring**: Resend continuously monitors the reputation and performance of your dedicated IPs.
* **Fully dedicated**: You can segregate your emails from sending on shared pools to reduce risk of "noisy neighbors".

<Note>
  Resend only provisions Managed Dedicated IP Pools, but we will refer to them
  as **Dedicated IPs** in this article to be succinct.
</Note>

## When Dedicated IPs are helpful

Historically, Dedicated IPs were seen as the primary ingredient to great deliverability. This is not true anymore as Inbox Providers have incorporated dozens of other factors like sending history, domain reputation, and sending feedback (bounces and complaints) more predominantly than IP reputation.

Though Dedicated IPs are not a deliverability silver bullet, they maintain a helpful benefit: **removing risk of noisy neighbors**.

There is power in numbers, and for many senders it can be helpful to leverage the positive reputation of other senders in an IP pool. For some senders though, they want to maintain their own IP reputation without any chance of being impacted, positively or negatively, by other senders. For them, Dedicated IPs are a helpful solution.

## When Dedicated IPs are not helpful

Dedicated IPs can be helpful, but there are some situations where they can actually hinder your ability to reach the inbox. If any of these situations match your use case, Dedicated IPs may hinder more than help:

* **Low email volume**: Sending less than 90,000 emails a month may not be enough to keep the IPs warm.
* **Inconsistent sending**: Sudden changes in email volume can hurt your IP reputation.
* **Poor email practices**: A Dedicated IP exposes your sending behavior even more.
* **New sender**: If you're starting out and have no sending history.
* **IP Allowlisting**: Resend does not expose the IPs included in your dedicated pool.

## How IP warmup works

With Resend's Managed Dedicated IP Pools, the warmup process is handled automatically:

1. **Automatic scaling**: Add or remove IP addresses based on your sending volume.
2. **Gradual increase**: Gradually increase the volume of emails sent through new IPs over time.
3. **Traffic distribution**: During warmup, traffic is distributed across shared and dedicated IPs.
4. **Reputation monitoring**: Continuously monitor the reputation of your dedicated IPs.
5. **Adaptive warmup**: Adapt the warmup process to your sending patterns.

Often IP warmup is a highly manual process and requires great care if you don't want a deliverability degradation in the process. With this automatic warmup process, that's handled for you so you can focus on sending.

<Note>
  Because Managed Dedicated IP Pools are dynamically scaled, **we do not expose
  the list of IPs** in your dedicated pool.
</Note>

## Requirements for a Dedicated IP

You can request a Dedicated IP if you meet the following requirements:

* Your domains are in the same region (Dedicated IPs are provisioned per region).
* Your sending volume exceeds 3,000 emails sent per day.
* You already have an active Transactional Scale or Marketing Pro subscription.
* All domains you want added to the Dedicated IP are already verified on Resend.

## How to request a Dedicated IP

If you're on a Scale plan or higher, you can request a Dedicated IP directly from your dashboard:

1. Navigate to **Settings** > **Usage**
2. Click **Request dedicated IP** in the Dedicated IPs section
3. Fill out the request form with information about your sending patterns

Alternatively, you can request a Dedicated IP by [chatting with support](https://resend.com/help).

You will need to provide the following information:

* What types of emails are you sending?
* How many emails are you sending per day and month on average?
* Is your sending consistent every day, or do you send in bursts?
* Which domains do you want included in your Dedicated IP?


# How to avoid conflicts with your MX records
Source: https://resend.com/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records

Learn how to avoid conflicts with your existing MX records when setting up a Resend domain.

## MX records for sending and receiving emails

MX (Mail Exchanger) records specify where incoming mail is delivered on behalf of a domain. Every MX value has a unique priority (also known as preference) value. The lower the number, the higher the priority.

Resend requires that you setup a MX record on two occasions:

1. **[Enabling your domain to send emails](https://resend.com/docs/dashboard/emails/introduction)**: You need to setup an MX record on `send.example.com` to establish a return-path for bounce/complaint reports from Inbox Providers. This return path is set in the email headers of every email you send through Resend.

2. **[Enabling your domain to receive emails](https://resend.com/docs/dashboard/receiving/custom-domains)**: You can setup an MX record on your domain to route all received emails to Resend.

## Avoiding conflicts with MX record priorities

Here's an example for each occasion Resend requires you to setup a MX record.

Say you're using G Suite for your email. You'll have an MX record that looks something like this:

```
example.com     MX    10 alt3.aspmx.l.google.com.
```

This record specifies that any incoming mail to `<anything>@example.com` is delivered to the Google servers.

Now, say you want to use Resend to send emails from `@example.com`. You'll need to add an MX record for `send.example.com` that looks something like this:

```
send.example.com     MX    10 feedback-smtp.us-east-1.amazonses.com
```

This **won't** conflict because the MX record is for `send.example.com`, not `example.com`. MX records only impact the subdomain they are associated to, so the Resend MX record will not affect your existing records on the root domain.

Now say you want to start receiving emails through Resend.

Because you already have the MX record `example.com`, you have two options:

1. **\[Recommended] Create a MX record for a subdomain** (e.g. `subdomain.example.com`). Now emails sent to `<anything>@example.com` will continue going to G Suite, and emails sent to `<anything>@subdomain.domain.com` will go to Resend.

2. **Create a MX record with the lowest priority** among the other MX record for your domain.
   Since on our example, you already had a MX record for `example.com` point to G Suite, you would create:

```
example.com    MX    9  inbound-smtp.us-east-1.amazonaws.com
```

Now this MX record priority has a lower value (higher priority) so it will be prioritized. But keep in mind that:

<Note>
  * This will route all emails destined to `<anything>@example.com` to Resend, instead of your previous provider (e.g., G Suite).
  * If two MX records have the same priority value, this does not mean it will send to both servers. Instead, only one server will be chosen, randomly, per email delivery attempt.
</Note>

## Solving common conflicts

<AccordionGroup>
  <Accordion title="Conflicts with existing records">
    If you already have a MX record set for `send.example.com`, you will need to remove it before adding the Resend MX record.

    If you need to keep the existing record, you can add a subdomain to your domain (e.g. `sub.example.com`) which will move the Resend MX location to `send.sub.example.com`.
  </Accordion>

  <Accordion title="Conflicts with existing priority">
    Each MX should have a unique priority value. We suggest using 10 for your MX record on `send.example.com`, but you can use a lower number (higher priority) if 10 is already in use.

    <Note>
      The lowest possible value (highest priority) is 0. So if you already have a record with this priority, you'll need to remove it in order to create the MX record for Resend.
    </Note>
  </Accordion>
</AccordionGroup>


# How to avoid Gmail's spam folder
Source: https://resend.com/docs/knowledge-base/how-do-i-avoid-gmails-spam-folder

Learn how to improve inbox placement in Gmail.

<Note>
  This guide is adapted from Google's article to [Prevent mail from being
  blocked or sent to
  spam](https://support.google.com/mail/answer/81126?hl=en\&vid=1-635789122382665739-3305764358\&sjid=4594872399309427672-NA#thirdparty)
</Note>

## Authenticate Your Email

All communication is built on trust, and email is no different. When you send an email, you want to be sure that the recipient (and Gmail) knows who you are and that you are a legitimate sender. Email authentication is a way to prove that an email is from you. It also helps to prevent your email from being spoofed or forged.

| Authentication                    | Requires Setup | Purpose                                                      |
| --------------------------------- | -------------- | ------------------------------------------------------------ |
| **SPF**                           | No             | Proves you are allowed to send from this domain              |
| **DKIM**                          | No             | Proves your email originated from you                        |
| [DMARC](/docs/dashboard/domains/dmarc) | Yes            | Proves you own the domain and instructs how to handle spoofs |
| [BIMI](/docs/dashboard/domains/bimi)   | Yes            | Proves you are the brand you say you are                     |

**SPF** and **DKIM** are baseline requirements for all sending which is why both are automatically setup when you verify your domain with Resend. [DMARC](/docs/dashboard/domains/dmarc) and [BIMI](/docs/dashboard/domains/bimi) are both additional authentication methods that can build trust and further improve inbox placement.

**Action Items**

1. [Setup DMARC](/docs/dashboard/domains/dmarc) for your domain
2. [Setup BIMI](/docs/dashboard/domains/bimi) for your domain

## Legitimize Your Domain

Gmail is using many methods to identify who you are as a sender, and one way they do that is by looking at your domain. Make sure that the domain you send with is the same domain where your website is hosted. If you send from `@example.com` but your website is hosted at `example.net`, Gmail won't be able to use your site to help legitimize you.

You can regularly check if your domain is listed as unsafe with [Google Safe Browsing](https://transparencyreport.google.com/safe-browsing/search?hl=en) to make sure Google isn't classifying your domain as suspicious.

**Action Items**

1. Host your website at the domain that you send from (especially for new domains)
2. Check if your domain is listed as unsafe with [Google Safe Browsing](https://transparencyreport.google.com/safe-browsing/search?hl=en)

## Manage your Mailing List

Gmail monitors your sending across all Gmail inboxes to see if recipients want to receive your emails. This is mainly measured by their engagement with your messages (opens, clicks, replies). If Gmail doesn't see this engagement, they will start to move your inbox placement towards promotional or even spam.

It would seem like adding open and click tracking would be ideal to gather this information, but this has been seen to negatively impact your inbox placement. Instead, focus on sending to recipients who want to receive your emails.

**Prevent sending to recipients who**:

* Didn't ask to be sent to (opt-in)
* Show no signs of engagement with your emails or product
* Requested to be unsubscribed
* Marked your emails as spam (complained)
* Never received your email (bounced)

**Action Items**

1. Provide a clear way to opt out of your emails (including the [Unsubscribe Headers](https://resend.com/docs/dashboard/emails/add-unsubscribe-to-transactional-emails))
2. Use [Webhooks](/docs/webhooks/introduction) to remove bounced or complained recipients from your list
3. Use [Gmail's Postmaster Tool](https://support.google.com/mail/answer/9981691?sjid=4594872399309427672-NA\&visit_id=638259770782293948-1913697299\&rd=1) to monitor your spam reports

## Monitor Affiliate Marketers

Affiliate marketing programs offer rewards to companies or individuals that send visitors to your website. However, spammers can take advantage of these programs. If your brand is associated with marketing spam, other messages sent by you might be marked as spam.

Regularly monitor affiliates, and remove any affiliates that send spam.

**Action Items**

1. Monitor your affiliate marketers for any spam

## Make Content People Want to Read

Trust is not only built with the domain, but also in the message. Sending content that people want to read and that is not misleading will help build trust with Gmail.

A few good rules for content:

* Less is more (keep it simple and to the point)
* Plain text over complex HTML
* Visible links that match the sending domain
* No hidden or manipulative content

**Action Items**

1. Reduce and simplify your email content
2. Make sure your links are using your sending domain

## Establish Sending Patterns

This is especially true for new domains since Gmail doesn't have any history of trust. Sending a large volume of emails from a new domain will likely result in poor inbox placement. Instead, start small and build up your sending volume over time.

A great way to start is by sending regular person-to-person email with your gmail account. These messages will have high engagement and built trust quickly, which will carry over when you start integrating with a sending service like Resend.

It can also be helpful to segment your sending by sending address to give Gmail more indication of what type of sending you are doing. This allows Gmail to place your emails in the correct inbox tab (for example, Primary or Promotions).

Some examples of helpful email addresses:

* **Personal emails** come from an address with a name like [marissa@example.com](mailto:marissa@example.com)
* **Transactional emails** come from an address like [notifications@example.com](mailto:notifications@example.com)
* **Marketing emails** come from an address like [updates@example.com](mailto:updates@example.com).

**Action Items**

1. Send emails from your gmail account before sending transactional
2. Send transactional emails before sending marketing emails
3. Choose dedicated sending addresses for each type of email

## Summary

Email deliverability is overwhelming. One way to simplify it is to think: **what would a phisher do?**

**Then do the opposite!**

Gmail's goal is to only show emails that their users want to see and malicious emails are at the bottom of the list. Reverse engineer phishing sending habits and consider how you can prove to Gmail at each step that you clearly have no malicious intent.

<Info>Anything we missed? [Let us know](https://resend.com/help).</Info>


# How to avoid iCloud's spam folder
Source: https://resend.com/docs/knowledge-base/how-do-i-avoid-icloud-spam-folder

Learn how to improve inbox placement in iCloud Mail.

<Note>
  This guide is adapted from Apple's article on [bulk email sending best
  practices for iCloud Mail](https://support.apple.com/en-us/HT204137). Many of
  these recommendations also apply to Gmail and Outlook, so be sure to read [How
  do I avoid Gmail's spam
  folder?](/docs/knowledge-base/how-do-i-avoid-gmails-spam-folder) and [How do I
  avoid Outlook's spam
  folder?](/docs/knowledge-base/how-do-i-avoid-outlooks-spam-folder).
</Note>

Apple does not offer allowlists or feedback loops for iCloud Mail. Your reputation as a sender is determined automatically based on how you send and how recipients engage with your email. The best way to land in the inbox is to follow the requirements below consistently.

## Authenticate Your Email

Like every major mailbox provider, iCloud uses email authentication to confirm that you are who you say you are. Apple requires that bulk senders authenticate with SPF, DKIM, and DMARC.

| Authentication                    | Requires Setup | Purpose                                                      |
| --------------------------------- | -------------- | ------------------------------------------------------------ |
| **SPF**                           | No             | Proves you are allowed to send from this domain              |
| **DKIM**                          | No             | Proves your email originated from you                        |
| [DMARC](/docs/dashboard/domains/dmarc) | Yes            | Proves you own the domain and instructs how to handle spoofs |

When you verify your domain with Resend, **SPF** and **DKIM** are configured and validated for you automatically, so your email meets Apple's authentication requirements out of the box. Resend also signs every message with DKIM and handles SPF alignment on your behalf, so you don't have to manage these records yourself. Apple additionally requires that your sending domain publish a [DMARC](/docs/dashboard/domains/dmarc) policy.

**Action Items**

1. Verify your domain with Resend to set up SPF and DKIM automatically
2. [Setup DMARC](/docs/dashboard/domains/dmarc) for your domain

## Use Consistent, Reputable Infrastructure

iCloud builds trust over time based on the domains you send from. Keeping your sending consistent helps Apple recognize you as a legitimate sender.

* **Separate your marketing and transactional streams** so each can build its own reputation.
* Maintain a **consistent `From:` name and address** so recipients (and Apple) recognize your brand.
* Make sure your email is **RFC 5321 and RFC 5322 compliant**.

**Action Items**

1. Use dedicated sending addresses for marketing vs. transactional email

## Send Only to Recipients Who Opted In

Apple requires that you send only to recipients who explicitly subscribed to your emails. Purchased lists, rented lists, and email appends are not permitted and will damage your reputation.

**Prevent sending to recipients who**:

* Didn't explicitly opt in to your emails
* Show no signs of engagement with your emails
* Requested to be unsubscribed
* Marked your emails as spam (complained)
* Never received your email (bounced)

**Action Items**

1. Only send to recipients who explicitly subscribed
2. Use [Webhooks](/docs/webhooks/introduction) to remove bounced or complained recipients from your list
3. Never resume sending to addresses on your suppression list

## Simplify the Unsubscribe Process

Apple requires bulk senders to offer an unsubscribe link so recipients can opt out immediately. You can [implement one-click unsubscribe](/docs/dashboard/emails/add-unsubscribe-to-transactional-emails) for the best user experience.

**Action Items**

1. Include a clearly visible unsubscribe link in bulk emails
2. Add [Unsubscribe Headers](/docs/dashboard/emails/add-unsubscribe-to-transactional-emails) to enable one-click unsubscribe

## Keep Your List Clean

iCloud monitors recipient engagement closely. Continuing to send to inactive or invalid addresses lowers your reputation.

* Periodically remove inactive subscribers.
* Handle bounces with a standard suppression policy.
* Keep your spam complaint rate low.

**Action Items**

1. Regularly prune inactive subscribers from your list
2. Suppress bounced and complained addresses automatically

## Monitor SMTP Errors

When iCloud rejects or defers a message, it returns an SMTP error explaining why. Apple expects senders to track both temporary and permanent errors and respond appropriately, rather than retrying blindly.

**Action Items**

1. Review your mail logs and Resend dashboard for SMTP errors
2. Adjust your sending based on temporary (defer) vs. permanent (reject) errors

## If You're Still Having Issues

Apple does not provide allowlists or feedback loops, but for unresolved delivery problems you can contact Apple at **[icloudadmin@apple.com](mailto:icloudadmin@apple.com)**. Include your company name, domain, the SMTP errors you're seeing, and a detailed description of the issue.

## Summary

Email deliverability is overwhelming. One way to simplify it is to think: **what would a phisher do?**

**Then do the opposite!**

iCloud's goal is to only show emails that their users want to see. Reverse engineer phishing sending habits and consider how you can prove to Apple at each step that you clearly have no malicious intent.

<Info>Anything we missed? [Let us know](https://resend.com/help).</Info>


# How to avoid Outlook's spam folder
Source: https://resend.com/docs/knowledge-base/how-do-i-avoid-outlooks-spam-folder

Learn how to improve inbox placement in Outlook.

<Note>
  This guide is adapted from Microsoft's article to [Improve your spam
  reputation](https://support.microsoft.com/en-us/office/sender-support-in-outlook-com-05875e8d-1950-4d89-a5c3-adc355d0d652).
  For high-volume senders (5,000+ messages per day), see [Microsoft's bulk
  sending requirements for
  2025](https://resend.com/blog/microsoft-bulk-sending-requirements-2025).
</Note>

* **Set up email authentication**. Configure [SPF, DKIM, and DMARC](/docs/dashboard/domains/introduction) for your domain. This is required for bulk senders (5,000+ messages per day) and strongly recommended for all senders.

* **Add your sender name**. Set your `from` like this: `"Name <name.domain.com>"`.

* **Engage with your own email**. Send an email to yourself, open it, and reply to it.

* **Add yourself as a contact**. See how to add contacts in [Outlook.com](https://support.microsoft.com/en-us/office/create-view-and-edit-contacts-and-contact-lists-in-outlook-com-5b909158-036e-4820-92f7-2a27f57b9f01).

* **Ask your recipients to add you in their contacts**. This can be done in [Outlook](https://support.microsoft.com/en-us/office/add-recipients-of-my-email-messages-to-the-safe-senders-list-be1baea0-beab-4a30-b968-9004332336ce) or [outlook.com](https://support.microsoft.com/en-us/office/safe-senders-in-outlook-com-470d4ee6-e3b6-402b-8cd9-a6f00eda7339).

* **Don't blast to a BCC list**. Send separate emails if you are sending to a large number of recipients.

* **Prevent over sending**. Limits are impacted by historical engagements and sending volumes, so avoid sending too many emails at once. If you think this is an issue, reduce the frequency or volume.

* **Send to engaged recipients**. Don't keep sending if there is no engagement from your recipients. This is especially true if a recipient has requested to unsubscribe or an address is bouncing. Keep spam complaint rates under 0.3%.

* **Include an unsubscribe option**. For bulk emails, include a clearly visible unsubscribe link. Consider implementing [one-click unsubscribe](/docs/dashboard/emails/add-unsubscribe-to-transactional-emails) for the best user experience.

* **Limit use of HTML**. Keep emails as close to plain text as possible.


# How to cancel a Broadcast
Source: https://resend.com/docs/knowledge-base/how-do-i-cancel-a-broadcast

Stop a Broadcast that is still sending and cancel all queued deliveries.

You can cancel a Broadcast while it is still sending. Canceling stops the send and cancels all queued deliveries, so no further emails go out.

## Cancel a Broadcast

1. Go to [Broadcasts](https://resend.com/broadcasts) and open the Broadcast that is sending.
2. Click **Cancel** on the Broadcast page.

Resend then halts delivery to the remaining recipients.

<Note>
  Canceling is only available while a Broadcast is still sending (`queued`). It
  stops delivery to recipients who haven't received the email yet. Emails that
  have already been sent cannot be recalled.
</Note>

## Related pages

* [Managing Broadcasts](/docs/dashboard/broadcasts/introduction)
* [Broadcast statuses](/docs/dashboard/broadcasts/introduction#understand-broadcast-statuses)


# How to ensure sensitive data isn't stored on Resend
Source: https://resend.com/docs/knowledge-base/how-do-i-ensure-sensitive-data-isnt-stored-on-resend

Information on how you can protect your customer's information.

Resend can turn off message content storage for teams with additional compliance requirements. This is available to customers who meet the following criteria:

1. The team has been a Resend Pro or Scale subscriber for at least 1 month.
2. The team is sending from a domain with an active website.
3. The team has sent over 3,000 emails with a \< 5% bounce rate.

This feature requires a \$50/mo add-on. If your account meets these requirements and you would like this turned on, contact our support team for help.


# How to fix CORS issues
Source: https://resend.com/docs/knowledge-base/how-do-i-fix-cors-issues

Information on recommended options to avoid CORS errors when sending emails.

## Problem

It's common for people to hit CORS (Cross-Origin Resource Sharing) issues when using the Resend API. This error typically shows as:

```
Access to XMLHttpRequest at 'https://api.resend.com/emails'
from origin 'http://localhost:3000' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
```

## Solution

Usually CORS errors happens when you're sending emails from the **client-side**.

Send the emails on the **server-side** to not expose your API keys and avoid CORS issues.


# How to maximize deliverability for Supabase Auth emails
Source: https://resend.com/docs/knowledge-base/how-do-i-maximize-deliverability-for-supabase-auth-emails

Everything to do before you start sending authentication emails with Resend and Supabase.

<Note>
  If you haven't yet, [configure your own Supabase
  integration](https://resend.com/settings/integrations)!
</Note>

Below are **five steps to improve the deliverability of your authentication emails**.

Prefer watching a video? Check out our video walkthrough below.

<YouTube />

## Setup a custom domain on Supabase

By default, Supabase generates a `supabase.co` domain for your project, and uses that domain for the links in your authentication emails (e.g., verify email, reset password).

Once you are ready to go live, though, it is important to setup a custom domain. The key benefit here is to align the domains used in your `from` address and the links in your emails. Especially for something as sensitive as email verification and magic links, **giving confidence to the inbox providers that the origin of the email and the links in the body are the same** can be impactful.

This changes your links from:

```
https://039357829384.supabase.co/auth/v1/{code}
```

To something like this:

```
https://auth.example.com/auth/v1/{code}
```

Supabase has a helpful guide for [Setting up a custom domain](https://supabase.com/docs/guides/platform/custom-domains).

## Setup a dedicated subdomain

There are many benefits to using a subdomain vs your root domain for sending, one being that you can isolate the reputation of the subdomain from your root domain.

For authentication emails, using a subdomain is particularly helpful because it is a way to **signal your intention to the inbox provider**. For example, if you use `auth.example.com` for your authentication emails, you are communicating to the inbox provider that all emails from this subdomain are related to sending authentication emails.

This clarity is essential because it helps the inbox provider understand that this subdomain is not used for sending marketing emails, which are more likely to be marked as spam.

<Note>
  If you don't want a subdomain just for auth, you can also achieve this by
  establishing one subdomain for all your transactional emails (e.g.,
  `notifications.example.com`).
</Note>

To add a subdomain to Resend, you can [add it as a domain on the dashboard](https://resend.com/domains).

<img alt="Create auth subdomain" />

## Disable link and open tracking

Link and open tracking can be great for marketing emails but not for transactional emails. This kind of **tracking can actually hurt your deliverability**. Open tracking embeds a 1x1 pixel image in the email, and link tracking rewrites the links in the email to point to Resend's servers first. Both types can be seen as suspicious by the inbox provider and hurt your deliverability.

Also, Supabase has noted that link tracking is [known for corrupting verification links](https://supabase.com/docs/guides/platform/going-into-prod), making them unusable for your users.

You can disable link and open tracking by clicking on your domain and disabling at the bottom.

<img alt="Disable link and open tracking" />

## Prepare for link scanners

Some inbox providers or enterprise systems have email scanners that run a `GET` request on all links in the body of the email. This type of scan can be problematic since Supabase Auth links are single-use.

To get around this problem, consider altering the email template to replace the original magic link with a link to a domain you control. The domain can present the user with a "Sign-in" button, which redirects the user to the original magic link URL when clicked.

## Setup DMARC

Like our human relationships, email deliverability is built on trust. The more inboxes can trust your emails, your domain, and your sending, the more likely your emails will be delivered to the inbox. This makes [Email Authentication a critical pillar](https://resend.com/blog/email-authentication-a-developers-guide) in the journey to excellent deliverability.

That is where DMARC comes in. As the industry standard for email authentication, **DMARC is a way to tell the inbox provider that you are who you say you are**. It is a way to signal to the inbox provider that you are a legitimate sender and that your emails should be delivered to the inbox.

Following security best practices like DMARC will show your validity and authenticity.

<img alt="DMARC policy details" />

You can use our [DMARC setup guide to get started](/docs/dashboard/domains/dmarc).


# How to send with an avatar
Source: https://resend.com/docs/knowledge-base/how-do-i-send-with-an-avatar

Learn how to show your avatar in the inbox of your recipients.

[Recent studies](https://www.businesswire.com/news/home/20210720005361/en/Red-Sift-and-Entrust-Survey-Showing-a-Logo-Positively-Affects-Consumer-Interaction-With-Emails-Open-Rates-Buying-Behavior-Brand-Recall-and-Confidence) are showing meaningful benefits of displaying your logo in the inbox:

* Increases brand recall by 18%.
* Improves open rate by 21%.
* Boosts purchase likelihood by 34%.
* Reinforces confidence in email by 90%.

<img alt="Email with an avatar" />

## Gmail

Follow these steps to add an avatar to your Gmail inbox:

1. Go to your [Google Account Settings](https://myaccount.google.com/personal-info)
2. Upload a profile picture

Avatars in Gmail only display in the mobile app (including in push notifications) and inside opened emails on desktop.

## Outlook

Follow these steps to add an avatar to your Outlook inbox:

1. Go to your [Outlook Profile Settings](https://account.microsoft.com/profile/)
2. Upload a profile picture

Avatars in Outlook only display in the mobile app and inside opened emails on desktop.

## Yahoo

Follow these steps to add an avatar to your Yahoo inbox:

1. Go to your [Yahoo Account Setting](https://login.yahoo.com/account/personalinfo)
2. Upload a profile picture

Avatars in Yahoo only display in the mobile app and inside an opened email on desktop.

## Apple Mail

Apple Mail only shows avatars if recipients have added images to contacts. Alternatively, you can set up [Apple Branded Mail](/docs/knowledge-base/how-do-i-set-up-apple-branded-mail), a proprietary Apple format introduced with iOS 18.2 that displays your logo as an avatar in the inbox of Apple Mail, or [set up BIMI](/docs/dashboard/domains/bimi#what-is-bimi) with a Verified Mark Certificate.

## Using Gravatar

Some inbox service providers or email clients (e.g. Thunderbird, Airmail, and Postbox) rely on [Gravatar](https://gravatar.com/) to display an image.

You can set up a free Gravatar account, add your avatar, and verify your addresses you're sending from to that account to have your avatar displayed.

## Limitations

Almost every email provider has its own way of adding a profile picture to an inbox.

This means **you can only**:

1. Add your avatar to a real inbox, limiting it only to that provider
2. Send mail from the same address that you set the avatar on

The way around this is [BIMI (Brand Indicators for Message Identification)](/docs/dashboard/domains/bimi). BIMI now supports Common Mark Certificates (CMC) in addition to Verified Mark Certificates (VMC), making it more accessible. It is supported by nearly all major providers and allows you to send from any address on that domain.

<Note>
  Need assistance setting up BIMI? [We can help](https://resend.com/help).
</Note>


# How to set up Apple Branded Mail
Source: https://resend.com/docs/knowledge-base/how-do-i-set-up-apple-branded-mail

Learn how to implement Apple Branded Mail to display your logo in Apple Mail clients.

## Prerequisites

To get the most out of this guide, you will need to:

* [Create an Apple Business Connect account](https://www.apple.com/business/connect/)
* [Setup DMARC on your domain](/docs/dashboard/domains/dmarc)
* A company identification number for Apple to verify your company

Prefer watching a video? Check out our video walkthrough below.

<YouTube />

## Why use Apple Branded Mail

Apple Branded Mail is a proprietary Apple format that displays your logo as an avatar in the inbox of Apple Mail. Displaying your logo can increase brand recognition and trust and improve engagement.

There are a few benefits of Apple Branded mail over BIMI:

* Since it's an Apple format, it does not require a certificate like [BIMI does](/docs/dashboard/domains/bimi).
* The image support is broader, supporting `.png`, `.heif`, and `.jpg` logos.

Since Apple Branded Mail works only with Apple Mail on new iOS, iPadOS, and macOS versions, your logo will not show in other mail clients or older versions of Apple Mail.

For this reason, follow all possible methods for adding your logo to your emails, including Apple Branded Mail, [our general guide](/docs/knowledge-base/how-do-i-send-with-an-avatar), and [BIMI](/docs/dashboard/domains/bimi) if it fits your needs.

## Implementing Apple Branded Mail

<Steps>
  <Step title="Configure DMARC">
    <Note>
      If you haven't set up DMARC yet, follow our [DMARC Setup
      Guide](/docs/dashboard/domains/dmarc).
    </Note>

    To ensure your logo appears with Apple Branded Mail, set your DMARC policy to either `p=quarantine;` or `p=reject;`. This policy guarantees that your emails are authenticated and prevents others from spoofing your domain and sending emails with your logo.

    Here's an overview of the required parameters:

    | Parameter | Purpose    | Required Value                 |
    | --------- | ---------- | ------------------------------ |
    | `p`       | Policy     | `p=quarantine;` or `p=reject;` |
    | `pct`     | Percentage | `pct=100;`                     |

    Here is an example of an adequate DMARC record:

    ```
    "v=DMARC1; p=quarantine; pct=100; rua=mailto:dmarcreports@example.com"
    ```

    As we mention in our [DMARC Setup Guide](/docs/dashboard/domains/dmarc), be sure to test your emails to make sure they are passing DMARC before changing your DMARC policy to `p=quarantine;` or `p=reject;`.
  </Step>

  <Step title="Create an Apple Business Connect account">
    Apple displays the logo you set in your Business Connect account. [Create an account](https://www.apple.com/business/connect/) if your company does not already have one. Make sure to use your company details when signing up.
  </Step>

  <Step title="Add your company details">
    Apple will prompt you to provide details like your company address and name.
  </Step>

  <Step title="Add your brand details">
    Once your company account is created, in Apple Business Connect, select the **Branded Mail** option in the left sidebar and provide details on your brand. Add details like the brand name and your brand website.

    <img alt="Add your brand details" />

    <img alt="Add your brand details" />
  </Step>

  <Step title="Add your logo">
    Once you fill out the brand details, upload your logo. Apple requires the logo to be at least 1024 x 1024 px in a `.png`, `.heif`, or `.jpeg` format.

    <img alt="Add your logo" />
  </Step>

  <Step title="Add your domain">
    Confirm the domains or email addresses where you want your brand logo to appear.

    You can register your logo for your root domain or a subdomain. If you don't set a specific logo for a subdomain, the root domain logo will automatically display for any email sent from your subdomains.
  </Step>

  <Step title="Verify your company">
    Apple requires details to confirm your company identity.

    If you're in the United States, provide a Federal Taxpayer Identification Number. Other countries will use a local equivalent for this step. Apple also asks that you add a DNS record to verify DNS access.
  </Step>

  <Step title="Verify with Apple">
    After you submit all your information, Apple will verify your details. This process may take up to seven business days.

    Once the logo is verified, Apple will send an email notification and note the verified status in Branded Mail. Your logo will start to display in compatible Apple Mail versions.

    <img alt="Verified logo" />

    <Tip>
      See Apple's documentation on [Apple Branded
      Mail](https://support.apple.com/en-au/guide/apple-business-connect/abcb761b19d2/web)
      for any detailed questions on adding your logo.
    </Tip>
  </Step>
</Steps>


# How to Handle API Keys
Source: https://resend.com/docs/knowledge-base/how-to-handle-api-keys

Learn our suggested practices for handling API keys securely.

## Best Practices

It's crucial you handle your API keys securely. Do not share your API key with others or expose it in the browser or other client-side code.

Here are some general guidelines:

* Store API keys in environment variables.
* Never commit API keys to version control.
* Never hard-code API keys in your code or share them publicly.
* Rotate API keys regularly. If an API key hasn't been used in the last 30 days, consider deleting it to keep your account secure.

<Info>
  When you create an API key in Resend, you can view the key only once. This
  practice helps encourage these best practices.
</Info>

## Key Rotation

Resend API keys do not expire automatically. Keys remain valid until you manually delete them. Resend includes no built-in expiration date or automatic rotation mechanism, but it is a good security practice to rotate keys regularly.

To rotate an API key:

1. **Create a new key** in the [**API keys** Dashboard page](https://resend.com/api-keys) or [via the API](/docs/api-reference/api-keys/create-api-key) with the same permission level and domain scope as the key you are replacing.
2. **Update your services** to use the new key. Deploy the change to all environments that reference the old key.
3. **Verify the new key is working** by [filtering by API key on the **Logs** Dashboard page](https://resend.com/logs) and checking for recent requests.
4. **Delete the old key** once you have confirmed the new key is active across all services.

<Warning>
  Do not delete the old key before the new key is deployed everywhere. Both keys
  will work simultaneously, so ensure your new key is working before deleting
  your old key so you do not experience downtime during the transition. You can
  programmatically [create](/docs/api-reference/api-keys/create-api-key),
  [list](/docs/api-reference/api-keys/list-api-keys), and
  [delete](/docs/api-reference/api-keys/delete-api-key) API keys to rotate keys.
</Warning>

Rotate keys at least every 90 days, or immediately if you suspect a key has been compromised. Resend flags keys unused for 30+ days in the dashboard to help you identify keys to review or delete.


# Introduction
Source: https://resend.com/docs/knowledge-base/introduction

A collection of answers to frequently asked questions.

## Domains & Verification

<CardGroup>
  <Card title="How do I avoid conflicts with my MX records?" href="/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records">
    Add DNS records without conflicting with existing MX records.
  </Card>

  <Card title="What if my domain is not verifying?" href="/knowledge-base/what-if-my-domain-is-not-verifying">
    What to do when your domain isn't verifying.
  </Card>
</CardGroup>

## DNS Guides

Step-by-step instructions for verifying your domain with popular DNS providers.

<CardGroup>
  <Card
    title="Cloudflare DNS Guide"
    icon={
<svg
  className="h-6 w-6"
  viewBox="0 0 24 24"
  fill="currentColor"
  xmlns="http://www.w3.org/2000/svg"
>
  <path d="M16.5088 16.8447c.1475-.5068.0908-.9707-.1553-1.3154-.2246-.3164-.6045-.499-1.0615-.5205l-8.6592-.1123a.1559.1559 0 0 1-.1333-.0713c-.0283-.042-.0351-.0986-.021-.1553.0278-.084.1123-.1484.2036-.1562l8.7359-.1123c1.0351-.0489 2.1601-.8868 2.5537-1.9136l.499-1.3013c.0215-.0561.0293-.1128.0147-.168-.5625-2.5463-2.835-4.4453-5.5499-4.4453-2.5039 0-4.6284 1.6177-5.3876 3.8614-.4927-.3658-1.1187-.5625-1.794-.499-1.2026.119-2.1665 1.083-2.2861 2.2856-.0283.31-.0069.6128.0635.894C1.5683 13.171 0 14.7754 0 16.752c0 .1748.0142.3515.0352.5273.0141.083.0844.1475.1689.1475h15.9814c.0909 0 .1758-.0645.2032-.1553l.12-.4268zm2.7568-5.5634c-.0771 0-.1611 0-.2383.0112-.0566 0-.1054.0415-.127.0976l-.3378 1.1744c-.1475.5068-.0918.9707.1543 1.3164.2256.3164.6055.498 1.0625.5195l1.8437.1133c.0557 0 .1055.0263.1329.0703.0283.043.0351.1074.0214.1562-.0283.084-.1132.1485-.204.1553l-1.921.1123c-1.041.0488-2.1582.8867-2.5527 1.914l-.1406.3585c-.0283.0713.0215.1416.0986.1416h6.5977c.0771 0 .1474-.0489.169-.126.1122-.4082.1757-.837.1757-1.2803 0-2.6025-2.125-4.727-4.7344-4.727" />
</svg>
}
    href="/knowledge-base/cloudflare"
  />

  <Card
    title="Gandi DNS Guide"
    icon={
<svg
  className="h-6 w-6"
  viewBox="0 0 24 24"
  fill="currentColor"
  xmlns="http://www.w3.org/2000/svg"
>
  <path d="M16.72 5.908a1.496 1.496 0 1 1 2.442 1.729c-.871 1.23-1.906 2.176-3.082 2.82-.661.436-1.414.844-2.209 1.274-.689.373-1.401.758-2.065 1.171-1.565.974-2.46 1.87-2.814 2.82-.473 1.266-.26 2.322.002 2.985a3.8 3.8 0 0 0 1.79 2.006c.808.413 1.931.39 2.93-.06.924-.415 1.542-1.11 1.612-1.813.07-.71-.24-1.114-.553-1.255-.368-.165-.788.006-1.152.467a1.495 1.495 0 1 1-2.349-1.854c1.227-1.554 3.082-2.08 4.726-1.342 1.588.713 2.493 2.392 2.305 4.28-.179 1.792-1.435 3.38-3.36 4.246-1.836.826-3.899.824-5.52-.005a6.8 6.8 0 0 1-3.212-3.572c-.642-1.625-.65-3.446-.022-5.13.605-1.62 1.869-2.803 3.037-3.647a8 8 0 0 1-.828-.33c-1.376-.638-2.573-1.668-3.56-3.061A1.496 1.496 0 0 1 7.28 5.908c.69.976 1.467 1.654 2.376 2.075.69.319 1.457.487 2.344.514.888-.027 1.656-.195 2.345-.514q.098-.045.194-.096.106-.053.208-.112c.738-.424 1.387-1.038 1.972-1.867M11.2 4.17c.191.192.447.297.717.297.271 0 .526-.105.718-.297s.297-.446.297-.717a1 1 0 0 0-.298-.718 1 1 0 0 0-.717-.297c-.27 0-.526.105-.717.297a1 1 0 0 0-.297.718c0 .27.105.525.297.717M9.476 1.011A3.43 3.43 0 0 1 11.917 0c.922 0 1.79.359 2.442 1.01a3.43 3.43 0 0 1 1.01 2.443c0 .922-.358 1.789-1.01 2.44a3.43 3.43 0 0 1-2.442 1.012 3.43 3.43 0 0 1-2.44-1.011 3.43 3.43 0 0 1-1.013-2.441c0-.923.36-1.79 1.012-2.442" />
</svg>
}
    href="/knowledge-base/gandi"
  />

  <Card
    title="GoDaddy DNS Guide"
    icon={
<svg
  className="h-6 w-6"
  viewBox="0 0 24 24"
  fill="currentColor"
  xmlns="http://www.w3.org/2000/svg"
>
  <path d="M20.702 2.29c-2.494-1.554-5.778-1.187-8.706.654C9.076 1.104 5.79.736 3.3 2.29c-3.941 2.463-4.42 8.806-1.07 14.167 2.47 3.954 6.333 6.269 9.77 6.226 3.439.043 7.301-2.273 9.771-6.226 3.347-5.361 2.872-11.704-1.069-14.167zM4.042 15.328a12.838 12.838 0 01-1.546-3.541 10.12 10.12 0 01-.336-3.338c.15-1.98.956-3.524 2.27-4.345 1.315-.822 3.052-.87 4.903-.137.281.113.556.24.825.382A15.11 15.11 0 007.5 7.54c-2.035 3.255-2.655 6.878-1.945 9.765a13.247 13.247 0 01-1.514-1.98zm17.465-3.541a12.866 12.866 0 01-1.547 3.54 13.25 13.25 0 01-1.513 1.984c.635-2.589.203-5.76-1.353-8.734a.39.39 0 00-.563-.153l-4.852 3.032a.397.397 0 00-.126.546l.712 1.139a.395.395 0 00.547.126l3.145-1.965c.101.306.203.606.28.916.296 1.086.41 2.214.335 3.337-.15 1.982-.956 3.525-2.27 4.347a4.437 4.437 0 01-2.25.65h-.101a4.432 4.432 0 01-2.25-.65c-1.314-.822-2.121-2.365-2.27-4.347-.074-1.123.039-2.251.335-3.337a13.212 13.212 0 014.05-6.482 10.148 10.148 0 012.849-1.765c1.845-.733 3.586-.685 4.9.137 1.316.822 2.122 2.365 2.271 4.345a10.146 10.146 0 01-.33 3.334z" />
</svg>
}
    href="/knowledge-base/godaddy"
  />

  <Card
    title="DreamHost DNS Guide"
    icon={
<svg
  className="h-6 w-6"
  viewBox="0 0 512 512"
  fill="currentColor"
  xmlns="http://www.w3.org/2000/svg"
  fillRule="evenodd"
  clipRule="evenodd"
>
  <g fillRule="nonzero">
    <path d="M493.647 381.78c-40.289 22.2-86.333 34.534-135.667 33.712-146.356-3.29-261.467-120.867-259-263.934.822-48.512 15.622-93.734 40.289-131.556C61.157 63.58 7.713 144.98 6.069 239.536 2.778 381.78 118.712 500.18 264.246 503.47c97.022 1.644 181.711-46.867 229.4-121.69" />
    <path d="M279.869 8.49c-39.467 0-76.467 9.867-109.356 27.956-20.555 33.712-32.067 72.356-33.711 111.823-2.467 124.156 98.667 226.934 224.467 229.4 37.822 0 80.578-9.044 113.467-27.133 19.733-33.711 31.245-73.178 31.245-115.111C507.625 110.446 405.669 8.49 279.869 8.49z" />
  </g>
</svg>
}
    href="/knowledge-base/dreamhost"
  />

  <Card
    title="Hetzner DNS Guide"
    icon={
<svg
  className="h-6 w-6"
  viewBox="0 0 24 24"
  fill="currentColor"
  xmlns="http://www.w3.org/2000/svg"
>
  <path d="M0 0v24h24V0H0zm4.602 4.025h2.244c.509 0 .716.215.716.717v5.64h8.883v-5.64c0-.509.215-.717.717-.717h2.229c.5 0 .71.23.724.717v14.516c0 .509-.215.717-.717.717h-2.23c-.51 0-.717-.215-.717-.717v-5.735H7.562v5.735c0 .516-.215.717-.716.717H4.602c-.51 0-.717-.208-.717-.717V4.742c0-.509.207-.717.717-.717z" />
</svg>
}
    href="/knowledge-base/hetzner"
  />

  <Card
    title="Hostinger DNS Guide"
    icon={
<svg
  className="h-6 w-6"
  viewBox="0 0 24 24"
  fill="currentColor"
  xmlns="http://www.w3.org/2000/svg"
>
  <path d="M16.415 0v7.16l5.785 3.384V2.949L16.415 0ZM1.8 0v11.237h18.815L14.89 8.09l-7.457-.003V3.024L1.8 0Zm14.615 20.894v-5.019l-7.514-.005c.007.033-5.82-3.197-5.82-3.197l19.119.091V24l-5.785-3.106ZM1.8 13.551v7.343l5.633 2.949v-6.988L1.8 13.551Z" />
</svg>
}
    href="/knowledge-base/hostinger"
  />

  <Card
    title="IONOS DNS Guide"
    icon={
<svg
  className="h-6 w-6"
  viewBox="0 0 24 24"
  fill="currentColor"
  xmlns="http://www.w3.org/2000/svg"
>
  <path d="M22.182 15.499a1.7634 1.7634 0 0 1-.3536-.0358 1.8319 1.8319 0 0 1-1.2086-.8632l-.0066-.012c-.1308-.2616-.0448-.5693.2-.7162a.5236.5236 0 0 1 .2689-.0743.5327.5327 0 0 1 .4632.272.558.558 0 0 0 .018.0299l.0564.0766.0757.0765a.7385.7385 0 0 0 .3453.167.7596.7596 0 0 0 .5954-.136.7206.7206 0 0 0 .299-.5386.7441.7441 0 0 0-.207-.578s-1.5994-1.6612-1.6712-1.7382a1.9604 1.9604 0 0 1-.1929-.229c-.2256-.3198-.2962-.697-.2614-1.0702a1.7361 1.7361 0 0 1 .2253-.7397s.0732-.124.0948-.1554c.0847-.1236.2515-.2834.3658-.3726a1.8813 1.8813 0 0 1 .3069-.1844 1.7494 1.7494 0 0 1 2.2815.7041.5186.5186 0 0 1 .0553.402.5298.5298 0 0 1-.2528.3263.5082.5082 0 0 1-.2593.0705.5283.5283 0 0 1-.46-.2706.6953.6953 0 0 0-.4656-.329.721.721 0 0 0-.5645.1269.688.688 0 0 0-.267.498.6998.6998 0 0 0 .1905.5398l1.6351 1.6862a1.8284 1.8284 0 0 1 .5071 1.3931c-.0465.5243-.3071.9994-.7152 1.3053a1.8425 1.8425 0 0 1-1.0984.369m-5.175-.0006a1.7608 1.7608 0 0 0 1.7585-1.7589v-3.4787a1.7587 1.7587 0 0 0-3.5173 0v3.4786a1.7608 1.7608 0 0 0 1.7587 1.7589m0-5.9342c.3777 0 .6968.319.6968.6967v3.4786a.6977.6977 0 0 1-.6968.6968.6894.6894 0 0 1-.6968-.6968v-3.4786a.6976.6976 0 0 1 .697-.6967m-7.8986.3224v5.0804a.5309.5309 0 0 0 1.0618 0V12.09Zm2.8802 2.0255V9.0328a.531.531 0 0 1 1.0619 0v5.0828zm1.053 2.9406v.1134a.533.533 0 0 1-1.0067.2408L9.1153 9.154v-.1212a.5261.5261 0 0 1 .3028-.4772.5253.5253 0 0 1 .7088.2475Zm-7.9067.6457a1.761 1.761 0 0 0 1.7586-1.7589v-3.4786a1.7587 1.7587 0 0 0-3.5173 0v3.4786a1.7609 1.7609 0 0 0 1.7587 1.7589m0-5.9342a.707.707 0 0 1 .6968.6967v3.4786a.6968.6968 0 1 1-1.3936 0v-3.4786a.6976.6976 0 0 1 .6968-.6967M0 14.9111a.5791.5791 0 1 0 1.1581 0V9.0803a.5791.5791 0 0 0-1.1582 0z" />
</svg>
}
    href="/knowledge-base/ionos"
  />

  <Card
    title="Namecheap DNS Guide"
    icon={
<svg
  className="h-6 w-6"
  viewBox="0 0 24 24"
  fill="currentColor"
  xmlns="http://www.w3.org/2000/svg"
>
  <path d="M17.295 17.484c.227.403.57.728.985.931-.309.15-.647.229-.99.232h-3.068a2.26 2.26 0 0 1-1.957-1.143L6.705 6.511a2.27 2.27 0 0 0-.974-.922c.309-.153.652-.233.997-.232h3.05c.81.003 1.558.438 1.959 1.143l5.558 10.984zm-9.329-7.392L6.269 6.755c-.209-.392-.582-.657-.984-.829-.204.165-.391.35-.522.581-.184.349-4.391 8.648-4.569 8.987a2.245 2.245 0 0 0 4.016 1.999l3.756-7.401zm15.846-1.593a2.245 2.245 0 0 0-1.162-2.955v-.001a2.243 2.243 0 0 0-.892-.187l-.003-.011c-.816 0-1.569.443-1.965 1.157l-3.749 7.414 1.689 3.323c.213.399.59.664.998.839.252-.2.473-.444.605-.742l4.479-8.837z" />
</svg>
}
    href="/knowledge-base/namecheap"
  />

  <Card
    title="Porkbun DNS Guide"
    icon={
<svg
  className="h-6 w-6"
  viewBox="0 0 24 24"
  fill="currentColor"
  xmlns="http://www.w3.org/2000/svg"
>
  <path d="M12 0C5.3708 0 .0176 5.3532.0176 11.9824.0176 18.6117 5.3708 24 12 24s11.9824-5.3532 11.9824-11.9824C23.9824 5.3883 18.6292 0 12 0ZM5.832 5.8848c1.0635.2481 2.092.6384 3.0137 1.1347-1.099.5318-1.9866 1.3824-2.6602 2.375-.4254-.5672-.6738-1.2767-.6738-2.0566 0-.5318.1076-.9923.3203-1.4531zm12.336 0c.2127.4254.3203.9213.3203 1.453 0 .78-.2484 1.4895-.6738 2.0567-.6736-.9926-1.5967-1.8432-2.6602-2.375a9.9821 9.9821 0 0 1 3.0137-1.1347zm-6.0723.8105c3.5286.0471 6.3547 2.9198 6.3203 6.457v3.8282c0 .638-.5318 1.1699-1.17 1.1699-.638 0-1.1698-.5318-1.1698-1.17v-.957H7.8516v.957c0 .6382-.5319 1.17-1.17 1.17-.638 0-1.1699-.5318-1.1699-1.17v-3.6503c0-3.5096 2.7307-6.489 6.2403-6.6309.1152-.0044.2299-.0054.3437-.0039zm1.5 3.7988c-.4963 0-.9219.4256-.9219.922 0 .248.0711.4242.213.6015.1417.2127.3536.3546.5663.461-.1418.0708-.3188.1425-.496.1425-.2128 0-.3907.176-.3907.3887s.178.3906.3906.3906h.1778c.6026 0 1.1346-.3553 1.3828-.8516.39-.1418.7092-.3896.9219-.7441.0709-.1064.0337-.2484-.0372-.2129-.1063-.0355-.2123-.034-.2832.0723-.1063.1418-.2485.2826-.4257.3535v-.1426c0-.39-.1409-.7086-.3536-.9922-.1772-.2481-.425-.3887-.7441-.3887zm0 .5313c.2127 0 .3532.1408.3887.3535v.1777c0 .1773-.0346.3543-.1055.4961-.2481-.0709-.4617-.213-.6035-.4257-.0355-.071-.0703-.14-.0703-.211 0-.2392.2063-.3906.3906-.3906z" />
</svg>
}
    href="/knowledge-base/porkbun"
  />

  <Card
    title="Route 53 DNS Guide"
    icon={
<svg
  className="h-6 w-6"
  viewBox="0 0 24 24"
  fill="currentColor"
  xmlns="http://www.w3.org/2000/svg"
>
  <path d="M6.763 10.036c0 .296.032.535.088.71.064.176.144.368.256.576.04.063.056.127.056.183 0 .08-.048.16-.152.24l-.503.335a.383.383 0 0 1-.208.072c-.08 0-.16-.04-.239-.112a2.47 2.47 0 0 1-.287-.375 6.18 6.18 0 0 1-.248-.471c-.622.734-1.405 1.101-2.347 1.101-.67 0-1.205-.191-1.596-.574-.391-.384-.59-.894-.59-1.533 0-.678.239-1.23.726-1.644.487-.415 1.133-.623 1.955-.623.272 0 .551.024.846.064.296.04.6.104.918.176v-.583c0-.607-.127-1.03-.375-1.277-.255-.248-.686-.367-1.3-.367-.28 0-.568.031-.863.103-.295.072-.583.16-.862.272a2.287 2.287 0 0 1-.28.104.488.488 0 0 1-.127.023c-.112 0-.168-.08-.168-.247v-.391c0-.128.016-.224.056-.28a.597.597 0 0 1 .224-.167c.279-.144.614-.264 1.005-.36a4.84 4.84 0 0 1 1.246-.151c.95 0 1.644.216 2.091.647.439.43.662 1.085.662 1.963v2.586zm-3.24 1.214c.263 0 .534-.048.822-.144.287-.096.543-.271.758-.51.128-.152.224-.32.272-.512.047-.191.08-.423.08-.694v-.335a6.66 6.66 0 0 0-.735-.136 6.02 6.02 0 0 0-.75-.048c-.535 0-.926.104-1.19.32-.263.215-.39.518-.39.917 0 .375.095.655.295.846.191.2.47.296.838.296zm6.41.862c-.144 0-.24-.024-.304-.08-.064-.048-.12-.16-.168-.311L7.586 5.55a1.398 1.398 0 0 1-.072-.32c0-.128.064-.2.191-.2h.783c.151 0 .255.025.31.08.065.048.113.16.16.312l1.342 5.284 1.245-5.284c.04-.16.088-.264.151-.312a.549.549 0 0 1 .32-.08h.638c.152 0 .256.025.32.08.063.048.12.16.151.312l1.261 5.348 1.381-5.348c.048-.16.104-.264.16-.312a.52.52 0 0 1 .311-.08h.743c.127 0 .2.065.2.2 0 .04-.009.08-.017.128a1.137 1.137 0 0 1-.056.2l-1.923 6.17c-.048.16-.104.263-.168.311a.51.51 0 0 1-.303.08h-.687c-.151 0-.255-.024-.32-.08-.063-.056-.119-.16-.15-.32l-1.238-5.148-1.23 5.14c-.04.16-.087.264-.15.32-.065.056-.177.08-.32.08zm10.256.215c-.415 0-.83-.048-1.229-.143-.399-.096-.71-.2-.918-.32-.128-.071-.215-.151-.247-.223a.563.563 0 0 1-.048-.224v-.407c0-.167.064-.247.183-.247.048 0 .096.008.144.024.048.016.12.048.2.08.271.12.566.215.878.279.319.064.63.096.95.096.502 0 .894-.088 1.165-.264a.86.86 0 0 0 .415-.758.777.777 0 0 0-.215-.559c-.144-.151-.416-.287-.807-.415l-1.157-.36c-.583-.183-1.014-.454-1.277-.813a1.902 1.902 0 0 1-.4-1.158c0-.335.073-.63.216-.886.144-.255.335-.479.575-.654.24-.184.51-.32.83-.415.32-.096.655-.136 1.006-.136.175 0 .359.008.535.032.183.024.35.056.518.088.16.04.312.08.455.127.144.048.256.096.336.144a.69.69 0 0 1 .24.2.43.43 0 0 1 .071.263v.375c0 .168-.064.256-.184.256a.83.83 0 0 1-.303-.096 3.652 3.652 0 0 0-1.532-.311c-.455 0-.815.071-1.062.223-.248.152-.375.383-.375.71 0 .224.08.416.24.567.159.152.454.304.877.44l1.134.358c.574.184.99.44 1.237.767.247.327.367.702.367 1.117 0 .343-.072.655-.207.926-.144.272-.336.511-.583.703-.248.2-.543.343-.886.447-.36.111-.734.167-1.142.167zM21.698 16.207c-2.626 1.94-6.442 2.969-9.722 2.969-4.598 0-8.74-1.7-11.87-4.526-.247-.223-.024-.527.272-.351 3.384 1.963 7.559 3.153 11.877 3.153 2.914 0 6.114-.607 9.06-1.852.439-.2.814.287.383.607zM22.792 14.961c-.336-.43-2.22-.207-3.074-.103-.255.032-.295-.192-.063-.36 1.5-1.053 3.967-.75 4.254-.399.287.36-.08 2.826-1.485 4.007-.215.184-.423.088-.327-.151.32-.79 1.03-2.57.695-2.994z" />
</svg>
}
    href="/knowledge-base/route53"
  />

  <Card
    title="Squarespace DNS Guide"
    icon={
<svg
  className="h-6 w-6"
  viewBox="0 0 24 24"
  fill="currentColor"
  xmlns="http://www.w3.org/2000/svg"
>
  <path d="M22.655 8.719c-1.802-1.801-4.726-1.801-6.564 0l-7.351 7.35c-.45.45-.45 1.2 0 1.65.45.449 1.2.449 1.65 0l7.351-7.351c.899-.899 2.362-.899 3.264 0 .9.9.9 2.364 0 3.264l-7.239 7.239c.9.899 2.362.899 3.263 0l5.589-5.589c1.836-1.838 1.836-4.763.037-6.563zm-2.475 2.437c-.451-.45-1.201-.45-1.65 0l-7.354 7.389c-.9.899-2.361.899-3.262 0-.45-.45-1.2-.45-1.65 0s-.45 1.2 0 1.649c1.801 1.801 4.726 1.801 6.564 0l7.351-7.35c.449-.487.449-1.239.001-1.688zm-2.439-7.35c-1.801-1.801-4.726-1.801-6.564 0l-7.351 7.351c-.45.449-.45 1.199 0 1.649s1.2.45 1.65 0l7.395-7.351c.9-.899 2.371-.899 3.27 0 .451.45 1.201.45 1.65 0 .421-.487.421-1.199-.029-1.649h-.021zm-2.475 2.437c-.45-.45-1.2-.45-1.65 0l-7.351 7.389c-.899.9-2.363.9-3.265 0-.9-.899-.9-2.363 0-3.264l7.239-7.239c-.9-.9-2.362-.9-3.263 0L1.35 8.719c-1.8 1.8-1.8 4.725 0 6.563 1.801 1.801 4.725 1.801 6.564 0l7.35-7.351c.451-.488.451-1.238 0-1.688h.002z" />
</svg>
}
    href="/knowledge-base/squarespace"
  />

  <Card
    title="Strato DNS Guide"
    icon={
<svg
  className="h-6 w-6"
  viewBox="0 0 139 139"
  fill="none"
  xmlns="http://www.w3.org/2000/svg"
>
  <path
    d="M138.92 19.8467C138.92 8.88382 130.036 0 119.075 0H49.6143C49.6144 10.9579 58.4987 19.8466 69.46 19.8467H109.151C114.631 19.8467 119.075 24.2901 119.075 29.7695L119.073 69.4629C119.073 80.4222 127.958 89.3086 138.919 89.3086L138.92 19.8467ZM89.3057 138.926C94.785 138.926 99.2284 134.483 99.2285 129.002V49.6172C99.2285 44.1368 94.7851 39.6924 89.3057 39.6924H9.92188C4.44155 39.6925 0 44.1368 0 49.6172V129.002C0.000110772 134.483 4.44161 138.926 9.92188 138.926H89.3057Z"
    fill="currentColor"
  />
</svg>
}
    href="/knowledge-base/strato"
  />

  <Card
    title="Vercel DNS Guide"
    icon={
<svg
  className="h-6 w-6"
  viewBox="0 0 24 24"
  fill="currentColor"
  xmlns="http://www.w3.org/2000/svg"
>
  <path d="m12 1.608 12 20.784H0Z" />
</svg>
}
    href="/knowledge-base/vercel"
  />
</CardGroup>

## Deliverability

<CardGroup>
  <Card title="How do I avoid Gmail's spam folder?" href="/knowledge-base/how-do-i-avoid-gmails-spam-folder">
    Learn how to improve inbox placement in Gmail.
  </Card>

  <Card title="Why Are My Emails Going to Spam?" href="/knowledge-base/why-are-my-emails-going-to-spam">
    Troubleshoot emails landing in spam or getting quarantined.
  </Card>

  <Card title="Is it better to send from a subdomain or root domain?" href="/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain">
    Discover why sending emails from a subdomain can be better than using a root
    domain.
  </Card>

  <Card title="Why are my emails landing on the suppression list?" href="/knowledge-base/why-are-my-emails-landing-on-the-suppression-list">
    Learn why your emails land on the suppression list, and how to remove them.
  </Card>

  <Card title="Domain and IP Warm-up Guide" href="/knowledge-base/warming-up">
    Learn how to warm up your domain and dedicated IP for optimal deliverability.
  </Card>
</CardGroup>

## Sending

<CardGroup>
  <Card title="Account Quotas and Limits" href="/knowledge-base/account-quotas-and-limits">
    Understand the sending quotas and rate limits for your Resend account.
  </Card>

  <Card title="How do Dedicated IPs Work?" href="/knowledge-base/how-do-dedicated-ips-work">
    Learn how Dedicated IPs work and how to request them.
  </Card>

  <Card title="What sending feature should I use?" href="/knowledge-base/what-sending-feature-to-use">
    Find the right Resend feature for your email sending use case.
  </Card>

  <Card title="Should I add an unsubscribe link?" href="/knowledge-base/should-i-add-an-unsubscribe-link">
    Learn when to add unsubscribe links to your transactional and marketing
    emails.
  </Card>
</CardGroup>

## Tutorials

<CardGroup>
  <Card title="Maximize deliverability for Supabase Auth emails" href="/knowledge-base/how-do-i-maximize-deliverability-for-supabase-auth-emails">
    Everything you should do before sending authentication emails with Resend and
    Supabase.
  </Card>

  <Card title="How do I set up Apple Branded Mail?" href="/knowledge-base/how-do-i-set-up-apple-branded-mail">
    Display your brand logo in the Apple Mail inbox.
  </Card>

  <Card title="How do I send with an avatar?" href="/knowledge-base/how-do-i-send-with-an-avatar">
    Learn how to show your avatar in the inbox of your recipients.
  </Card>

  <Card title="Forward emails with Resend Inbound" href="/knowledge-base/forward-emails-with-resend-inbound">
    Set up email forwarding using Resend's inbound email processing.
  </Card>

  <Card title="Template emails with React Email" href="/knowledge-base/template-emails-with-react-email">
    Author email templates as React components and upload them to Resend with the
    CLI.
  </Card>

  <Card title="Embed the React Email editor" href="/knowledge-base/embed-react-email-editor">
    Add the open-source visual email editor to your own application.
  </Card>
</CardGroup>

## Troubleshooting

<CardGroup>
  <Card title="How do I fix CORS issues?" href="/knowledge-base/how-do-i-fix-cors-issues">
    Recommended options to avoid CORS errors when sending emails.
  </Card>

  <Card title="403 Error: Domain Mismatch" href="/knowledge-base/403-error-domain-mismatch">
    Resolve 403 errors when the sending domain doesn't match your verified domain.
  </Card>

  <Card title="Domain Already Registered by Another Account" href="/knowledge-base/domain-already-registered">
    Resolve domain ownership conflicts when a domain is already registered.
  </Card>

  <Card title="Email says delivered but not received?" href="/knowledge-base/what-if-an-email-says-delivered-but-the-recipient-has-not-received-it">
    Steps to take when an email is delivered but the recipient hasn't received it.
  </Card>
</CardGroup>

## AI Tools

<CardGroup>
  <Card title="AI Onboarding" href="/ai-onboarding">
    Everything you need to onboard your AI agent to Resend.
  </Card>

  <Card title="MCP Server" href="/mcp-server">
    Use Resend's Model Context Protocol server to send emails from AI tools.
  </Card>

  <Card title="Email Best Practices Skills" href="/email-best-practices-skill">
    Skills for AI agents to build production-ready email systems with Resend.
  </Card>

  <Card title="React Email Skill" href="/react-email-skill">
    Skills for AI agents to build HTML emails using React components with Resend.
  </Card>

  <Card title="Resend Skill" href="/resend-skill">
    Skills for AI agents to send emails with Resend.
  </Card>
</CardGroup>

## Account Management

<CardGroup>
  <Card title="What is Resend Pricing?" href="/knowledge-base/what-is-resend-pricing">
    Learn more about Resend's pricing plans.
  </Card>

  <Card title="How can I delete my Resend account?" href="/knowledge-base/how-can-i-delete-my-resend-account">
    Learn how to permanently delete your Resend account and data.
  </Card>

  <Card title="How to Handle API Keys" href="/knowledge-base/how-to-handle-api-keys">
    Best practices for managing and securing your Resend API keys.
  </Card>
</CardGroup>

## Testing

<CardGroup>
  <Card title="E2E Testing with Playwright" href="/knowledge-base/end-to-end-testing-with-playwright">
    Set up end-to-end email testing with Playwright and Resend.
  </Card>

  <Card title="What email addresses to use for testing?" href="/knowledge-base/what-email-addresses-to-use-for-testing">
    Use Resend's test email addresses to simulate different delivery scenarios.
  </Card>
</CardGroup>


# IONOS
Source: https://resend.com/docs/knowledge-base/ionos

Verify your domain on IONOS with Resend.

## Add Domain to Resend

First, log in to your [Resend Account](https://resend.com/login) and [add a domain](https://resend.com/domains).

<img alt="Domain Details" />

<Tip>
  It is [best practice to use a
  subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain)
  (updates.example.com) instead of the root domain (example.com). Using a
  subdomain allows for proper reputation segmentation based on topics or purpose
  (e.g. marketing) and is especially important if receiving emails with Resend.
</Tip>

## Log in to IONOS

Log in to your [IONOS account](https://my.ionos.com/domains):

1. Choose your Domain from the `Domain` list.
2. Select the `DNS` tab to get to the page to manage DNS records.

<img alt="Domain Details" />

## Add MX SPF Record

Select “Add record” on IONOS to copy and paste the values MX from Resend.

1. On the `Add a DNS Record` page, select `MX`.
2. Type `send` for the `Name` of the record.
3. Copy the MX Value from Resend into the `Points to` field.
4. Use the default `Priority` of `10`.
5. Use the default TTL of `1 hour`.
6. Select `Save`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to IONOS:

| IONOS     | Resend   | Example Value                           |
| --------- | -------- | --------------------------------------- |
| Type      | Type     | `MX Record`                             |
| Name      | Name     | `send`                                  |
| Points to | Content  | `feedback-smtp.us-east-1.amazonses.com` |
| TTL       | TTL      | `1 hour`                                |
| Priority  | Priority | `10`                                    |

<Info>
  Do not use the same priority for multiple records. If Priority `10` is already
  in use on another record, try a higher value `20` or `30`.
</Info>

## Add TXT SPF Record

In the same section, select “Add record” again.

1. On the `Add a DNS Record` page, select `TXT`.
2. Type `send` for the `Host name` of the record.
3. Copy the TXT Value Resend into the `TXT value` field.
4. Use the default TTL of `1 hour`.
5. Select `Save`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to IONOS:

| IONOS     | Resend  | Example Value                         |
| --------- | ------- | ------------------------------------- |
| Type      | Type    | `TXT Record`                          |
| Host name | Name    | `send`                                |
| TXT value | Content | `"v=spf1 include:amazonses.com ~all"` |
| TTL       | -       | `1 hour`                              |

## Add TXT DKIM Records

In the same section, select “Add record” again.

1. On the `Add a DNS Record` page, select `TXT`.
2. Type `resend._domainkey` for the `Host name` of the record.
3. Copy the record value from Resend into the `TXT value` field.
4. Use the default TTL of `1 hour`.
5. Select `Save`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `resend._domainkey.example.com`, paste only `resend._domainkey` (or
  `resend._domainkey.subdomain` if you're using a subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to IONOS:

| IONOS     | Resend  | Example Value                |
| --------- | ------- | ---------------------------- |
| Type      | Type    | `TXT Record`                 |
| Host name | Name    | `send`                       |
| TXT value | Content | `p=example_domain_key_value` |
| TTL       | -       | `1 hour`                     |

## Receiving Emails

If you want to receive emails at your domain, toggle the "Receiving" switch on the domain details page.

<img alt="Enable Receiving Emails for a verified domain" />

<Warning>
  When you enable Inbound on a domain, Resend receives *all emails* sent to that
  specific domain depending on the priority of the MX record. For this reason,
  we strongly recommend verifying a subdomain (`subdomain.example.com`) instead
  of the root domain (`example.com`). Learn more about [avoiding conflicts with
  your existing MX
  records](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
</Warning>

Select “Add record” on IONOS:

1. On the `Add a DNS Record` page, select `MX`.
2. Type `inbound` (or whatever your subdomain is) for the `Name` of the record.
3. Copy the MX Value from Resend into the `Points to` field.
4. Use the default `Priority` of `10`.
5. Use the default TTL of `1 hour`.
6. Select `Save`.

Below is a mapping of the record fields from Resend to IONOS:

| IONOS     | Resend   | Example Value                          |
| --------- | -------- | -------------------------------------- |
| Type      | Type     | `MX Record`                            |
| Name      | Name     | `inbound`                              |
| Points to | Content  | `inbound-smtp.us-east-1.amazonaws.com` |
| TTL       | TTL      | `1 hour`                               |
| Priority  | Priority | `10`                                   |

After verifying your domain, create a webhook to process incoming emails. For help setting up a webhook, how to access email data and attachments, forward emails, and more, see [our guide on receiving emails with Resend](/docs/dashboard/receiving/introduction).

## Complete Verification

Now click [Verify DNS Records](https://resend.com/domains) on your Domain in Resend. It may take a few hours to complete the verification process (often much faster).

## Troubleshooting

If your domain is not successfully verified, these are some common troubleshooting methods.

<AccordionGroup>
  <Accordion title="Resend shows my domain verification failed.">
    Review the records you added to IONOS to rule out copy and paste errors.
  </Accordion>

  <Accordion title="It has been longer than 72 hours and my domain is still Pending.">
    [Review our guide on a domain not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying).
  </Accordion>
</AccordionGroup>


# Is it better to send emails from a subdomain or the root domain?
Source: https://resend.com/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain

Discover why sending emails from a subdomain can be better than using a root domain.

We recommend sending emails from a subdomain (`notifications.acme.com`) instead of your root/apex domain (`acme.com`).

There are **two main goals to achieve with your domain setup**:

* Reputation Isolation
* Sending Purpose Transparency

## Reputation Isolation

Things happen. Maybe someone decides to DDOS your signup page and you get stuck sending tens of thousands of bounced verification emails to burner addresses. Or maybe a cold outreach campaign gets out of hand and your sending gets pegged as spam.

Whatever it is, you want to be consistently hedging your reputation. One way to do this is by not using your root domain. This allows you to quarantine a compromised subdomain if needed. If your root domain ends up with a jeopardized reputation, it can be a long road to recovery.

## Sending Purpose Transparency

All of us want all of our emails to go right to the top of the priority folder of the inbox, but the reality is, not all of our email belongs there. A password reset email carries higher priority than a monthly product update. Inbox providers like Outlook and Gmail are constantly trying to triage incoming mail to put only the most important stuff in that priority spot, and move the rest towards Promotional or even Spam.

By segmenting your sending purposes by subdomain, you give Inbox Providers clear indication of where to place your emails, which builds trust and confidence.

## Avoid "Lookalike" Domains

Never use domains that look like your main brand but aren’t actually your main brand. These brand-adjacent domains like `getacme-mail.com` or `acme-alerts.com` can appear suspicious to spam filters and confusing to your recipients. Inbox providers may flag them as phishing or spoofing attempts, and your users are more likely to ignore, delete, or even report the emails as spam.

If you’re launching a new project or sending for a different purpose, again use a subdomain of your main domain. Sticking with clear, consistent subdomains helps reinforce your brand identity and builds trust with inbox providers and recipients alike.

<Note>
  We cover this in depth in our [deliverability
  guide](/docs/knowledge-base/how-do-i-avoid-gmails-spam-folder#establish-sending-patterns).
</Note>


# Send emails with n8n and Resend
Source: https://resend.com/docs/knowledge-base/n8n-integration

Learn how to install and use the official Resend node for n8n to send emails, manage contacts, handle webhooks, and more.

[n8n](https://n8n.io) is a workflow automation platform that lets you connect apps and build powerful automations. The official [Resend node](https://github.com/resend/n8n-nodes-resend) (`n8n-nodes-resend`) provides full coverage of the Resend API. From within n8n, you can send emails, manage contacts, handle domains, and trigger workflows from email events.

<img alt="Resend node in the n8n editor" />

## How to use Resend's n8n node

<Steps>
  <Step title="Install the Resend node">
    1. Open the nodes panel by selecting **+** or pressing **Tab**
    2. Search for **Resend**
    3. Select **Install** to install the node for your instance
    4. The node is now available in all your workflows

    <video />
  </Step>

  <Step title="Setup Resend">
    1. [Create an API Key](https://resend.com/api-keys): copy this key to your clipboard
    2. [Verify your own domain](https://resend.com/domains): to send to email addresses other than your own
  </Step>

  <Step title="Add your Resend API credential">
    1. In n8n, go to **Credentials** > **Add credential**.
    2. Search for **Resend API** and paste your API key.

    <video />

    This credential is used by the main **Resend** node for all API operations.
  </Step>

  <Step title="Send your first email">
    1. Click the **+** (Add node) connector on the canvas.
    2. Search for **Resend** in the nodes panel.
    3. n8n displays a list of available actions — select **Send an Email**.
    4. The Resend node is added to your workflow with the **Send** operation pre-selected.
    5. Fill in the **From**, **To**, **Subject**, and **Email Body** fields.
    6. Execute the node.

    <Note>
      By default, you can only send emails to your own email address using the
      `onboarding@resend.dev` sender domain. To send to other recipients, [add a
      custom domain](/docs/dashboard/domains/introduction) to your Resend account.
    </Note>
  </Step>
</Steps>

## Human in the Loop (Send and Wait)

The **Send and Wait for Response** operation enables human-in-the-loop workflows. Send an email and pause the workflow until the recipient responds, via approval buttons or a free-text form.

1. Select the **Email** resource and the **Send and Wait for Response** operation.
2. Choose a **Response Type**: **Approval** (buttons) or **Free Text** (form).
3. Configure the email content and any wait-time limits.
4. The workflow pauses until the recipient clicks a button or submits the form.

| Option                   | Description                                              |
| ------------------------ | -------------------------------------------------------- |
| **Response Type**        | Choose between Approval (buttons) or Free Text (form)    |
| **Approval Type**        | Single button (Approve only) or Double (Approve/Decline) |
| **Button Labels**        | Customize the button text                                |
| **Message Button Label** | Label for the form link button (Free Text mode)          |
| **Response Form Title**  | Title shown on the response form                         |
| **Limit Wait Time**      | Set a timeout for the wait period                        |

## Receive webhooks with the Resend Trigger

The **Resend Trigger** node lets you start workflows automatically when email events occur in Resend (e.g., an email is delivered, opened, or bounced). Webhook signatures are verified automatically using Svix.

### Set up the Trigger node

1. Add a **Resend Trigger** node to your workflow.
2. Create a **Resend Webhook Signing Secret** credential:
   * Create a webhook endpoint in the [Resend Dashboard](https://resend.com/webhooks).
   * Copy the signing secret (starts with `whsec_`).
   * In n8n, go to **Credentials** > **Add credential**, search for **Resend Webhook Signing Secret**, and paste the secret.

<Info>
  Give each webhook credential a unique name (e.g., "Resend Webhook — Bounces"
  or "Resend Webhook — Delivery Events"). This makes it much easier to identify
  the right credential when you have multiple triggers connected to different
  webhooks.
</Info>

3. Select the events you want to listen for.
4. Copy the **webhook URL** from the Trigger node and paste it into your Resend Dashboard webhook configuration.

### Supported trigger events

| Event                    | Description                                                                                                                  |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
| `email.sent`             | Email sent to recipient                                                                                                      |
| `email.delivered`        | Email delivered successfully                                                                                                 |
| `email.delivery_delayed` | Email delivery delayed                                                                                                       |
| `email.failed`           | Email failed to send due to an error (for example, invalid recipients, API key issues, domain verification, or quota limits) |
| `email.opened`           | Recipient opened the email                                                                                                   |
| `email.clicked`          | Link clicked in email                                                                                                        |
| `email.bounced`          | Email bounced                                                                                                                |
| `email.complained`       | Spam complaint received                                                                                                      |
| `email.received`         | Resend successfully received an inbound email                                                                                |
| `email.scheduled`        | Email is scheduled to be sent                                                                                                |
| `email.suppressed`       | Email is suppressed by Resend                                                                                                |
| `contact.created`        | New contact added                                                                                                            |
| `contact.updated`        | Contact modified                                                                                                             |
| `contact.deleted`        | Contact removed                                                                                                              |
| `domain.created`         | New domain added                                                                                                             |
| `domain.updated`         | Domain modified                                                                                                              |
| `domain.deleted`         | Domain removed                                                                                                               |

## Example workflow: Send a welcome email when a contact is created

Here's a simple workflow you can build with the Resend nodes:

1. **Resend Trigger**: listens for `contact.created` events.
2. **Resend** (Email > Send): sends a welcome email to the new contact using data from the trigger.

The Trigger-Action pattern works for any event. For example, you can notify your team on Slack when an email bounces, or log delivery events to a spreadsheet.

<Note>
  The Resend node is also available as an [AI
  tool](https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolworkflow/)
  in n8n, so you can use it inside AI agent workflows.
</Note>


# Namecheap
Source: https://resend.com/docs/knowledge-base/namecheap

Verify your domain on Namecheap with Resend.

## Add Domain to Resend

First, log in to your [Resend Account](https://resend.com/login) and [add a domain](https://resend.com/domains).

<img alt="Domain Details" />

<Tip>
  It is [best practice to use a
  subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain)
  (updates.example.com) instead of the root domain (example.com). Using a
  subdomain allows for proper reputation segmentation based on topics or purpose
  (e.g. marketing) and is especially important if receiving emails with Resend.
</Tip>

## Log in to Namecheap

1. Log in to your [Namecheap account](https://ap.www.namecheap.com).

2. Click `Manage` for the domain.

   <img alt="Domain Details" />

   <Info>You may need to expand a dropdown to see the `Manage` button.</Info>

3. Go to the `Advanced DNS` page for the domain you want to verify.

   <img alt="Domain Details" />

## Add MX SPF Record

<Warning>
  If you are changing the MX configuration from `Gmail` to `Custom MX`, you need
  to [setup new MX records for
  Gmail](https://support.google.com/a/answer/174125). If you don't setup new
  records, receiving mail in your gmail inboxes will stop.
</Warning>

Under the `Mail Settings` section, click the dropdown and select `Custom MX`:

1. Type `send` for the `Host` of the record.
2. Copy the MX Value from Resend into the `Value` field.
3. Use the `Automatic` TTL.
4. Select `Save all changes`.

<img alt="Domain Details" />

<br />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Namecheap:

| Namecheap | Resend   | Example Value                           |
| --------- | -------- | --------------------------------------- |
| Type      | Type     | `MX Record`                             |
| Host      | Name     | `send`                                  |
| TTL       | TTL      | `Automatic`                             |
| Value     | Content  | `feedback-smtp.us-east-1.amazonses.com` |
| -         | Priority | `10`                                    |

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<Info>
  Namecheap does not label the `priority` column. It is the empty column after
  `Value`. Do not use the same priority for multiple records. If Priority `10`
  is already in use, try a higher value `20` or `30`.
</Info>

## Add TXT SPF Record

Under the `Host Records` section, click `Add New Record`:

1. Set the `Type` to `TXT Record`.
2. Enter `send` into the `Host` field.
3. Copy the TXT Value from Resend into the `Value` field.
4. Use the `Automatic` TTL.
5. Select `Save all changes`.

<img alt="Domain Details" />

<br />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Namecheap:

| Namecheap | Resend  | Example Value                         |
| --------- | ------- | ------------------------------------- |
| Type      | Type    | `TXT Record`                          |
| Host      | Name    | `send`                                |
| TTL       | TTL     | `Automatic`                           |
| Value     | Content | `"v=spf1 include:amazonses.com ~all"` |

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

## Add TXT DKIM Records

In that same `Host Records` section, click `Add New Record`.

1. Set the `Type` to `TXT Record`.
2. Enter `resend._domainkey` into the `Host` field.
3. Copy the TXT Value from Resend into the `Value` field.
4. Use the `Automatic` TTL.
5. Select `Save all changes`.

<img alt="Domain Details" />

<br />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Namecheap:

| Namecheap | Resend  | Example Value                |
| --------- | ------- | ---------------------------- |
| Type      | Type    | `TXT Record`                 |
| Host      | Name    | `resend._domainkey`          |
| TTL       | TTL     | `Automatic`                  |
| Value     | Content | `p=example_domain_key_value` |

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `resend._domainkey.example.com`, paste only `resend._domainkey` (or
  `resend._domainkey.subdomain` if you're using a subdomain).
</Info>

## Receiving Emails

If you want to receive emails at your domain, toggle the "Receiving" switch on the domain details page.

<img alt="Enable Receiving Emails for a verified domain" />

<Warning>
  When you enable Inbound on a domain, Resend receives *all emails* sent to that
  specific domain depending on the priority of the MX record. For this reason,
  we strongly recommend verifying a subdomain (`subdomain.example.com`) instead
  of the root domain (`example.com`). Learn more about [avoiding conflicts with
  your existing MX
  records](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
</Warning>

Under the `Mail Settings` section, click the dropdown and select `Custom MX`:

1. Type `inbound` (or whatever your subdomain is) for the `Host` of the record.
2. Copy the MX Value from Resend into the `Value` field.
3. Use the `Automatic` TTL.
4. Select `Save all changes`.

Below is a mapping of the record fields from Resend to Namecheap:

| Namecheap | Resend   | Example Value                          |
| --------- | -------- | -------------------------------------- |
| Type      | Type     | `MX Record`                            |
| Host      | Name     | `inbound`                              |
| TTL       | TTL      | `Automatic`                            |
| Value     | Content  | `inbound-smtp.us-east-1.amazonaws.com` |
| -         | Priority | `10`                                   |

After verifying your domain, create a webhook to process incoming emails. For help setting up a webhook, how to access email data and attachments, forward emails, and more, see [our guide on receiving emails with Resend](/docs/dashboard/receiving/introduction).

## Complete Verification

Now click [Verify DNS Records](https://resend.com/domains) on your Domain in Resend. It may take up to 72 hours to complete the verification process (often much faster).

## Troubleshooting

If your domain is not successfully verified, these are some common troubleshooting methods.

<AccordionGroup>
  <Accordion title="Resend shows my domain verification failed.">
    Review the records you added to Namecheap to rule out copy and paste errors.
  </Accordion>

  <Accordion title="It has been longer than 72 hours and my domain is still Pending.">
    [Review our guide on a domain not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying).
  </Accordion>
</AccordionGroup>


# Porkbun
Source: https://resend.com/docs/knowledge-base/porkbun

Verify your domain on Porkbun with Resend.

## Add Domain to Resend

First, log in to your [Resend Account](https://resend.com/login) and [add a domain](https://resend.com/domains).

<img alt="Domain Details" />

<Tip>
  It is [best practice to use a
  subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain)
  (updates.example.com) instead of the root domain (example.com). Using a
  subdomain allows for proper reputation segmentation based on topics or purpose
  (e.g. marketing) and is especially important if receiving emails with Resend.
</Tip>

## Log in to Porkbun

Log in to your [Porkbun account](https://porkbun.com/account/domainsSpeedy):

1. Select the `DNS` option under your domain to manage DNS records.

<img alt="Domain Details" />

## Add MX SPF Record

In the `DNS` section on Porkbun copy and paste the values MX from Resend:

1. On the `Type` page, choose `MX`.
2. Type `send` for the `Host` of the record.
3. Copy the MX Value from Resend into the `Answer / Value` field.
4. Use the default TTL of `600`.
5. In the `Priority` field enter `10`.
6. Select `Add`.

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Porkbun:

| Porkbun        | Resend   | Example Value                           |
| -------------- | -------- | --------------------------------------- |
| Type           | Type     | `MX Record`                             |
| Host           | Name     | `send`                                  |
| Answer / Value | Content  | `feedback-smtp.us-east-1.amazonses.com` |
| TTL            | TTL      | `600`                                   |
| Priority       | Priority | `10`                                    |

<Info>
  Do not use the same priority for multiple records. If Priority `10` is already
  in use on another record, try a higher value `20` or `30`.
</Info>

## Add TXT SPF Record

On the same section:

1. On the `Type` page, choose `TXT`.
2. Type `send` for the `Host` of the record.
3. Copy the TXT Value Resend into the `Answer / Value` field.
4. Use the default TTL of `600`.
5. Select `Add Record`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Porkbun:

| Porkbun        | Resend  | Example Value                         |
| -------------- | ------- | ------------------------------------- |
| Type           | Type    | `TXT Record`                          |
| Host           | Name    | `send`                                |
| Answer / Value | Content | `"v=spf1 include:amazonses.com ~all"` |
| TTL            | TTL     | `600`                                 |

## Add TXT DKIM Records

On the same `Create Record` section:

1. On the `Type` page, choose `TXT`.
2. Type `resend._domainkey` for the `Host` of the record.
3. Copy the TXT Value Resend into the `Answer / Value` field.
4. Use the default TTL of `600`.
5. Select `Add Record`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `resend._domainkey.example.com`, paste only `resend._domainkey` (or
  `resend._domainkey.subdomain` if you're using a subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Porkbun:

| Porkbun        | Resend  | Example Value                |
| -------------- | ------- | ---------------------------- |
| Type           | Type    | `TXT Record`                 |
| Host           | Name    | `send`                       |
| Answer / Value | Content | `p=example_domain_key_value` |
| TTL            | TTL     | `600`                        |

## Receiving Emails

If you want to receive emails at your domain, toggle the "Receiving" switch on the domain details page.

<img alt="Enable Receiving Emails for a verified domain" />

<Warning>
  When you enable Inbound on a domain, Resend receives *all emails* sent to that
  specific domain depending on the priority of the MX record. For this reason,
  we strongly recommend verifying a subdomain (`subdomain.example.com`) instead
  of the root domain (`example.com`). Learn more about [avoiding conflicts with
  your existing MX
  records](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
</Warning>

In the `DNS` section on Porkbun:

1. On the `Type` page, choose `MX`.
2. Type `inbound` (or whatever your subdomain is) for the `Host` of the record.
3. Copy the MX Value from Resend into the `Answer / Value` field.
4. Use the default TTL of `600`.
5. In the `Priority` field enter `10`.
6. Select `Add`.

Below is a mapping of the record fields from Resend to Porkbun:

| Porkbun        | Resend   | Example Value                          |
| -------------- | -------- | -------------------------------------- |
| Type           | Type     | `MX Record`                            |
| Host           | Name     | `inbound`                              |
| Answer / Value | Content  | `inbound-smtp.us-east-1.amazonaws.com` |
| TTL            | TTL      | `600`                                  |
| Priority       | Priority | `10`                                   |

After verifying your domain, create a webhook to process incoming emails. For help setting up a webhook, how to access email data and attachments, forward emails, and more, see [our guide on receiving emails with Resend](/docs/dashboard/receiving/introduction).

## Complete Verification

Now click [Verify DNS Records](https://resend.com/domains) on your Domain in Resend. It may take a few hours to complete the verification process (often much faster).

## Troubleshooting

If your domain is not successfully verified, these are some common troubleshooting methods.

<AccordionGroup>
  <Accordion title="Resend shows my domain verification failed.">
    Review the records you added to Porkbun to rule out copy and paste errors.
  </Accordion>

  <Accordion title="It has been longer than 72 hours and my domain is still Pending.">
    [Review our guide on a domain not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying).
  </Accordion>
</AccordionGroup>


# AWS Route 53
Source: https://resend.com/docs/knowledge-base/route53

Verify your domain on Route 53 with Resend.

## Add Domain to Resend

First, log in to your [Resend Account](https://resend.com/login) and [add a domain](https://resend.com/domains).

<img alt="Domain Details" />

<Tip>
  It is [best practice to use a
  subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain)
  (updates.example.com) instead of the root domain (example.com). Using a
  subdomain allows for proper reputation segmentation based on topics or purpose
  (e.g. marketing) and is especially important if receiving emails with Resend.
</Tip>

## Log in to Route 53

Then, log in to your [AWS Management Console, and open Route 53 console](https://console.aws.amazon.com/route53/), then click on your domain name. From there, click on `Create Record`.

<img alt="Domain Details" />

## Add MX SPF Record

1. Type in `send` for the `Record name`.
2. Select the `Record type` dropdown, and choose `MX`.
3. Copy the MX Value from your domain in Resend into the `Value` field.
4. Be sure to include the `10` in the `Value` field, as seen in the screenshot.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Route 53:

| Route 53       | Resend             | Example Value                              |
| -------------- | ------------------ | ------------------------------------------ |
| Record Type    | Type               | `MX Record`                                |
| Record name    | Name               | `send`                                     |
| Value          | Content & Priority | `10 feedback-smtp.us-east-1.amazonses.com` |
| TTL            | TTL                | `Use Route 53 Default (300)`               |
| Routing policy | -                  | `Simple routing`                           |

<Info>
  Route 53 does not label the `priority` column, and you will need to add this
  in to the `Value` section, as shown in the screenshot. Do not use the same
  priority for multiple records. If Priority `10` is already in use, try a
  number slightly higher like `11` or `12`.
</Info>

## Add TXT SPF Record

In the same section, choose `Add another record`:

1. Type in `send` for the `Record name`.
2. Click the `Record type` dropdown.
3. Select the `Record type` dropdown, and choose `TXT`.
4. Copy TXT Value from your domain in Resend into the `Value` field.

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Route 53:

| Route 53       | Resend  | Example Value                         |
| -------------- | ------- | ------------------------------------- |
| Record type    | Type    | `TXT Record`                          |
| Record name    | Name    | `send`                                |
| Value          | Content | `"v=spf1 include:amazonses.com ~all"` |
| TTL            | TTL     | `Use Route 53 Default (300)`          |
| Routing policy | -       | `Simple routing`                      |

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

## Add TXT DKIM Records

In the same section, choose `Add another record`:

1. Type in `resend._domainkey` for the `Record name`.
2. Change the `Record Type` to `TXT`.
3. Copy the TXT Value value from your domain in Resend to the `Value` text box.
4. Click on `Create Records`.

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Route 53:

| Route 53       | Resend  | Example Value                |
| -------------- | ------- | ---------------------------- |
| Record type    | Type    | `TXT Record`                 |
| Record name    | Name    | `resend._domainkey`          |
| Value          | Content | `p=example_domain_key_value` |
| TTL            | TTL     | `Use Route 53 Default (300)` |
| Routing policy | -       | `Simple routing`             |

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `resend._domainkey.example.com`, paste only `resend._domainkey` (or
  `resend._domainkey.subdomain` if you're using a subdomain).
</Info>

## Receiving Emails

If you want to receive emails at your domain, toggle the "Receiving" switch on the domain details page.

<img alt="Enable Receiving Emails for a verified domain" />

<Warning>
  When you enable Inbound on a domain, Resend receives *all emails* sent to that
  specific domain depending on the priority of the MX record. For this reason,
  we strongly recommend verifying a subdomain (`subdomain.example.com`) instead
  of the root domain (`example.com`). Learn more about [avoiding conflicts with
  your existing MX
  records](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
</Warning>

In the Route 53 console, click `Create Record`:

1. Type in `inbound` (or whatever your subdomain is) for the `Record name`.
2. Select the `Record type` dropdown, and choose `MX`.
3. Copy the MX Value from your domain in Resend into the `Value` field.
4. Be sure to include the `10` in the `Value` field (e.g., `10 inbound-smtp.us-east-1.amazonaws.com`).

Below is a mapping of the record fields from Resend to Route 53:

| Route 53       | Resend             | Example Value                             |
| -------------- | ------------------ | ----------------------------------------- |
| Record Type    | Type               | `MX Record`                               |
| Record name    | Name               | `inbound`                                 |
| Value          | Content & Priority | `10 inbound-smtp.us-east-1.amazonaws.com` |
| TTL            | TTL                | `Use Route 53 Default (300)`              |
| Routing policy | -                  | `Simple routing`                          |

After verifying your domain, create a webhook to process incoming emails. For help setting up a webhook, how to access email data and attachments, forward emails, and more, see [our guide on receiving emails with Resend](/docs/dashboard/receiving/introduction).

## Complete Verification

Now click [Verify DNS Records](https://resend.com/domains) on your Domain in Resend. It may take up to 5 hours to complete the verification process (often much faster).

## Troubleshooting

If your domain is not successfully verified, these are some common troubleshooting methods.

<AccordionGroup>
  <Accordion title="Resend shows my domain verification failed.">
    Review the records you added to Route 53 to rule out copy and paste errors.
  </Accordion>

  <Accordion title="It has been longer than 72 hours and my domain is still Pending.">
    [Review our guide on a domain not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying).
  </Accordion>
</AccordionGroup>


# How to prevent bounces with @privaterelay.appleid.com recipients?
Source: https://resend.com/docs/knowledge-base/sending-apple-private-relay

Sending to Apple Private Email Relay requires specific configuration steps to ensure your emails get delivered

If your website or application supports Sign In with Apple, your customers have the option to receive emails from you via Apple’s Private Email Relay service. This feature allows users to keep their actual email addresses private when they sign up or log in.

When a user selects the Hide My Email option, Apple assigns them a unique, randomly generated email address under the `@privaterelay.appleid.com` domain, which you can link to that specific user.

To ensure your emails are delivered through Apple’s Private Email Relay, you must first access the Apple Developer Portal and navigate to `Certificates, Identifiers & Profiles` > `More` > `Sign in with Apple for Email Communication` > `Configure`.

<Info>
  **Apple Offers Multiple Hide My Email Services**

  Starting with iOS 15, Apple provides two separate Hide My Email services—one through Sign in with Apple and another via iCloud+.

  This guide is specifically for apps and websites utilizing Sign in with Apple, which generates a unique email address for account creation and login purposes.
</Info>

## Register your sending domains

Apple mandates that you list the domains from which you will send emails to its service. Additionally, if your return-path domain differs from your sending domain, you must include that as well.

If you use Resend, note that its return-path domain is different since it operates through a subdomain. You will find this subdomain in your Domain settings, formatted as `send.yourdomain.tld` or `send.yoursubdomain.yourdomain.tld` for MX and SPF records. Ensure you add both your primary domain and the subdomain as Apple Email Sources.

## Register your email addresses

Alongside your Sending Domains, Apple requires registration of all email addresses used to send messages from those domains.

You can add these email addresses one by one or in a comma-separated list. If you use other email sources outside of Resend to send messages to Private Relay addresses, include those as well.

## Authenticate your sending domains

Since Resend mandates SPF and DKIM authentication for all domains sending emails through its service, your domain will automatically meet Apple’s authentication requirements.

## Troubleshooting bounces from @privaterelay.appleid.com

At times, emails sent to `@privaterelay.appleid.com` may still bounce. While the bounce messages may not always contain detailed explanations, common reasons include:

* The user has deleted their Hide My Email address from Apple’s settings.
* The user has exceeded their daily limit of 100 emails sent to and from their Hide My Email address.
* A misconfiguration in your settings. Double-check that all Sending Domains and From Addresses are correctly registered and authenticated with Apple.

Apple allows the account owner and admins in the Apple Developer Portal to receive notifications if messages fail to deliver through the relay. You can enable this setting in the portal.

***

Once you have completed these three steps, you will be ready to send emails to customers using Hide My Email addresses via Apple’s Private Email Relay service.

For additional details on Apple Private Email Relay and configuration options, refer to Apple’s official documentation:

* [Apple: Configure Private Email Relay Service](https://developer.apple.com/help/account/configure-app-capabilities/configure-private-email-relay-service/)
* [Apple: Communicating Using the Private Email Relay Service](https://developer.apple.com/documentation/signinwithapple/communicating-using-the-private-email-relay-service/)


# Setting up Resend for Multi-Tenant Applications
Source: https://resend.com/docs/knowledge-base/setting-up-resend-for-multi-tenants

Learn how to configure Resend for SaaS platforms where tenants send emails from their own domains.

Many SaaS platforms need to send emails on behalf of their tenants: whether it's transactional notifications, onboarding sequences, or marketing campaigns from a tenant's own domain. This guide walks through the two main approaches to configuring Resend for multi-tenant email sending.

<Info>
  There is no single "right" approach. Both options described below are valid
  and widely used. The best choice depends on your product's requirements, how
  much control you want over the sending experience, and your tenants' needs.
</Info>

## At a glance

| Factor                   | Single Account                                | Separate Accounts / BYOK                   |
| ------------------------ | --------------------------------------------- | ------------------------------------------ |
| **Setup complexity**     | Low: fully API-driven                         | Higher: manual account creation per tenant |
| **Sending isolation**    | Shared: one bad actor affects all             | Full: each tenant is isolated              |
| **Billing**              | Single plan covers all tenants                | Each tenant manages their own plan         |
| **Per-tenant analytics** | Not available natively                        | Each tenant has own dashboard              |
| **Webhook routing**      | Via tags or `from` domain                     | Each account has its own webhooks          |
| **Deliverability**       | Shared sender reputation                      | Independent sender reputation              |
| **Rate limits**          | Aggregate volume: likely requires an increase | Each tenant uses their own limits          |
| **Troubleshooting**      | Full visibility into all tenant emails        | Requires access to tenant's account        |

## Option A: Single Resend account

### How it works

In this approach, you manage everything from a single Resend account. You add each tenant's domain to your account, verify it, and create domain-scoped API keys so that each tenant can only send from their own domain. All sending, billing, and analytics flow through your account.

### Setting up a tenant domain

When a tenant signs up and wants to send from their own domain, you create and verify the domain via the API.

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
const domain = await resend.domains.create({ name: 'tenant-domain.com' });

// After the tenant adds DNS records, trigger verification
await resend.domains.verify(domain.id);
```

<Note>
  Domain verification is asynchronous: DNS records need to propagate before
  verification succeeds. You can use [webhooks](/docs/webhooks/introduction) to
  listen for `domain.verified` events instead of polling.
</Note>

### Creating a domain-scoped API key

Once the domain is verified, create an API key scoped to that domain. This ensures the tenant can only send from their own domain.

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
const apiKey = await resend.apiKeys.create({
  name: 'Tenant: tenant-domain.com',
  permission: 'sending_access',
  domain_id: domain.id,
});
```

<Warning>
  The API key token is only returned once at creation time. Store it securely:
  you will not be able to retrieve it again.
</Warning>

### Pros

* Seamless, fully API-driven setup: no manual steps required
* Domain-scoped API keys limit each tenant to their own domain
* Single account to manage billing, monitoring, and configuration

### Cons

* No per-tenant volume breakdown or analytics in the dashboard
* All tenants share your account's sender reputation
* Aggregate sending volume will likely require a [rate-limit increase](/docs/knowledge-base/account-quotas-and-limits) as you onboard tenants

<Warning>
  If one tenant engages in poor sending practices (spam, high bounce rates), it
  can affect deliverability for all tenants on your account. In severe cases,
  the entire account may be suspended.
</Warning>

## Option B: Separate accounts (BYOK)

### How it works

In the Bring Your Own Key (BYOK) model, each tenant creates their own Resend account, adds their domain, and provides you with their API key. Your application stores each tenant's API key and uses it when sending on their behalf.

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
// Initialize a Resend client with the tenant's own API key
const resend = new Resend(tenantApiKey);

await resend.emails.send({
  from: 'notifications@tenant-domain.com',
  to: 'user@example.com',
  subject: 'Your order has shipped',
  html: '<p>Your order #1234 is on its way.</p>',
});
```

### Pros

* Full sending isolation: each tenant's reputation and deliverability are independent
* No liability for tenant sending behavior on your account
* Tenants who already use Resend can reuse their existing account
* Each tenant has their own dashboard with analytics and logs
* Each tenant uses their own rate limits, so you're less likely to need increases

### Cons

* Requires each tenant to create a Resend account and manage their own plan
* More onboarding friction for tenants unfamiliar with email infrastructure

<Note>
  Team creation is not currently available via the API. Each tenant will need to
  create their Resend account manually through the
  [dashboard](https://resend.com/signup).
</Note>

## Billing implications

With **Option A**, you pay a single plan that covers all tenant sending volume. Your total email count is the aggregate of all tenants' emails, so choose a plan that accommodates your combined volume.

With **Option B**, each tenant is responsible for their own Resend plan and billing. This removes billing complexity from your side but means tenants need to manage their own subscription. See [Resend pricing](/docs/knowledge-base/what-is-resend-pricing) and [account quotas and limits](/docs/knowledge-base/account-quotas-and-limits) for details.

## Deliverability considerations

Sender reputation is tied to the sending account and its associated domains and IPs. This is the most important distinction between the two approaches.

With **Option A**, all tenants share the same sender reputation. If a single tenant sends to stale lists, generates high bounce rates, or triggers spam complaints, it can degrade deliverability for every tenant on your account. In the worst case, your entire account faces suspension.

With **Option B**, each tenant has a fully independent sender reputation. A problem with one tenant has zero impact on others. However, each tenant is responsible for following best practices on their own.

Regardless of which approach you choose, each new tenant domain must follow a [warm-up schedule](/docs/knowledge-base/warming-up). Using a [subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain) for sending is also a good practice to protect the tenant's root domain reputation.

## Webhook routing

### Option A: Tags for tenant identification

When using a single account, use [tags](/docs/dashboard/emails/tags) when sending emails to identify which tenant triggered the message. Tags are included in webhook payloads, so you can route events back to the correct tenant.

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
await resend.emails.send({
  from: 'notifications@tenant-domain.com',
  to: 'user@example.com',
  subject: 'Welcome aboard',
  html: '<p>Thanks for signing up.</p>',
  tags: [{ name: 'tenant_id', value: 'tenant_abc123' }],
});
```

When you receive a [webhook](/docs/webhooks/introduction) event, the `tags` array in the payload will include `tenant_id`, allowing you to route the event to the appropriate tenant in your system.

### Option B: Natural isolation

With separate accounts, each tenant configures their own webhooks in their Resend dashboard. Events are naturally isolated: you don't need to tag or filter anything.

## Migrating between approaches

If your needs change, you can migrate from one approach to the other.

**A to B (Single Account → Separate Accounts):**

* Each tenant creates their own Resend account
* Tenants add and verify their domains in their new accounts
* You replace the shared API key with each tenant's individual key in your application
* Remove the tenant domains from your original account

**B to A (Separate Accounts → Single Account):**

* Add each tenant's domain to your central account and verify DNS records
* Create domain-scoped API keys for each tenant
* Update your application to use the new keys
* Tenants can deactivate their individual accounts

<Warning>
  When moving a domain between accounts, it will need to be deleted from the
  original account before being re-verified in the second account. Plan for
  potential sending interruptions during the DNS propagation window.
</Warning>

## Share your feedback

Please share any feedback on your experience using Resend for your multi-tenant application to help us better serve this use case.

<Info>
  We're tracking interest for improved multi-tenant capabilities. Share your use
  case at [support@resend.com](mailto:support@resend.com).
</Info>

## Related resources

<CardGroup>
  <Card title="Create Domain API" href="/api-reference/domains/create-domain">
    Add and verify tenant domains programmatically.
  </Card>

  <Card title="Create API Key API" href="/api-reference/api-keys/create-api-key">
    Create domain-scoped API keys for tenant isolation.
  </Card>

  <Card title="Webhooks" href="/webhooks/introduction">
    Set up webhooks to receive real-time email event notifications.
  </Card>

  <Card title="Managing Tags" href="/dashboard/emails/tags">
    Use tags to organize emails and route webhook events by tenant.
  </Card>
</CardGroup>


# Do you need to add an unsubscribe link to all of your emails sent with Resend?
Source: https://resend.com/docs/knowledge-base/should-i-add-an-unsubscribe-link

Learn best practices about using unsubscribe links.

Transactional emails are generally exempt from including an unsubscribe link. Unlike marketing emails, transactional emails serve a functional purpose, such as account confirmation, password resets, and order confirmations.

As a best practice, tell recipients how to opt out of receiving future email from you if the content is more related to nurturing relationships with your customers, rather than pragmatic, action-oriented emails.

Laws enforced by the FTC and GDPR prioritize giving recipients a clear way to give and withdraw their consent to receiving email marketing content. Additionally, not having an option for opting out of emails risks recipients complaining or marking the email as spam, which can hurt your reputation as a sender.

Here is more on how to [manually add and manage unsubscribe links](https://resend.com/docs/dashboard/emails/add-unsubscribe-to-transactional-emails).

If you're using [Resend Broadcasts or Automations](https://resend.com/docs/dashboard/audiences/managing-unsubscribe-list), Resend will automatically handle unsubscribe requests once you include `{{{RESEND_UNSUBSCRIBE_URL}}}` in your email. You can include the Unsubscribe Footer in your Broadcasts, which will be automatically replaced with the correct link for each contact, or use `{{{RESEND_UNSUBSCRIBE_URL}}}` as a link target if you want to customize the unsubscribe footer.


# Squarespace
Source: https://resend.com/docs/knowledge-base/squarespace

Verify your domain on Squarespace with Resend.

## Add Domain to Resend

First, log in to your [Resend Account](https://resend.com/login) and [add a domain](https://resend.com/domains).

<img alt="Domain Details" />

<Tip>
  It is [best practice to use a
  subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain)
  (updates.example.com) instead of the root domain (example.com). Using a
  subdomain allows for proper reputation segmentation based on topics or purpose
  (e.g. marketing) and is especially important if receiving emails with Resend.
</Tip>

## Log in to Squarespace

Log in to your [Squarespace domains page](https://account.squarespace.com/domains) and click on your domain.

<img alt="Domain Details" />

## Add MX SPF Record

Scroll down to the **Custom records** section and select `Add record` on Squarespace.

1. Type `send` for the `Host` of the record.
2. Set the `Type` to `MX`.
3. Set the `Priority` to `10`.
4. Use the Default 4 hours for `TTL`.
5. Copy the MX Value from Resend into the `Mail Server` field
6. Select `Save`.

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Squarespace:

| Squarespace | Resend   | Example Value                           |
| ----------- | -------- | --------------------------------------- |
| Type        | Type     | `MX`                                    |
| Host        | Name     | `send`                                  |
| TTL         | TTL      | `4 hrs` (default)                       |
| Mail Server | Content  | `feedback-smtp.us-east-1.amazonses.com` |
| Priority    | Priority | `10`                                    |

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<Info>
  Do not use the same priority for multiple records. If Priority `10` is already
  in use, try a higher value `20` or `30`.
</Info>

## Add TXT SPF Record

In the same **Custom records** section, select `Add Record` on Squarespace.

1. Type `send` for the `Host` of the record.
2. Set the `Type` to `TXT`.
3. Use the Default 4 hours for `TTL`.
4. Copy the TXT Value from Resend into the `Text` field
5. Select `Save`.

Add the **TXT Record** from your domain in Resend to Squarespace and click "Save".

<img alt="Domain Details" />

<br />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Squarespace:

| Squarespace | Resend  | Example Value                         |
| ----------- | ------- | ------------------------------------- |
| Type        | Type    | `TXT`                                 |
| Host        | Name    | `send`                                |
| TTL         | TTL     | `4 hrs` (default)                     |
| Text        | Content | `"v=spf1 include:amazonses.com ~all"` |

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

## Add TXT DKIM Records

In the same **Custom records** section, select `Add Record` on Squarespace.

1. Type `resend._domainkey` for the `Host` of the record.
2. Set the `Type` to `TXT`.
3. Use the Default 4 hours for `TTL`.
4. Copy the TXT Value from Resend into the `Text` field
5. Select `Save`.

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Squarespace:

| Squarespace | Resend  | Example Value                |
| ----------- | ------- | ---------------------------- |
| Type        | Type    | `TXT`                        |
| Host        | Name    | `resend._domainkey`          |
| TTL         | TTL     | `4 hrs` (default)            |
| Text        | Content | `p=example_domain_key_value` |

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `resend._domainkey.example.com`, paste only `resend._domainkey` (or
  `resend._domainkey.subdomain` if you're using a subdomain).
</Info>

## Receiving Emails

If you want to receive emails at your domain, toggle the "Receiving" switch on the domain details page.

<img alt="Enable Receiving Emails for a verified domain" />

<Warning>
  When you enable Inbound on a domain, Resend receives *all emails* sent to that
  specific domain depending on the priority of the MX record. For this reason,
  we strongly recommend verifying a subdomain (`subdomain.example.com`) instead
  of the root domain (`example.com`). Learn more about [avoiding conflicts with
  your existing MX
  records](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
</Warning>

Scroll down to the **Custom records** section and select `Add record` on Squarespace:

1. Type `inbound` (or whatever your subdomain is) for the `Host` of the record.
2. Set the `Type` to `MX`.
3. Set the `Priority` to `10`.
4. Use the Default 4 hours for `TTL`.
5. Copy the MX Value from Resend into the `Mail Server` field.
6. Select `Save`.

Below is a mapping of the record fields from Resend to Squarespace:

| Squarespace | Resend   | Example Value                          |
| ----------- | -------- | -------------------------------------- |
| Type        | Type     | `MX`                                   |
| Host        | Name     | `inbound`                              |
| TTL         | TTL      | `4 hrs` (default)                      |
| Mail Server | Content  | `inbound-smtp.us-east-1.amazonaws.com` |
| Priority    | Priority | `10`                                   |

After verifying your domain, create a webhook to process incoming emails. For help setting up a webhook, how to access email data and attachments, forward emails, and more, see [our guide on receiving emails with Resend](/docs/dashboard/receiving/introduction).

## Complete Verification

Now click [Verify DNS Records](https://resend.com/domains) on your Domain in Resend. It may take up to 72 hours to complete the verification process (often much faster).

## Troubleshooting

If your domain is not successfully verified, these are some common troubleshooting methods.

<AccordionGroup>
  <Accordion title="Resend shows my domain verification failed.">
    Review the records you added to Squarespace to rule out copy and paste errors.
  </Accordion>

  <Accordion title="It has been longer than 72 hours and my domain is still Pending.">
    [Review our guide on a domain not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying).
  </Accordion>
</AccordionGroup>


# Strato
Source: https://resend.com/docs/knowledge-base/strato

Verify your domain on Strato with Resend.

## Add Domain to Resend

First, log in to your [Resend Account](https://resend.com/login) and [add a domain](https://resend.com/domains).

<img alt="Domain Details" />

<Tip>
  It is [best practice to use a
  subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain)
  (updates.example.com) instead of the root domain (example.com). Using a
  subdomain allows for proper reputation segmentation based on topics or purpose
  (e.g. marketing) and is especially important if receiving emails with Resend.
</Tip>

## Log in to Strato

Log in to your [Strato account](https://www.strato.es/apps/CustomerService):

1. In the left-hand navigation, go to Domains > Manage Domain.

<img alt="Domain Details" />

## Add MX SPF Record

1. On the domain page, click on the gear icon to redirect to Settings.
2. Create a new subdomain named `send`.
3. Navigate to the subdomain settings.
4. Go to the `DNS` tab, you'll see a list of DNS records you can update. Click on `manage` MX record.
5. Select own mail server.
6. Copy MX value from Resend into `Server` field.
7. Use the default priority `Low`.
8. Save settings.

<Info>
  By default, Strato domains use Strato mail server which uses `mail` as their
  send path. You will need to bypass this default behavior by creating a
  subdomain and setting the MX record there.
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Strato:

| Strato      | Resend   | Example Value                            |
| ----------- | -------- | ---------------------------------------- |
| Type        | Type     | `MX Record`                              |
| Name        | Name     | `send`                                   |
| Mail server | Content  | `feedback-smtp.eu-west-1.amazonses.com.` |
| Priority    | Priority | `Low`                                    |

## Add TXT SPF Record

On the base domain settings:

1. Go to the `DNS` tab.
2. Manage TXT and CNAME records.
3. On the bottom, click `Create another record`.
4. Choose `TXT` type.
5. Add `send` for the `name` record.
6. For `value` input `v=spf1 include:amazonses.com ~all`.
7. Save settings.

<Info>
  Strato provides a standard DMARC record similar to Resend's recommended value:
  `v=DMARC1;p=reject;`.
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Strato:

| Strato | Resend  | Example Value                       |
| ------ | ------- | ----------------------------------- |
| Type   | Type    | `TXT Record`                        |
| Name   | Name    | `send`                              |
| Value  | Content | `v=spf1 include:amazonses.com ~all` |

## Add TXT DKIM Records

On the same TXT and CNAME manage page:

1. Click `Create another record`.
2. Choose `TXT` type.
3. Add `resend._domainkey` for the `Name` record.
4. Copy the record value from Resend into the TXT value field.
5. Save settings.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `resend._domainkey.example.com`, paste only `resend._domainkey` (or
  `resend._domainkey.subdomain` if you're using a subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Strato:

| Strato | Resend  | Example Value                |
| ------ | ------- | ---------------------------- |
| Type   | Type    | `TXT Record`                 |
| Name   | Name    | `send`                       |
| Value  | Content | `p=example_domain_key_value` |

<Info>
  Copy DKIM value using the small copy icon in Resend. DKIM records are
  case-sensitive and must match up exactly.
</Info>

## Receiving Emails

If you want to receive emails at your domain, toggle the "Receiving" switch on the domain details page.

<img alt="Enable Receiving Emails for a verified domain" />

<Warning>
  When you enable Inbound on a domain, Resend receives *all emails* sent to that
  specific domain depending on the priority of the MX record. For this reason,
  we strongly recommend verifying a subdomain (`subdomain.example.com`) instead
  of the root domain (`example.com`). Learn more about [avoiding conflicts with
  your existing MX
  records](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
</Warning>

1. Create a new subdomain named `inbound` (or whatever your subdomain is).
2. Navigate to the subdomain settings.
3. Go to the `DNS` tab and click on `manage` MX record.
4. Select own mail server.
5. Copy MX value from Resend into `Server` field.
6. Use the default priority `Low`.
7. Save settings.

Below is a mapping of the record fields from Resend to Strato:

| Strato      | Resend   | Example Value                           |
| ----------- | -------- | --------------------------------------- |
| Type        | Type     | `MX Record`                             |
| Name        | Name     | `inbound`                               |
| Mail server | Content  | `inbound-smtp.us-east-1.amazonaws.com.` |
| Priority    | Priority | `Low`                                   |

After verifying your domain, create a webhook to process incoming emails. For help setting up a webhook, how to access email data and attachments, forward emails, and more, see [our guide on receiving emails with Resend](/docs/dashboard/receiving/introduction).

## Complete Verification

Now click [Verify DNS Records](https://resend.com/domains) on your Domain in Resend. It may take a few hours to complete the verification process (often much faster).

## Troubleshooting

If your domain is not successfully verified, these are some common troubleshooting methods.

<AccordionGroup>
  <Accordion title="Resend shows my domain verification failed.">
    Review the records you added to Strato to rule out copy and paste errors.
  </Accordion>

  <Accordion title="It has been longer than 72 hours and my domain is still Pending.">
    [Review our guide on a domain not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying).
  </Accordion>
</AccordionGroup>


# Template emails with React Email
Source: https://resend.com/docs/knowledge-base/template-emails-with-react-email

Author email templates as React components and upload them to Resend with the CLI.

With [React Email](https://react.email), write email templates as React components, with full TypeScript and [Tailwind support](https://react.email/docs/components/tailwind), and a local preview server. Preview your emails in real time with hot reloading, and render to email-friendly HTML or plain text when you're ready to send.

This guide walks through setting up a React Email project, writing a template, and uploading it to [Resend Templates](/docs/dashboard/templates/introduction) with the [Resend CLI](/docs/cli) so the rest of your team can collaborate on it in the dashboard.

<Steps>
  <Step title="Set up a React Email project">
    Use `create-email` to scaffold a project with a starter template, a preview server, and the `@react-email/components` package.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npx create-email@latest
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn create email
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm create email
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun create email
      ```
    </CodeGroup>

    This creates a new `react-email-starter` folder with an `emails/` directory and a few example templates. Install dependencies:

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      cd react-email-starter
      npm install
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      cd react-email-starter
      yarn
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      cd react-email-starter
      pnpm install
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      cd react-email-starter
      bun install
      ```
    </CodeGroup>

    <Tip>
      Already have a project? See the [React Email
      docs](https://react.email/docs/getting-started/manual-setup) for the manual
      setup and then create an `emails/` directory in your preferred location.
    </Tip>
  </Step>

  <Step title="Write your template">
    Create `emails/welcome.tsx`. Each component can be imported from `react-email` ([view all components](https://react.email/docs/components/html)). Optionally add props to the component to be used as variables when sending.

    ```tsx emails/welcome.tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
    import {
      Body,
      Button,
      Container,
      Head,
      Heading,
      Html,
      Preview,
      Section,
      pixelBasedPreset,
      Tailwind,
      Text,
    } from 'react-email';
    import * as React from 'react';

    interface WelcomeEmailProps {
      firstName?: string;
      productName?: string;
    }

    export default function WelcomeEmail({
      firstName = 'there',
      productName = 'Acme',
    }: WelcomeEmailProps) {
      return (
        <Html>
          <Head />
          <Tailwind config={{ presets: [pixelBasedPreset] }}>
            <Preview>Welcome to {productName}</Preview>
            <Body className="bg-white font-sans">
              <Container className="mx-auto py-12">
                <Heading className="text-2xl font-semibold text-black">
                  Welcome, {firstName}
                </Heading>
                <Text className="text-base text-zinc-700">
                  Thanks for signing up for {productName}. Let's get you started.
                </Text>
                <Section className="mt-6">
                  <Button
                    className="rounded-md bg-black px-5 py-3 text-sm font-medium text-white"
                    href="https://example.com/get-started"
                  >
                    Get started
                  </Button>
                </Section>
              </Container>
            </Body>
          </Tailwind>
        </Html>
      );
    }
    ```
  </Step>

  <Step title="Add email script">
    ```json package.json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "scripts": {
        "email:dev": "email dev"
      }
    }
    ```

    The `email:dev` script will start the preview server. If your `email` directory is not in the root of your project, you can specify the path to it.

    ```json package.json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "scripts": {
        "email:dev": "email dev --dir src/emails"
      }
    }
    ```
  </Step>

  <Step title="Preview locally">
    Run the preview server to see your email render in real time as you edit. Hot reload picks up changes automatically.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm run email:dev
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn email:dev
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm email:dev
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun email:dev
      ```
    </CodeGroup>

    Open [localhost:3000](http://localhost:3000) and select `welcome.tsx` from the sidebar.

    <img alt="React Email Preview server" />

    The preview shows the rendered email and offers desktop/mobile toggles, the source HTML, and plain-text output. Changes you make to `welcome.tsx` show in real-time and dedicated email tools show in the toolbars.

    * `Linter`: lint your email content, links, and more.
    * `Compatibility`: check your email's HTML/CSS with [caniemail](https://caniemail.com).
    * `Spam`: see how spam checkers view your email.
  </Step>

  <Step title="Send your email template">
    You can pass your React Email template in the email call using the Resend Node SDK.

    ```ts sendEmail.tsx {10} theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { Resend } from 'resend';
    import { Email } from './email';

    const resend = new Resend('re_123456789');

    await resend.emails.send({
      from: 'you@example.com',
      to: 'delivered@resend.com',
      subject: 'hello world',
      react: <Email url="https://example.com" />,
    });
    ```
  </Step>

  <Step title="Upload your template to Resend">
    [Templates](/docs/dashboard/templates/introduction) are stored on Resend and can be referenced when you send transactional emails. With Templates, define the structure and layout of a message and optionally include custom variables which will be replaced with the actual values when sending the email.

    Set up the Resend integration using the React Email CLI:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}} theme={"theme":{"light":"github-light","dark":"vesper"}}
    npx react-email@latest resend setup
    ```

    This will prompt you to enter your Resend API Key. To get one, navigate to [API Keys](https://resend.com/api-keys) in your Resend dashboard, click **Create API key**, and ensure that the API Key is scoped to **Full Access**.

    Paste the API Key into the terminal and press enter.

    Run the React Email preview server and visit the **Resend** tab of the toolbar. Choose **Upload** or **Bulk Upload** to import your Template to Resend.

    <video />

    If you want to remove the Resend integration, run `npx react-email@latest resend reset`.
  </Step>
</Steps>

<CardGroup>
  <Card title="React Email components" icon="cube" href="https://react.email/docs/components/html">
    Browse every available component — Button, Container, Tailwind, and more.
  </Card>

  <Card title="Resend CLI reference" icon="terminal" href="/cli">
    See every CLI command and flag, including templates, automations, and
    webhooks.
  </Card>

  <Card title="Templates introduction" icon="file-lines" href="/dashboard/templates/introduction">
    Learn how Templates, variables, and version history work in Resend.
  </Card>

  <Card title="Embed the React Email editor" icon="pen-to-square" href="/knowledge-base/embed-react-email-editor">
    Add the open-source visual editor to your own app.
  </Card>
</CardGroup>


# Vercel
Source: https://resend.com/docs/knowledge-base/vercel

Verify your domain on Vercel with Resend.

<Note>
  This guide helps you verify your domain on Vercel with Resend. We also have
  [an official integration for
  Vercel](https://resend.com/blog/vercel-integration) that helps you set up your
  API keys on Vercel projects so you can start sending emails with Resend. [View
  the integration here](https://vercel.com/resend/~/integrations/resend).
</Note>

## Vercel Marketplace integration

If you installed Resend through the [Vercel Marketplace](https://vercel.com/marketplace/resend), Vercel manages the lifecycle of your Resend team, API keys, and domains. These resources cannot be deleted from the Resend dashboard, as they must uninstalled from Vercel to remove them.

## Add Domain to Resend

First, log in to your [Resend Account](https://resend.com/login) and [add a domain](https://resend.com/domains).

<img alt="Domain Details" />

<Tip>
  It is [best practice to use a
  subdomain](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain)
  (updates.example.com) instead of the root domain (example.com). Using a
  subdomain allows for proper reputation segmentation based on topics or purpose
  (e.g. marketing) and is especially important if receiving emails with Resend.
</Tip>

## Automatic Setup (Recommended)

The fastest way to verify your domain on Vercel is using the **Auto Configure** button on Resend. This uses Domain Connect to automatically configure your DNS records.

1. Go to your [Domains page](https://resend.com/domains) in Resend.
2. (Optional) If you want to receive emails, select `Manual setup` and toggle the "Receiving" switch on the domain details page. ([Learn more below](#receiving-emails))
3. Click **Auto Configure**.
4. Authorize Resend to access your Vercel DNS settings.
5. The DNS records will be added automatically.

<video aria-label="Vercel Domain Connect Setup" />

That's it. Your domain will be verified within a few minutes.

## Manual Setup

If you prefer to add DNS records manually, follow these steps.

### Log in to Vercel

Log in to your [Vercel account](https://vercel.com/login) and select the `Domains` tab.

<img alt="Domain Details" />

## Add MX SPF Record

Copy and paste the values in Resend to Vercel.

1. Type `send` for the `Name` of the record in Vercel.
2. Expand the `Type` dropdown and select `MX`.
3. Copy the record value from Resend into the `Value` field in Vercel.
4. Add `10` for the `Priority`.
5. Select `Add`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Vercel:

| Vercel   | Resend   | Example Value                           |
| -------- | -------- | --------------------------------------- |
| Type     | Type     | `MX Record`                             |
| Name     | Name     | `send`                                  |
| Value    | Content  | `feedback-smtp.us-east-1.amazonses.com` |
| TTL      | TTL      | `Use Vercel default (60)`               |
| Priority | Priority | `10`                                    |

<Info>
  Do not use the same priority for multiple records. If Priority `10` is already
  in use on another record, try a higher value `20` or `30`.
</Info>

## Add TXT SPF Record

In the same section, add another record in Vercel.

1. Type `send` for the `Name` of the record.
2. Expand the `Type` dropdown and select `TXT`.
3. Copy the `TXT` record value from Resend into the `Value` field in Vercel.
4. Use the default TTL of `60`.
5. Select `Add`.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `send.example.com`, paste only `send` (or `send.subdomain` if you're using a
  subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Vercel:

| Vercel | Resend  | Example Value                         |
| ------ | ------- | ------------------------------------- |
| Type   | Type    | `TXT Record`                          |
| Name   | Name    | `send`                                |
| Value  | Content | `"v=spf1 include:amazonses.com ~all"` |
| TTL    | TTL     | `Use Vercel default (60)`             |

## Add TXT DKIM Records

In the same section, add another record in Vercel.

1. Type `resend._domainkey` for the `Name` of the record.
2. Expand the `Type` dropdown and select `TXT`.
3. Copy the record value from Resend into the `Value` field in Vercel.

<Info>
  Omit your domain from the record values in Resend when you paste. Instead of
  `resend._domainkey.example.com`, paste only `resend._domainkey` (or
  `resend._domainkey.subdomain` if you're using a subdomain).
</Info>

<img alt="Domain Details" />

<img alt="Domain Details" />

Below is a mapping of the record fields from Resend to Vercel:

| Vercel | Resend  | Example Value                |
| ------ | ------- | ---------------------------- |
| Type   | Type    | `TXT Record`                 |
| Name   | Name    | `resend._domainkey`          |
| Value  | Content | `p=example_domain_key_value` |
| TTL    | TTL     | `Use Vercel default (60)`    |

## Receiving Emails

If you want to receive emails at your domain, toggle the "Receiving" switch on the domain details page.

<img alt="Enable Receiving Emails for a verified domain" />

<Warning>
  When you enable Inbound on a domain, Resend receives *all emails* sent to that
  specific domain depending on the priority of the MX record. For this reason,
  we strongly recommend verifying a subdomain (`subdomain.example.com`) instead
  of the root domain (`example.com`). Learn more about [avoiding conflicts with
  your existing MX
  records](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
</Warning>

Copy and paste the values in Resend to Vercel:

1. Type `inbound` (or whatever your subdomain is) for the `Name` of the record in Vercel.
2. Expand the `Type` dropdown and select `MX`.
3. Copy the MX Value from Resend into the `Value` field in Vercel.
4. Add `10` for the `Priority`.
5. Select `Add`.

Below is a mapping of the record fields from Resend to Vercel:

| Vercel   | Resend   | Example Value                          |
| -------- | -------- | -------------------------------------- |
| Type     | Type     | `MX Record`                            |
| Name     | Name     | `inbound`                              |
| Value    | Content  | `inbound-smtp.us-east-1.amazonaws.com` |
| TTL      | TTL      | `Use Vercel default (60)`              |
| Priority | Priority | `10`                                   |

After verifying your domain, create a webhook to process incoming emails. For help setting up a webhook, how to access email data and attachments, forward emails, and more, see [our guide on receiving emails with Resend](/docs/dashboard/receiving/introduction).

## Complete Verification

Now click [Verify DNS Records](https://resend.com/domains) on your Domain in Resend. It may take a few hours to complete the verification process (often much faster).

## Troubleshooting

If your domain is not successfully verified, these are some common troubleshooting methods.

<AccordionGroup>
  <Accordion title="Resend shows my domain verification failed.">
    Review the records you added to Vercel to rule out copy and paste errors.
  </Accordion>

  <Accordion title="It has been longer than 72 hours and my domain is still Pending.">
    [Review our guide on a domain not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying).
  </Accordion>
</AccordionGroup>


# Domain and/or IP Warm-up Guide
Source: https://resend.com/docs/knowledge-base/warming-up

Learn how to warm up a domain or IP to avoid deliverability issues.

Warming up a domain or IP refers to the practice of progressively increasing your sending volume to maximize your deliverability. The goal is to send at a consistent rate and avoid any spikes in email volume that might be concerning to inbox service providers.

Whenever you change your sending patterns, warm up your domain and/or IP. This applies when you use a new domain, a new IP, or a new vendor, or when your volume will increase.

A thought-out warm-up plan limits greylisting and delivery throttling, as well as helping establish a good domain and IP reputation.

As your volume increases, you'll need to monitor your bounce rate to ensure it remains below 4%, and your spam rate below 0.08%. An increase in these rates would be a sign that your warm-up plan needs to be slowed down and an investigation into the root causes of the increases started.

Following these rules and metrics will establish a good domain reputation.

<Info>
  Each sender has different constraints and needs, so these numbers are meant as
  a baseline. Our [Support team](https://resend.com/help) can work with you on
  devising a plan adapted to your needs.
</Info>

## Existing domain

If you're already sending from an existing domain with established reputation and volumes, you can use the following guidelines to start sending with Resend.

| **Day** | **Messages per day** | **Messages per hour** |
| ------- | -------------------- | --------------------- |
| **1**   | Up to 1,000 emails   | 100 Maximum           |
| **2**   | Up to 2,500 emails   | 300 Maximum           |
| **3**   | Up to 5,000 emails   | 600 Maximum           |
| **4**   | Up to 5,000 emails   | 800 Maximum           |
| **5**   | Up to 7,500 emails   | 1,000 Maximum         |
| **6**   | Up to 7,500 emails   | 1,500 Maximum         |
| **7**   | Up to 10,000 emails  | 2,000 Maximum         |

## New domain

Before you start sending emails with a brand new domain, it's especially important to have a warm-up plan so you can maximize your deliverability right from the start.

| **Day** | **Messages per day** | **Messages per hour** |
| ------- | -------------------- | --------------------- |
| **1**   | Up to 150 emails     |                       |
| **2**   | Up to 250 emails     |                       |
| **3**   | Up to 400 emails     |                       |
| **4**   | Up to 700 emails     | 50 Maximum            |
| **5**   | Up to 1,000 emails   | 75 Maximum            |
| **6**   | Up to 1,500 emails   | 100 Maximum           |
| **7**   | Up to 2,000 emails   | 150 Maximum           |

## Warm-up calculator

Use the calculator below to generate a personalized warm-up schedule based on your specific needs. Enter your target volume, timeline, and domain type to get a custom plan.

The guide is meant as a general plan, but always pay careful attention to your deliverability and adjust accordingly. If you have specific questions, [please reach out to us](https://resend.com/help).

<WarmupCalculator />

# Warming up your Dedicated IP with Resend

In order for a Dedicated IP to be beneficial or useful, you first need to establish a certain sending volume and patterns. Once you've established this volume and these patterns, our [Support team](https://resend.com/help) can set it up for you.

Resend provides an automatic warm-up process so that you can focus on sending.

[Learn more about requesting a Dedicated IP](https://resend.com/docs/knowledge-base/how-do-dedicated-ips-work#how-to-request-a-dedicated-ip).

# Third-party warm-up services

Email deliverability is important, and it can be tempting to use services promising quick fixes. However, using tools that artificially boost engagement can harm your long-term sender reputation. These services often rely on manipulating anti-spam filters, which can backfire as email providers like Gmail adjust their systems.

Instead, focus on sustainable practices, such as sending relevant content, maintaining a clean list, and using proper authentication. These methods build trust with email providers and improve your deliverability over time.


# What attachment types are not supported?
Source: https://resend.com/docs/knowledge-base/what-attachment-types-are-not-supported

Learn which file attachment extensions you can't send.

You can **send** any file attachment types except for those in the following list.

|          |       |       |         |           |
| -------- | ----- | ----- | ------- | --------- |
| .adp     | .app  | .asp  | .bas    | .bat      |
| .cer     | .chm  | .cmd  | .com    | .cpl      |
| .crt     | .csh  | .der  | .exe    | .fxp      |
| .gadget  | .hlp  | .hta  | .inf    | .ins      |
| .isp     | .its  | .js   | .jse    | .ksh      |
| .lib     | .lnk  | .mad  | .maf    | .mag      |
| .mam     | .maq  | .mar  | .mas    | .mat      |
| .mau     | .mav  | .maw  | .mda    | .mdb      |
| .mde     | .mdt  | .mdw  | .mdz    | .msc      |
| .msh     | .msh1 | .msh2 | .mshxml | .msh1xml  |
| .msh2xml | .msi  | .msp  | .mst    | .ops      |
| .pcd     | .pif  | .plg  | .prf    | .prg      |
| .reg     | .scf  | .scr  | .sct    | .shb      |
| .shs     | .sys  | .ps1  | .ps1xml | .ps2      |
| .ps2xml  | .psc1 | .psc2 | .tmp    | .url      |
| .vb      | .vbe  | .vbs  | .vps    | .vsmacros |
| .vss     | .vst  | .vsw  | .vxd    | .ws       |
| .wsc     | .wsf  | .wsh  | .xnk    |           |

<Info>
  You can *receive* any file attachment types, including those listed above.
  These restrictions only apply to *sending* attachments.
</Info>


# What counts as email consent?
Source: https://resend.com/docs/knowledge-base/what-counts-as-email-consent

Learn what valid email permission looks like and why it matters.

Getting consent to send email isn’t only a legal requirement. It’s also essential for keeping your deliverability strong and your Resend account in good standing.

This guide explains what valid email permission looks like, why it matters, and how to set it up properly.

## Why consent matters

Many senders assume that if someone provides an email address, that automatically means it’s okay to email them. But that’s not always true and can often cause large-scale deliverability problems, especially for marketing or bulk messages.

Mailbox providers like Gmail and Outlook closely monitor how recipients react to your emails, paying special attention to whether people mark your emails as spam. High complaint rates or low overall engagement signal that your messages weren’t wanted, which can hurt your reputation and lead to filtering, blocking, or delivery issues.

## What *doesn’t* count as permission

These common methods are not considered valid:

* Including a clause in your Terms of Service that says users “agree to receive emails”
* Using a **pre-checked** box on your signup form for marketing messages
* Assuming someone is opted in unless they unsubscribe

These approaches violate email best practices and don’t meet legal standards [like GDPR](https://gdpr-info.eu/art-7-gdpr/).

## What *does* count as permission

Valid consent means the recipient **clearly and knowingly agreed** to receive the specific kind of email you're sending.

[According to GDPR](https://gdpr-info.eu/recitals/no-32/) (and general best practices), consent must be:

* **Freely given** – without pressure, bundling, or tricks
* **Specific** – clearly describes the type of messages the user will receive
* **Informed** – the user knows who you are and how you’ll use their data
* **Unambiguous** – requires an active opt-in (like checking a box)

In other words, recipients must be able to consent to each message type from a particular sender.

## What happens if you send without consent

If you send to recipients who didn’t explicitly opt in, here’s what can happen:

1. Some of those people will **mark the message as spam**.
2. Mailbox providers may **block your mail or filter it to the spam folder**.
3. If your spam complaint or bounce rate remains high, [Resend may have to **pause or terminate your account**](https://resend.com/legal/acceptable-use) to protect our sending reputation.

And this applies *globally*, not only in the EU. Even if your emails are technically legal in your country, violating consent can lead to your mail being blocked or filtered to the spam folder.

## Best practice: Let people say “yes”

The easiest way to get consent is to **ask for it clearly and separately**. Add an unchecked checkbox to your signup form, like this:

>  Yes, I want to receive product updates and occasional marketing emails

**Follow these best practices:**

* Keep it **optional** and **unchecked** by default
* Make the wording clear and specific
* Place it outside of your Terms of Service
* Include a one-click unsubscribe link in every email

<img alt="Example of a consent checkbox and unsubscribe link" />

## Get more help

Following best practices helps everyone: your recipients, your deliverability, and the health of the email ecosystem. When you start with clear consent, your messages are the ones people are *glad* to receive.

If you’re new to permission-based sending, Resend [Support](https://resend.com/help) can help you get started.


# What email addresses to use for testing?
Source: https://resend.com/docs/knowledge-base/what-email-addresses-to-use-for-testing

Learn what email addresses are safe to use for testing with Resend

## Safe email addresses for testing

When testing email functionality, it's important to use designated test addresses to avoid unintended consequences like deliverability issues or spam complaints.

Resend provides a set of safe email addresses specifically designed for testing, ensuring that you can simulate different email events without affecting your domain's reputation.

### Avoid example or test domains

Many developers attempt to use domains like `@example.com` or `@test.com` for testing purposes. However, these domains are not designed for email traffic and often reject messages, leading to bounces.

A high bounce rate can negatively impact your sender reputation and affect future deliverability. To prevent this, Resend blocks such addresses and returns a `422 Unprocessable Entity` error if you attempt to send to them.

### List of addresses to use

To help you safely test email functionality, Resend provides the following test addresses, each designed to simulate a different delivery event:

| Address                 | Delivery event simulated |
| ----------------------- | ------------------------ |
| `delivered@resend.dev`  | Email being delivered    |
| `bounced@resend.dev`    | Email bouncing           |
| `complained@resend.dev` | Email marked as spam     |
| `suppressed@resend.dev` | Email being suppressed   |

Using these addresses in your tests allows you to validate email flows without risking real-world deliverability problems. For more help sending test emails, see our [testing documentation](/docs/dashboard/emails/send-test-emails).

### Labeling support

Most test email addresses support labeling, which enables you to send emails to the same test address in multiple ways. You can add a label after the `+` symbol to help track and differentiate between different test scenarios:

* `delivered+user1@resend.dev`
* `bounced+signup@resend.dev`
* `complained+newsletter@resend.dev`

This is particularly useful for testing different email flows, tracking webhook responses, and matching responses with the specific email address that triggered the event.

Whether you need to confirm that an email has been sent, track engagement events, or simulate a bounce scenario, these addresses provide a controlled and predictable way to test your email integration with Resend.

<Warning>
  The suppressed test email address does not support labeling yet
</Warning>


# What if an email says delivered but the recipient has not received it?
Source: https://resend.com/docs/knowledge-base/what-if-an-email-says-delivered-but-the-recipient-has-not-received-it

Learn the steps to take when an email is delivered, but the recipient does not receive it.

Some emails may be marked as `Delivered` but not reach the recipient's inbox due to various inbox sorting variables. This guide provides reasons for and advice on avoiding such issues.

## Why does this happen

When an email is sent, it is marked as `Delivered` once the recipient server accepts it with a `250 OK` response. However, the server can then direct the email to the inbox, queue it for later, route it to the spam folder, or even discard it. This is done by major inbox providers (e.g., Gmail, Yahoo, Outlook), as well as by IT departments and individual users who set up firewalls or filtering rules.

As a result, even though most legitimate emails land in the intended inboxes, your message might end up in the spam/junk folder or, in rare cases, be deleted.

**Inbox Providers do not share any information on how the messages are later filtered.** Resend is only notified about the initial acceptance and marks the email as `Delivered`. Any subsequent events (e.g., open/click events, unsubscribes) require recipient engagement.

## How to avoid this

### If you are in contact with the user

The easiest way to solve this is by cooperating with the end user. If you have direct communication with the recipient, you can ask them to **check these places for your email**:

* Corporate spam filters or firewalls
* Personal inbox filtering
* Promotional, spam, or deleted folders
* Group inboxes or queues

If they find it, ask them to mark the email as `Not Spam` or add your domain to an allowlist.

### If you are not in contact with the user

Debugging without direct contact with the user is challenging. However, there are some optimizations that can **improve your chances of delivering to their inbox next time**:

* [Configure DMARC](/docs/dashboard/domains/dmarc) to build trust with the inbox provider
* Warm up new domains slowly before sending large volumes
* Change all links in your email to use your own domain (matching your sender domain)
* Turn off open and click tracking
* Reduce the number of images in your email
* Improve wording to be succinct, clear, and avoid spammy words

Check out our [extensive but practical deliverability guide](/docs/knowledge-base/how-do-i-avoid-gmails-spam-folder) that covers these topics in more detail.


# What if my domain is not verifying?
Source: https://resend.com/docs/knowledge-base/what-if-my-domain-is-not-verifying

Learn what steps to take when your domain doesn't seem to be verifying.

Verifying a domain involves a few steps:

1. Add your domain to Resend
2. Copy the required DNS records from Resend
3. Add these records to your DNS provider
4. Wait for verification to complete

When this process is completed correctly, your domain will often verify within 15 minutes of adding the DNS records.

<Tip>
  If you are having any conflict issues with the `MX` records, [check out this
  guide](/docs/knowledge-base/how-do-i-avoid-conflicting-with-my-mx-records).
</Tip>

## Common verification issues

When your domain doesn't verify as expected, it's typically due to DNS configuration issues. This guide will help you troubleshoot and resolve common verification problems.

<Tip>
  Resend provides real-time DNS validation when viewing your domain details.
  When viewing your domain, you'll see specific error messages and visual
  indicators highlighting any issues with your DNS records in case you've added
  them incorrectly.
</Tip>

### Incorrect DNS records

Usually when a domain doesn't verify, it's because the DNS records were not added correctly. Here's how to check:

1. Confirm that you've added all required records (DKIM, SPF, and MX)
2. Verify that the records are added at the correct location (the `send` subdomain, not the root domain)
3. Check that record values match exactly what Resend generated for you
4. Look for red wavy underlines on the domain details page (these indicate specific DNS record errors)

<img alt="Check for errors in the domain details page" />

### DNS provider auto-appending domain names

Some DNS providers automatically append your domain name to record MX values, causing verification failures.

**Problem:**

Your MX record appears as:

`feedback-smtp.eu-west-1.amazonses.com.example.com`

Instead of:

`feedback-smtp.eu-west-1.amazonses.com`

**Solution:**

In your DNS provider, add a trailing period (dot) at the end of the record value:

`feedback-smtp.eu-west-1.amazonses.com.`

The trailing period tells your DNS provider that this is a fully qualified domain name that must not be modified.

<Tip>
  Note: The region your domain is added to is in this MX record. It may be
  `us-east-1`, `eu-west-1`, `ap-northeast-1`, or `sa-east-1` depending on the
  region.
</Tip>

### Nameserver conflicts

If your domain's DNS is managed in multiple places (e.g., Vercel, Cloudflare, your domain registrar), you might be adding records in the wrong location.

**How to check:** Run a nameserver lookup for your domain using a tool like [dns.email](https://dns.email) to see which provider actually controls your DNS. Add the Resend records at that provider, not elsewhere.

### Region mismatch errors

If your MX records point to a different AWS region than where your domain is configured, you'll see a "region-mismatch" error. This happens when:

* Your domain is configured in one region (e.g., `us-east-1`)
* But your MX record points to a different region (e.g., `eu-west-1`)

**Solution:** Update your MX record to match the region shown in your Resend domain configuration. The correct MX record value is displayed in the DNS records table on your domain details page.

### Multiple regions detected

If you have multiple MX records pointing to different AWS regions, you'll see a "multiple-regions" error. All MX records for a domain must point to the same region.

**Solution:** Remove any MX records pointing to incorrect regions, keeping only the one that matches your domain's configured region.

### DKIM record value mismatches

The DKIM record must match exactly what Resend generated. Common mistakes include:

1. Adding extra quotes or spaces
2. Truncating long values
3. Adding SPF information to the DKIM record
4. Not copying the entire value

Always copy and paste the exact value from Resend's domain configuration page. If there's a mismatch, you'll see a red wavy underline on the incorrect value.

### DNS Propagation

After adding or correcting your DNS records:

1. DNS changes can take up to 72 hours to propagate globally (though often much faster)
2. Use the "Restart verification" button in the Resend dashboard to trigger a fresh verification check
3. If verification still fails after 24 hours, use [dns.email](https://dns.email) to check if your records are visible publicly

## Get more help

If you've followed all the steps above and your domain still isn't verifying, contact [Resend support](https://resend.com/help) with:

1. Your domain name
2. Screenshots of your DNS configuration

Our team will help identify any remaining issues preventing successful verification.

<AccordionGroup>
  <Accordion title="Check your records in the browser">
    Tools like [dns.email](https://dns.email) allow you to check your DNS records in the browser.

    Go to this URL and replace `example.com` with the domain you added in Resend.

    <img alt="Check domain records with dns.email" />

    You are looking to see the same values that you see in Resend.
  </Accordion>

  <Accordion title="Check your records in the terminal">
    Checking your DNS records in the terminal is just as easy. You can use the `nslookup` command and a record type flag to get the same information.

    Replace `example.com` with whatever you added as the domain in Resend:

    Check your DKIM `TXT` record:

    ```
    nslookup -type=TXT resend._domainkey.example.com
    ```

    Check your SPF `TXT` record:

    ```
    nslookup -type=TXT send.example.com
    ```

    Check your SPF `MX` record:

    ```
    nslookup -type=MX send.example.com
    ```

    <img alt="Check domain records with nslookup" />

    You are looking to see the same values that you see in Resend.
  </Accordion>
</AccordionGroup>


# What is Resend Pricing
Source: https://resend.com/docs/knowledge-base/what-is-resend-pricing

Learn more about Resend's pricing plans.

Resend offers Free, Pro, Scale, and Enterprise plans for transactional email, plus contact-based plans for marketing email. For the most up-to-date pricing, visit [resend.com/pricing](https://resend.com/pricing).

## Transactional Email

Transactional Email plans are based on the number of emails sent and received each month. Multiple `To`, `CC`, or `BCC` recipients count as separate emails.

| Plan       | Price      | Emails/mo | Overage per 1,000 emails |
| ---------- | ---------- | --------- | ------------------------ |
| Free       | \$0/mo     | 3,000     | Not available            |
| Pro        | \$20/mo    | 50,000    | \$0.90                   |
| Pro        | \$35/mo    | 100,000   | \$0.90                   |
| Scale      | \$90/mo    | 100,000   | \$0.90                   |
| Scale      | \$160/mo   | 200,000   | \$0.80                   |
| Scale      | \$350/mo   | 500,000   | \$0.70                   |
| Scale      | \$650/mo   | 1,000,000 | \$0.65                   |
| Scale      | \$825/mo   | 1,500,000 | \$0.52                   |
| Scale      | \$1,150/mo | 2,500,000 | \$0.46                   |
| Enterprise | Custom     | Custom    | Custom                   |

The Free plan is limited to 100 emails per day. Paid plans have no daily sending limit, and overage rates apply only to emails sent beyond the included monthly volume.

For teams sending 3 million or more emails per month, Resend offers custom Enterprise plans that include:

* Volume-based pricing
* Priority support
* SLA guarantees
* Flexible data retention
* SSO
* Dedicated IP options

[Contact sales](https://resend.com/contact) to learn more.

## Marketing Email

Marketing Email plans are based on the number of contacts, not the number of emails sent. Broadcasts can only be sent to existing contacts.

| Plan          | Price    | Contacts/mo |
| ------------- | -------- | ----------- |
| Free          | \$0/mo   | 1,000       |
| Pro Marketing | \$40/mo  | 5,000       |
| Pro Marketing | \$80/mo  | 10,000      |
| Pro Marketing | \$120/mo | 15,000      |
| Pro Marketing | \$180/mo | 25,000      |
| Pro Marketing | \$250/mo | 50,000      |
| Pro Marketing | \$450/mo | 100,000     |
| Pro Marketing | \$650/mo | 150,000     |
| Enterprise    | Custom   | Custom      |

## Automations

All plans include 10,000 Automation Runs per month. Paid plans can continue beyond the included usage with pay-as-you-go billing at \$0.0015 per run. The Free plan includes 10,000 Automation Runs per month with no overage.

## Add-ons

Dedicated IPs are available for \$30/month on the Scale plan for customers sending more than 3,000 emails per day. Dedicated IPs include automatic warmup, monitoring, and autoscaling.

## Annual plans

Annual subscriptions are available for Enterprise plans. [Book time with our sales team to learn more.](https://resend.com/enterprise)


# Which sending feature do you need?
Source: https://resend.com/docs/knowledge-base/what-sending-feature-to-use

How to pick between our different sending features depending on your number of recipients and the nature of the message.

Resend allows you to send both **Transactional** and **Marketing** emails.

## The difference between Transactional and Marketing emails

### Transactional emails

A **Transactional email** is a message triggered by a user action or required for legal compliance. These emails are essential communications that users **cannot unsubscribe** from. Common examples include:

* Order confirmations
* Password reset emails
* Account notifications

Typically, transactional emails are **1-to-1** messages sent in response to a specific event.

### Marketing emails

A **Marketing email** is any email that is not transactional. These can be **promotional**, **informative**, or **general communication** messages.

Marketing emails are regulated by laws like **CAN-SPAM** (US) and **CASL** (Canada), and **recipients must have the option to unsubscribe**.

Examples of marketing emails:

* Promotional offers and discounts
* Newsletters
* Product updates

Marketing emails can be **1-to-1** (e.g., abandoned cart reminders) or **1-to-many** (e.g., newsletters).

## Transactional vs Marketing: Which to Choose

While not exhaustive, here's a table listing different examples of emails and the most appropriate type for each example.

| Type of Message    | Type of Recipient | Transactional | Marketing |
| ------------------ | ----------------- | ------------- | --------- |
| Order confirmation | Single            | ✓             | ⨯         |
| Password reset     | Single            | ✓             | ⨯         |
| Abandoned cart     | Single            | ⨯             | ✓         |
| Newsletter         | Multiple          | ⨯             | ✓         |
| Promotional offer  | Multiple          | ⨯             | ✓         |

## How to send an email with Resend

### How to send a Transactional email

You can send a Transactional email using:

* Our [Send Email API](/docs/api-reference/emails/send-email)
* Our [Batch Send API](/docs/api-reference/emails/send-batch-emails) (send up to 100 transactional emails in one API call)

### How to send a Marketing email

You can send Marketing emails using:

* [Resend no-code Editor](/docs/dashboard/broadcasts/introduction) – a collaborative interface for designing emails
* [Broadcast API](/docs/api-reference/broadcasts/create-broadcast) – for programmatic sending


# What's the difference between Opportunistic TLS vs Enforced TLS?
Source: https://resend.com/docs/knowledge-base/whats-the-difference-between-opportunistic-tls-vs-enforced-tls

Understand the different TLS configurations available.

Resend supports TLS 1.2, TLS 1.1 and TLS 1.0 for TLS connections.

There are two types of TLS configurations available:

* Opportunistic TLS
* Enforced TLS

## What is Opportunistic TLS?

Opportunistic TLS means that Resend always attempts to make a secure connection to the receiving mail server.

If the receiving server does not support TLS, the fallback is sending the message unencrypted.

## What is Enforced TLS?

Enforced TLS means that the email communication must use TLS no matter what.

If the receiving server does not support TLS, the email will not be sent.

## Is Enforced TLS better than Opportunistic TLS?

One strategy is not necessarily better than the other.

The decision is less about one option being safe and the other being unsafe, and more about one option being safe and the other being safer.

When you have Enforced TLS enabled, you might see an increase in bounce rates because some outdated mail servers do not support TLS.

So it's important to understand the different use cases for each configuration. If you're sending sensitive information like authentication emails, you might want to use Enforced TLS. If you're sending marketing emails, you might want to use Opportunistic TLS.

In simple terms, with Opportunistic TLS, delivery is more important than security. On the other hand, with Enforced TLS, security is more important than delivery.


# Why Are My Emails Going to Spam?
Source: https://resend.com/docs/knowledge-base/why-are-my-emails-going-to-spam

Troubleshoot and resolve emails landing in spam or being quarantined.

If your emails are landing in spam or being quarantined, work through this checklist to identify and fix the issue.

## Check your authentication records

Make sure your domain has all three authentication records properly configured:

* **SPF**: Automatically set up when you verify your domain with Resend. Verify it is still present with [dns.email](https://dns.email).
* **DKIM**: Also set up during domain verification. Confirm with [dns.email](https://dns.email).
* **DMARC**: Not automatically set up, but strongly recommended. See [DMARC](/docs/dashboard/domains/dmarc) for setup instructions.

<Warning>
  If any of these records are missing or misconfigured, fix them first.
  Authentication issues are the most common cause of spam placement.
</Warning>

## Use Deliverability Insights

If you sent the email through Resend, open the email in your dashboard and review
[Deliverability Insights](/docs/dashboard/emails/deliverability-insights).

Deliverability Insights runs a set of best-practice checks against your email and
flags issues that may affect inbox placement. Pay close attention to warnings
about:

* Links that do not match your sending domain
* Missing or invalid DMARC
* Missing plain text versions
* Using `no-reply` sender addresses
* Large email body size
* Open or click tracking for sensitive emails

## Check the spam banner

When an email lands in spam, providers like Gmail display a banner explaining why. Here are common messages and what they mean:

| Banner message                                                       | What it means                             | Fix                                                                                     |
| -------------------------------------------------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------- |
| "It's similar to messages that were identified as spam in the past." | Content is triggering spam filters        | Simplify your email content and remove excessive links, images, or marketing language   |
| "This message seems dangerous"                                       | A URL or content was flagged as malicious | Review the links and content in your email for anything that might be flagged as unsafe |

## Check your domain reputation

* Use [Google Postmaster Tools](https://postmaster.google.com) to see your domain and IP reputation with Gmail.
* If your domain is new, you may need to warm it up by starting with low volume and increasing over time. See our [Domain and/or IP Warm-up Guide](/docs/knowledge-base/warming-up).

## Corporate email filters

Some recipients use enterprise email security services like Mimecast, Proofpoint, or Barracuda. These services apply their own filtering on top of standard spam checks.

If your emails are being blocked by a specific corporate recipient:

* Ask the recipient to check their quarantine or junk folder and allowlist your sending domain.
* These filters often block based on domain age, content patterns, or URL reputation. The fixes in the steps above still apply.

## Review your sending practices

* Send from a dedicated address per email type, such as `notifications@` for transactional emails and `updates@` for marketing emails. For more guidance on domain setup, review [Is it better to send emails from a subdomain or the root domain?](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain).
* Do not send to purchased lists or addresses that have not opted in. If you are unsure what qualifies as permission, review [What counts as email consent?](/docs/knowledge-base/what-counts-as-email-consent).
* Include a visible unsubscribe link in marketing emails.
* Keep HTML simple. Heavy formatting and image-only emails are more likely to trigger filters.

<Tip>
  For provider-specific guidance, see [How do I avoid Gmail's spam
  folder?](/docs/knowledge-base/how-do-i-avoid-gmails-spam-folder) and [How do I
  avoid Outlook's spam
  folder?](/docs/knowledge-base/how-do-i-avoid-outlooks-spam-folder).
</Tip>

## Get more help

If you have worked through the steps above and still need help, our support team
is happy to take a closer look. Contact us through our
[support form](https://resend.com/help) and share any relevant details about the
issue, such as the recipient provider, sending domain, and what you have already
tried.


# Why are my emails landing on the Suppression List?
Source: https://resend.com/docs/knowledge-base/why-are-my-emails-landing-on-the-suppression-list

Learn why your emails land on the Suppression List and how to remove them.

When sending to an email address results in a hard bounce or spam complaint, Resend places this address on the Suppression List. Future emails to addresses on the list will be marked as `suppressed` and won't be delivered until the address is removed.

<Info>
  We place emails on the Suppression List to protect domain reputation, both
  yours and ours. Sending an email to a known hard bounce recipient can damage
  domain reputation and affect email deliverability.
</Info>

## Reasons emails are placed on the Suppression List

Here are some possible reasons an email address is placed on the Suppression List:

* The recipient's email address **contains a typo**.
* The recipient's email address **doesn't exist**.
* The recipient's email server has **permanently blocked delivery**.
* The recipient has marked a previous delivery as spam.

## What happens when you send to an address on the Suppression List

Whenever you send an email with Resend, the recipient is checked against the suppression list. If they're on it, the delivery is [suppressed](/docs/dashboard/emails/email-suppressions) to prevent damaging your sender reputation and our infrastructure.

Suppressed emails will appear with a `suppressed` status in your [Emails](https://resend.com/emails) dashboard:

<img alt="Email Suppression in Dashboard" />

## View suppression details

You can view the reason an email was suppressed on the [Emails](https://resend.com/emails) page:

1. Open the [Emails](https://resend.com/emails) page and search for the recipient's email address in question.
2. Click on the email to view its details.
3. The suppression details will show suggested fixes to help you resolve the issue.

<video />

## Removing an email address from the Suppression List

You may be able to send a message to the same recipient in the future if the issue that caused the original bounce or complaint is resolved and the email address is removed from the Suppression List.

<Warning>
  Remember, if you do not address the issue that caused the email to bounce, the
  email address will return to the Suppression List the next time you attempt to
  send to it.
</Warning>

To remove your recipient from the Suppression List, click on the suppressed email in the [emails dashboard](https://resend.com/emails), and click **Remove from suppression list**.


# Why are my open rates not accurate?
Source: https://resend.com/docs/knowledge-base/why-are-my-open-rates-not-accurate

Learn why your open rate statistics are not accurate and what you can do about it.

## How open rates are tracked

A 1x1 pixel transparent GIF image is inserted in each email and includes a unique reference. When the image is downloaded, an open event is triggered.

## Why open rates are not accurate

Open tracking is generally not accurate because each inbox handles incoming email differently.

**Clipped messages in Gmail** happen when you send a message over 102KB. A message over this size won’t be counted as an open unless the recipient views the entire message. Resend’s Deliverability Insights on the email will note if a message exceeds this threshold.

**Some inboxes do not download images by default** or block/cache assets with a corporate firewall. This approach can prevent the open event from being tracked.

**Other inboxes open the email prior to delivering** to scan for malware or to [protect user privacy](https://www.apple.com/newsroom/2021/06/apple-advances-its-privacy-leadership-with-ios-15-ipados-15-macos-monterey-and-watchos-8/). This approach can trigger an open event without the recipient reading your email.

**Emails sent with only a plain text version** will not include open tracking at all. Since open tracking relies on a 1x1 pixel image, plain text emails cannot trigger open events. Only emails with an HTML version can be tracked for opens.

Because of this, open tracking is **not a statistically accurate way** of detecting if your users are engaging with your content.

## How open tracking impacts inbox placement

Though open tracking does not impact whether your email is delivered, it most likely will impact your inbox placement. Trackers are generally **used by marketers and even spammers**. Because of this, inbox providers will often use open tracking as a signal that your email is promotional, or even spam, and categorize accordingly.

**We recommend disabling open rates for transactional email**, to maximize inbox placement.

## Alternatives to open tracking

Instead of relying on open rates, there are a few other ways to still understand your sending.

1. **Track Clicks:** Monitoring the link clicks is an even more granular way to know how a recipient engaged with your email. By knowing if they clicked, you also know that they read parts of your email and took action.
2. **Track Outside the Inbox:** Often emails are sent as a means to an end. Maybe it's to increase page visits of an announcement or convert free users to paid. Tracking your sending by metrics outside of the inbox can be a great way to understand the true impact of your sending.


# Why and when to use Topics?
Source: https://resend.com/docs/knowledge-base/why-use-topics

Learn when to use Topics to improve deliverability and give recipients control over their email preferences.

When you send an email, you make one primary decision: **who is this for?** Those recipients (a person, a list, or a Segment) are the core of sending. By default, everyone in that recipient group receives the message, but not everyone in that group may want that message.

Topics give recipients a way to say "don't send me this kind of email" without unsubscribing from everything. Think of Topics as **contracts with your recipients**: a promise that if they opt out of a content type, you'll respect it.

Topics don't define who receives a message. They **define who asked not to receive that message**. This guide explains why Topics matter for deliverability, when to use them, and how they differ from Segments.

## Why Topics improve deliverability

Deliverability focuses on landing in the inbox instead of the spam folder. And *recipient engagement* is a key factor in deliverability. Mailbox providers like Gmail and Outlook track whether people open, click, or mark your emails as spam.

When you send all your marketing emails to everyone on your list, a subsection of your recipients will not engage with your content. This leads to:

* **Lower open rates**: recipients ignore emails that don't interest them
* **Higher spam complaints**: frustrated recipients mark emails as spam instead of unsubscribing
* **Decreased sender reputation**: mailbox providers see low engagement and filter your emails to spam

Topics give your recipients agency, and they give you signals. When a recipient says "stop sending promotional emails," the system honors that request while continuing to send them content they do want. Topics let them decline one without losing the other.

## Without topics: global unsubscribe

Without Topics, your unsubscribe page offers only one option: **unsubscribe from everything**. This is a blunt instrument. Many recipients who would have gladly kept receiving some of your content will unsubscribe entirely because they received one too many emails about something they didn't want.

With Topics, recipients can say "no" to specific content types while staying connected to what they value. You retain more engaged subscribers.

## When to use Topics

Topics are most valuable when you send **multiple types of marketing content** to the same audience. Consider using Topics if you send:

| Topic Example        | Description                                   |
| -------------------- | --------------------------------------------- |
| **Newsletter**       | Regular updates, articles, or curated content |
| **Product Updates**  | New features, releases, and announcements     |
| **Promotions**       | Discounts, sales, and special offers          |
| **Events**           | Webinars, conferences, and meetups            |
| **Tips & Tutorials** | Educational content and how-to guides         |

## When you might not need Topics

If you only send one type of marketing email (for example, a monthly newsletter and nothing else), Topics add complexity without much benefit. In that case, a simple subscribe/unsubscribe model is sufficient.

## Topics vs Segments: key differences

Topics and Segments serve fundamentally different purposes. Understanding this distinction is key to using them effectively.

| Aspect              | Topics                             | Segments                                   |
| ------------------- | ---------------------------------- | ------------------------------------------ |
| **Who controls it** | Your recipients                    | You (the sender)                           |
| **Visibility**      | Shown on the unsubscribe page      | Internal only (recipients never see them)  |
| **Purpose**         | Let users manage their preferences | Organize contacts for targeted sending     |
| **Example**         | "Newsletter", "Product Updates"    | "Enterprise customers", "Free trial users" |

## How Segments and Topics work together

Think of Segments as **who you're sending to** and Topics as **what you're sending**.

When you send a Broadcast:

1. You choose a **Segment** as your recipients (your sender intent).
2. You label the content with a **Topic** (so the system can respect recipient preferences).
3. Everyone in the Segment receives the message, **except** those who opted out of that Topic.

For example, you might send a product announcement to your "Enterprise Customers" Segment, labeled with the "Product Updates" Topic. Recipients who previously said "don't send me product updates" are automatically excluded.

**Segments are for targeting. Topics are for protecting preferences.** They work together without competing.

## Customizing your unsubscribe page

When a recipient clicks the unsubscribe link in a Broadcast, they see a preference page showing your public Topics. This page is fully customizable to match your brand.

You can customize:

* **Title and description**
* **Logo**
* **Background color, text color, and accent color**

A branded unsubscribe page looks more professional and trustworthy, which can encourage recipients to adjust their preferences rather than unsubscribe entirely.

Learn more about [customizing your unsubscribe page](/docs/dashboard/settings/unsubscribe-page).

<Note>
  Pro plan users or higher can remove the "Powered by Resend" footer from the
  unsubscribe page.
</Note>

## Opt-in vs Opt-out Topics

When creating a Topic, choose between two default subscription behaviors:

* **Opt-in (default)**: All contacts receive emails for this Topic unless they explicitly unsubscribe (applies retroactively to all contacts)
* **Opt-out**: Contacts do NOT receive emails for this Topic unless they explicitly subscribe

Use **Opt-in** for content that's broadly relevant to your audience (like product updates). Use **Opt-out** for niche content that only some users will want (like a beta program or developer-focused updates).

<Warning>
  You cannot change the default subscription type after creating a Topic.
</Warning>

## Public vs Private Topics

When creating a Topic, you can set its visibility:

* **Public**: All contacts see this Topic on the unsubscribe page
* **Private**: Only contacts who are opted in to the Topic can see it

Private Topics are useful for exclusive content, like a beta program or VIP announcements, where you don't want to advertise the Topic to everyone.

## Best practices for Topics

### Keep it simple

Don't create too many Topics. Recipients get overwhelmed when faced with a long list of checkboxes. Aim for 3–5 distinct content types that clearly communicate what the recipient will receive.

### Use clear, descriptive names

Topic names must be immediately understandable. "Newsletter" and "Product Updates" are clear. "Category A" and "Misc" are not.

### Add descriptions

The optional description field helps recipients understand the topic. Use it to set expectations about frequency and content.

### Always label your Broadcasts with a Topic

Whenever you send a Broadcast, label it with a Topic. This ensures:

1. Recipients who declined that content type won't receive the email.
2. If someone unsubscribes, they can opt out of that Topic only, rather than unsubscribe from all your emails.

<Info>
  If you send a Broadcast without a Topic and someone unsubscribes, they'll be
  unsubscribed from all your emails. Labeling your content protects both you and
  your recipients.
</Info>

## Getting started with Topics

1. [Create your Topics](/docs/dashboard/topics/introduction) in the Resend dashboard
2. [Customize your unsubscribe page](/docs/dashboard/settings/unsubscribe-page) with your branding
3. Use [Segments](/docs/dashboard/segments/introduction) to define who you're sending to
4. When sending [Broadcasts](/docs/dashboard/broadcasts/introduction), always label them with a Topic

By using Segments for targeting and Topics for respecting preferences, you send to the right people while honoring those who said no, improving engagement and protecting your sender reputation.


# Send emails with Leap and Resend
Source: https://resend.com/docs/leap-new-integration

Learn how to add the Resend integration to your Leap.new project.

[Leap](https://leap.new) is a platform for building full-stack web and mobile apps via chat.

## Guide

<Steps>
  <Step title="Ask Leap to add Resend">
    You can add Resend in a Leap project by asking the chat to add email sending with Resend.

    **Example prompt**

    ```
    When someone fills out the contact form, send an email using Resend.
    ```
  </Step>

  <Step title="Add your Resend API key">
    To use Resend with Leap, you'll need to add a Resend API key, which you can create in the [Resend Dashboard](https://resend.com/api-keys). Do not share your API key with others or expose it in the browser or other client-side code.

    Leap will prompt you to set a secret value on the Infrastructure page. Paste your key value and click **Update secret**.

    <img alt="adding the Resend integration to a leap.new chat" />

    <Info>
      Learn more about the Resend integration in the [Leap
      documentation](https://docs.leap.new/integrations/resend).
    </Info>
  </Step>

  <Step title="Add a custom domain to your Resend account">
    By default, you can only send emails to your own email address.

    To send emails to other email addresses:

    1. Add a [custom domain to your Resend account](/docs/add-a-domain).
    2. Add the custom domain to the `from` field in the `resend` function in Leap (or ask the chat to update these fields).

    Get more help adding a custom domain in [Resend's documentation](/docs/dashboard/domains/introduction).
  </Step>
</Steps>


# Send emails with Lovable and Resend
Source: https://resend.com/docs/lovable-integration

Learn how to add the Resend integration to your Lovable project.

[Lovable](https://lovable.dev) is a platform for building web sites, tools, apps, and projects via chat. You can add Resend in a Lovable project by asking the chat to add email sending with Resend.

If you prefer to watch a video, check out our video walkthrough below.

<YouTube />

## Guide

<Steps>
  <Step title="Add your Resend API key">
    To use Resend with Lovable, you'll need to add a Resend API key, which you can create in the [Resend Dashboard](https://resend.com/api-keys). Do not share your API key with others or expose it in the browser or other client-side code.

    Lovable may integrate Resend in a few different ways:

    * Use the Supabase integration to store the API key **(highly recommended)**
    * Ask users to provide their own API key
    * Add the API key directly in the code

    You may need to prompt Lovable to store the API key for Resend using Supabase. Clicking **Add API key** will open a modal where you can add the API key.

    <img alt="adding the Resend integration to a Lovable chat" />

    <Info>
      At the time of writing, Lovable does not securely handle API keys
      independently. Instead, it uses the [Supabase integration to store
      secrets](https://docs.lovable.dev/integrations/supabase#storing-secrets-api-keys-%26-config).
    </Info>
  </Step>

  <Step title="Add a custom domain to your Resend account">
    By default, you can only send emails to your own email address.

    To send emails to other email addresses:

    1. Add a [custom domain to your Resend account](/docs/add-a-domain).
    2. Add the custom domain to the `from` field in the `resend` function in Lovable (or ask the chat to update these fields).

    <Info>
      By default, Lovable deploys using the test domain `resend.dev`. Once your custom domain is verified, the function does not automatically redeploy or update the sender address.

      You’ll need to ask Lovable to manually update the `From` email to use your verified domain and then redeploy the function so the changes take effect.
    </Info>

    Get more help adding a custom domain in [Resend's documentation](/docs/dashboard/domains/introduction).
  </Step>
</Steps>


# MCP Server
Source: https://resend.com/docs/mcp-server

Connect your AI agent to Resend using the hosted MCP server.

MCP is an open protocol that standardizes how applications provide context to LLMs. Among other benefits, it provides LLMs tools to act on your behalf. Resend offers both a [remote MCP server](#remote-mcp-server) and a [local MCP server](#local-mcp-server).

<YouTube />

## Remote MCP Server

Resend hosts the MCP server at:

```
https://mcp.resend.com/mcp
```

Connect any MCP client that supports remote servers (Streamable HTTP). There's nothing to install and no local process to run, which makes it the best option for web-based clients like Claude and hosted agent platforms.

When you connect, your client opens a browser window to log in to Resend and approve access using OAuth.

<Tabs>
  <Tab title="Claude Code">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    claude plugin install resend@claude-plugins-official
    ```

    Then run `/mcp` in Claude Code and select **resend** to complete the OAuth login. The plugin bundles the MCP server and every [Resend skill](/docs/resend-skill).
  </Tab>

  <Tab title="Claude">
    Connect Resend in one click from the [connector directory](https://claude.ai/directory/connectors/resend). The connector bundles the MCP server and every Resend skill.

    To install only the MCP server, add it manually in Claude (web or desktop) from **Settings** > **Connectors** > **Add custom connector**:

    ```
    https://mcp.resend.com/mcp
    ```
  </Tab>

  <Tab title="Cursor">
    Open the command palette and choose "Cursor Settings" > "MCP" > "Add new global MCP server".

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "mcpServers": {
        "resend": {
          "url": "https://mcp.resend.com/mcp"
        }
      }
    }
    ```
  </Tab>

  <Tab title="Codex">
    Install the [Resend plugin](https://chatgpt.com/plugins/plugin_asdk_app_6a3c407853888191beddc2151c2b6f8b?open_in_codex) in one click. It bundles the MCP server and every Resend skill.

    To connect the MCP server on its own, use the Codex CLI:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    codex mcp add resend --url https://mcp.resend.com/mcp
    ```
  </Tab>

  <Tab title="Antigravity">
    Add this to your `~/.gemini/config/mcp_config.json` file:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "mcpServers": {
        "resend": {
          "serverUrl": "https://mcp.resend.com/mcp"
        }
      }
    }
    ```
  </Tab>

  <Tab title="Copilot">
    To use GitHub Copilot in VS Code, add the following to your `settings.json`:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "mcp": {
        "servers": {
          "resend": {
            "type": "http",
            "url": "https://mcp.resend.com/mcp"
          }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Windsurf">
    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "mcpServers": {
        "resend": {
          "serverUrl": "https://mcp.resend.com/mcp"
        }
      }
    }
    ```
  </Tab>

  <Tab title="Warp">
    In Warp's Settings, navigate to **Agents** > **MCP servers**, and click **+ Add** to add a new server.

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "resend": {
        "serverUrl": "https://mcp.resend.com/mcp"
      }
    }
    ```
  </Tab>
</Tabs>

***

*If your client runs somewhere a browser login isn't possible* (a server, CI, or a headless agent), pass a [Resend API key](https://resend.com/api-keys) as a Bearer token instead of using OAuth.

<Tabs>
  <Tab title="Claude Code">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    claude mcp add --transport http resend https://mcp.resend.com/mcp --header "Authorization: Bearer re_xxxxxxxxx"
    ```
  </Tab>

  <Tab title="JSON config">
    For clients configured with JSON (Cursor, Windsurf, and others), add an `Authorization` header:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "mcpServers": {
        "resend": {
          "url": "https://mcp.resend.com/mcp",
          "headers": {
            "Authorization": "Bearer re_xxxxxxxxx"
          }
        }
      }
    }
    ```
  </Tab>
</Tabs>

## Local MCP Server

The hosted server runs the same open-source code that's available on NPM as [`resend-mcp`](https://github.com/resend/resend-mcp). If you prefer to run the server yourself, you can integrate it into any supported MCP client using `npx`. You'll need to:

* [Create an API key](/docs/create-an-api-key)
* [Verify your domain](/docs/add-a-domain)

The local server supports two transport modes: **stdio** (default) and **HTTP**.

Choose your preferred mode and client below to get started. Remember to replace `re_xxxxxxxxx` with your actual API key.

### Stdio Transport (Default)

<Tabs>
  <Tab title="Claude Code">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    claude mcp add resend -e RESEND_API_KEY=re_xxxxxxxxx -- npx -y resend-mcp
    ```
  </Tab>

  <Tab title="Codex">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    codex mcp add resend \
      --env RESEND_API_KEY=re_xxxxxxxxx \
      -- npx -y resend-mcp
    ```
  </Tab>

  <Tab title="Antigravity">
    Add this to your `~/.gemini/config/mcp_config.json` file:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "mcpServers": {
        "resend": {
          "command": "npx",
          "args": ["-y", "resend-mcp"],
          "env": {
            "RESEND_API_KEY": "re_xxxxxxxxx"
          }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Cursor">
    Open the command palette and choose "Cursor Settings" > "MCP" > "Add new global MCP server".

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "mcpServers": {
        "resend": {
          "command": "npx",
          "args": ["-y", "resend-mcp"],
          "env": {
            "RESEND_API_KEY": "re_xxxxxxxxx"
          }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Claude Desktop">
    Open Claude Desktop settings > "Developer" tab > "Edit Config".

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "mcpServers": {
        "resend": {
          "command": "npx",
          "args": ["-y", "resend-mcp"],
          "env": {
            "RESEND_API_KEY": "re_xxxxxxxxx"
          }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Copilot">
    To use Github Copilot in VS Code, add the following to your `settings.json`:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "mcp": {
        "servers": {
          "resend": {
            "command": "npx",
            "args": ["-y", "resend-mcp"],
            "env": {
              "RESEND_API_KEY": "re_xxxxxxxxx"
            }
          }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Gemini CLI">
    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "mcpServers": {
        "resend": {
          "command": "npx",
          "args": ["-y", "resend-mcp"],
          "env": {
            "RESEND_API_KEY": "re_xxxxxxxxx"
          }
        }
      }
    }
    ```
  </Tab>

  <Tab title="OpenCode">
    Add to your `opencode.json` config:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "$schema": "https://opencode.ai/config.json",
      "mcp": {
        "resend": {
          "type": "local",
          "command": ["npx", "-y", "resend-mcp"],
          "enabled": true,
          "environment": {
            "RESEND_API_KEY": "re_xxxxxxxxx"
          }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Windsurf">
    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "mcpServers": {
        "resend": {
          "command": "npx",
          "args": ["-y", "resend-mcp"],
          "env": {
            "RESEND_API_KEY": "re_xxxxxxxxx"
          }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Warp">
    In Warp's Settings, navigate to **Agents** > **MCP servers**, and click **+ Add** to add a new server.

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "resend": {
        "command": "npx",
        "args": ["-y", "resend-mcp"],
        "env": {
          "RESEND_API_KEY": "re_xxxxxxxxx"
        }
      }
    }
    ```
  </Tab>

  <Tab title="Devin">
    In Devin, open **Settings** > **Connections** > **MCP Servers** and click **Add a custom MCP**. See the [Devin guide](/docs/guides/devin) for the full step-by-step.

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "mcpServers": {
        "resend": {
          "command": "npx",
          "args": ["-y", "resend-mcp"],
          "env": {
            "RESEND_API_KEY": "re_xxxxxxxxx",
            "SENDER_EMAIL_ADDRESS": "onboarding@resend.dev"
          }
        }
      }
    }
    ```
  </Tab>
</Tabs>

### HTTP Transport

Run the server over HTTP for remote or web-based integrations. In HTTP mode, each client authenticates by passing their Resend API key as a Bearer token in the `Authorization` header.

Start the server:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
npx -y resend-mcp --http --port 3000
```

The server will listen on `http://127.0.0.1:3000` and expose the MCP endpoint at `/mcp` using Streamable HTTP.

<Tabs>
  <Tab title="Claude Code">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    claude mcp add resend --transport http http://127.0.0.1:3000/mcp --header "Authorization: Bearer re_xxxxxxxxx"
    ```
  </Tab>

  <Tab title="Cursor">
    Open the command palette and choose "Cursor Settings" > "MCP" > "Add new global MCP server".

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "mcpServers": {
        "resend": {
          "url": "http://127.0.0.1:3000/mcp",
          "headers": {
            "Authorization": "Bearer re_xxxxxxxxx"
          }
        }
      }
    }
    ```
  </Tab>
</Tabs>

You can also set the port via the `MCP_PORT` environment variable:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
MCP_PORT=3000 npx -y resend-mcp --http
```

### Options

You can pass additional arguments to configure the local server:

* `--key`: Your Resend API key (stdio mode only, since HTTP mode uses the Bearer token from the client)
* `--sender`: Default sender email address from a verified domain
* `--reply-to`: Default reply-to email address (can be specified multiple times)
* `--http`: Use HTTP transport instead of stdio (default: stdio)
* `--port`: HTTP port when using `--http` (default: 3000, or `MCP_PORT` env var)

**Environment variables:**

* `RESEND_API_KEY`: Your Resend API key (required for stdio, optional for HTTP since clients pass it via Bearer token)
* `SENDER_EMAIL_ADDRESS`: Default sender email address from a verified domain (optional)
* `REPLY_TO_EMAIL_ADDRESSES`: Comma-separated reply-to email addresses (optional)
* `MCP_PORT`: HTTP port when using `--http` (optional)

<Info>
  If you don't provide a sender email address, the MCP server will ask you to
  provide one each time you call the tool.
</Info>

## MCP Server tools

Resend's MCP server gives your AI agent native access to the full Resend platform through a single integration. You can manage all aspects of your email infrastructure using natural language.

* **Emails**: Send, list, get, cancel, update, and batch send emails. Supports HTML, plain text, attachments (local file, URL, or base64), CC/BCC, reply-to, scheduling, tags, and topic-based sending.
* **Received Emails**: List and read inbound emails. List and download received email attachments.
* **Templates**: Create, list, get, update, publish, duplicate, and remove email templates. Supports composing template content and `{{{VARIABLE}}}` placeholders.
* **Contacts**: Create, list, get, update, and remove contacts. Manage segment memberships, topic subscriptions, and CSV contact imports. Supports custom contact properties.
* **Broadcasts**: Create, send, list, get, update, and remove broadcast campaigns. Supports scheduling, personalization placeholders, and preview text.
* **Automations**: Create, list, get, update, and remove automations. Review the runs of an automation.
* **Events**: Send events to trigger automations for a contact. Create, update, and remove event definitions.
* **Domains**: Create, list, get, update, remove, and verify sender domains. Configure tracking, TLS, and sending/receiving capabilities. Create and verify domain claims.
* **Segments**: Create, list, get, and remove audience segments.
* **Topics**: Create, list, get, update, and remove subscription topics.
* **Contact Properties**: Create, list, get, update, and remove custom contact attributes.
* **API Keys**: Create, list, and remove API keys.
* **Webhooks**: Create, list, get, update, and remove webhooks for event notifications.
* **Logs**: List and inspect API request logs, including full request and response bodies.
* **Editor**: Connect to (and disconnect from) the visual editor in the Resend dashboard, and read a draft's content while collaborating on broadcasts and templates.

Here are some real examples of what your agent can do with these tools:

* Turn a [Paper design](/docs/guides/paper) into a ready-to-send [Template](/docs/dashboard/templates/introduction) or [Broadcast](/docs/dashboard/broadcasts/introduction)
* [Bulk import contacts from a CSV](/docs/dashboard/audiences/contacts#bulk-upload-by-csv), upserting or skipping duplicates, and organize them into [Segments](/docs/dashboard/segments/introduction)
* Build [Automations](/docs/dashboard/automations/introduction) that send emails when a contact is created, updated, or triggers a [custom event](/docs/dashboard/automations/custom-events)
* Read and triage [inbound email](/docs/dashboard/receiving/introduction), download attachments, and send replies
* Schedule, reschedule, and cancel [scheduled emails](/docs/dashboard/emails/schedule-email)
* Debug failed API requests by inspecting the [request logs](/docs/dashboard/logs/introduction)


# OpenClaw Guide
Source: https://resend.com/docs/openclaw-guide

Learn how to give your AI agent an inbox to send and receive emails.

## Why give your agent an inbox

Giving your agent an inbox enables it to:

* **Sign up for its own accounts** to GitHub, hosting platforms, and more, so you don't need to share your own credentials.
* **Process attachments** (such as receipts and invoices) and act accordingly
* **Receive newsletters**, parse them, and send the most important information to you
* **Send you daily reports and digests**
* **Send and receive emails**

## How to set up an inbox for OpenClaw

### Step 1: Install the skill

Ask your agent to install the skill:

```
Let's get you set up with an email inbox! Install the resend-skills from https://github.com/resend/resend-skills and review them before continuing.
```

<Tip>
  Giving your agent the GitHub link helps it to install the latest version of
  the skill since OpenClaw skills operate differently than traditional agent
  skills.
</Tip>

Your agent may also benefit from installing the [Resend CLI](/docs/cli).

### Step 2: Get an API key

Your agent will ask you to create an API key.

<Tip>
  Your API key will be scoped to the team that's currently selected. If you'd
  like to sandbox your agent, create a new team just for your agent.
</Tip>

<Steps>
  <Step title="Open the API Keys dialog">
    Navigate to the [API Keys](https://resend.com/api-keys) page in Resend and
    click **Create API Key**.
  </Step>

  <Step title="Choose a name and permission scope">
    Choose a name for your API key and ensure **Full access** is selected as the
    permission scope.
  </Step>

  <Step title="Create the API key">
    Click **Add** to create the API key, and copy it to your clipboard.
  </Step>
</Steps>

We recommend not pasting API keys into the chat. Instead, use one of these two methods:

1. SSH into your agent's machine and **store the API key in an `.env` file**.
2. **Store the API key in a password manager** like 1Password, and give your agent access to its own vault. This can be done using a [1Password Service Account](https://developer.1password.com/docs/service-accounts/) on team plans.

### Step 3: Verify a domain

Next, your agent needs to know the email address it will use to send and receive emails. [Strongly consider](/docs/knowledge-base/is-it-better-to-send-emails-from-a-subdomain-or-the-root-domain) using a subdomain (`agent.example.com`) instead of the root domain (`example.com`), especially if you want to receive emails.

You can also use the [Resend CLI](/docs/cli) to verify a domain, although you will need to manually add the DNS records to your DNS provider.

<Steps>
  <Step title="Add a domain">
    Navigate to the [Domains tab](https://resend.com/domains) and click **Add
    Domain**.
  </Step>

  <Step title="Select a subdomain and region">
    Add the subdomain you want to verify, and choose the region that's closest
    to your agent.

    You may see one of three options:

    * **Auto Configure**: This will automatically configure the DNS records for you if your provider supports it.
    * **Go to (provider)**: This will take you to the provider's website to add the DNS records manually if we can detect your provider.
    * **I've added the records**: If we cannot detect your provider, you can manually add the DNS records by opening your DNS provider's website.

    If you want only to send emails with your agent, add the DNS records and confirm. If you want to also receive emails, continue to the next step to enable receiving (for autoconfigure, you can add receiving after you autoconfigure).
  </Step>

  <Step title="Enable receiving">
    **Receiving** allows your agent to receive emails at your domain, rather
    than simply sending. Scroll to the bottom of the page and toggle the switch
    to **On**.
  </Step>

  <Step title="Add the DNS records to your domain">
    Add the DNS records to your domain's DNS provider. For
    more guidance, see our [guides on adding DNS records to various
    providers](knowledge-base/introduction#dns-guides).
  </Step>

  <Step title="Wait for verification">
    Wait for the domain to be verified. This can take up to 72 hours, but is
    typically finished within a few minutes.
  </Step>
</Steps>

<Tip>
  For a more in-depth guide on domain verification, see our [guide on verifying
  a domain](/docs/dashboard/domains/introduction).
</Tip>

Once your domain is verified in Resend, you can use it to send (and receive) emails with your agent. Add the email address to your agent's memory and tell it to send you a test email to your own email address.

### Step 4: Use webhooks to receive emails

At this point, your agent can send emails, but **it can't receive emails yet**.

To receive, you need to set up a webhook.

<Steps>
  <Step title="Ask your agent to set up a webhook server">
    Your agent should be equipped to do this using the Resend skill. Prompt it to get started:

    ```
    I want you to be able to receive emails, too. Let's set up a webhook to receive emails at my domain using the agent email inbox agent skill.
    ```
  </Step>

  <Step title="Set up a tunnel">
    Your agent should spin up a local server and suggest using a tunneling tool
    to expose it to the internet. We recommend [Tailscale
    Funnel](https://tailscale.com/kb/1223/funnel):

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    tailscale funnel 3000
    ```

    This gives your agent a stable public URL at
    `https://hostname.tailnet-name.ts.net`.
  </Step>

  <Step title="Give your agent access to secrets securely">
    When your agent asks for webhook signing secrets, give it access securely using one of the methods described in [Step 2: Get an API key](#step-2-get-an-api-key). Don't paste them directly into the chat.
  </Step>

  <Step title="Add the webhook to Resend">
    Ask your agent to register the webhook with Resend:

    ```
    Let's add a webhook to Resend using the server you just built. Use the email.received event, as instructed by the resend-skills agent skill, and securely save the returned webhook signing secret.
    ```
  </Step>

  <Step title="Test receiving an email">
    Send your agent a test email and ask it to check its inbox.
  </Step>
</Steps>

Your webhook server might look something like this:

```js theme={"theme":{"light":"github-light","dark":"vesper"}}
import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);

// Security: strict allowlist
const ALLOWED_SENDERS = ['your@email.com'];

async function handler(req) {
  const payload = await req.text();

  const id = req.headers.get('svix-id');
  const timestamp = req.headers.get('svix-timestamp');
  const signature = req.headers.get('svix-signature');

  if (!id || !timestamp || !signature) {
    return new Response('Missing headers', { status: 400 });
  }

  const event = resend.webhooks.verify({
    payload,
    headers: { id, timestamp, signature },
    webhookSecret: process.env.RESEND_WEBHOOK_SECRET,
  });

  if (event.type === 'email.received') {
    // Security check
    if (!ALLOWED_SENDERS.includes(event.data.from.toLowerCase())) {
      return new Response('OK', { status: 200 });
    }

    // Get full email
    const { data: email } = await resend.emails.receiving.get(
      event.data.email_id,
    );

    // Notify user instantly
    await notifyUser(email);
  }

  return new Response('OK', { status: 200 });
}
```

<Info>
  For more help working with inbound emails, including how to see the full email
  body, attachments, and more, see our [guide on receiving emails with
  Resend](/docs/dashboard/receiving/introduction).
</Info>

### Step 5: Hook into OpenClaw's APIs for instant notifications

One of the benefits of using Resend over other tools is that you don't need to constantly ask your agent to check its inbox, or rely on cron jobs to check every so often. With Resend, you can use OpenClaw's Gateway API to be notified instantly when your agent receives an email.

<Steps>
  <Step title="Ask your agent to hook into the Gateway API">
    ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
    Use the OpenClaw Gateway API to notify me instantly when you receive an email webhook call from Resend. Use the resend-skills agent skill for guidance.
    ```
  </Step>

  <Step title="Test instant notifications">
    Send your agent another test email. It should notify you instantly.
  </Step>
</Steps>

## Security considerations

Giving your agent an inbox is incredibly powerful, but it also comes with some security concerns. The risk of prompt injection via email is a real concern.

The Resend Skill [includes security guidelines](https://github.com/resend/resend-skills/blob/main/skills/agent-email-inbox/SKILL.md#security-levels). Use the leveled security approach below to decide which security level is right for your use case.

1. **Strict Allowlist**: Only allow emails from specific senders. **Recommended for most use cases**.
2. **Domain Allowlist**: Allow emails from any sender from a given domain (e.g. anyone from `example.com`).
3. **Content Filtering with Sanitization**: Accept emails from anyone, but sanitize content to remove potential injection attempts.
4. **Sandboxed Processing**: Process all emails but in a restricted context where the agent has limited capabilities.
5. **Human-in-the-Loop**: Process all emails but require human approval for each email.

In general, we recommend starting with the **Strict Allowlist** and gradually decreasing security if needed. Review additional security best practices in the [Resend Skill](https://github.com/resend/resend-skills/blob/main/skills/agent-email-inbox/SKILL.md#security-levels).

If you have any questions, please [contact support](https://resend.com/help).


# React Email Skill
Source: https://resend.com/docs/react-email-skill

Build HTML emails using React components with AI agents.

The React Email skill enables AI agents to build production-ready HTML emails using React components. It provides a modern development experience for creating responsive, cross-client compatible emails.

## Installation

Install the skill using the following command:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
npx skills add resend/react-email
```

## Advantages

* **Component-based email development**: Build emails using reusable React components for consistent, maintainable templates.
* **Brand-consistent styling with Tailwind**: Use Tailwind CSS to style emails with your brand's design system.
* **Multi-format rendering**: Automatically generate both HTML and plain text versions of your emails.
* **Email client compatibility handling**: Built-in support for rendering emails correctly across all major email clients.
* **Built-in preview server**: Preview your emails in real-time during development with hot reloading.

## Learn More

<Card title="View on GitHub" icon="arrow-up-right-from-square" href="https://github.com/resend/react-email/tree/canary/skills">
  See the full source code and documentation.
</Card>


# Send emails with Replit and Resend
Source: https://resend.com/docs/replit-integration

Learn how to add the Resend integration to your Replit project.

[Replit](https://replit.com/) is a platform for building sites and apps with AI. You can add Resend in a Replit project by asking the chat to add email sending with Resend.

**Example prompt**

```
When someone fills out the contact form, send an email using Resend.
```

Prefer watching a video? Check out our video walkthrough below.

<YouTube />

## Guide

<Steps>
  <Step title="Add a custom domain to your Resend account">
    By default, you can only send emails to your own email address.

    To send emails to other email addresses:

    1. Add a [custom domain to your Resend account](https://resend.com/domains).
    2. Add the custom domain to the `from` field in the `resend` function in Replit (or ask the chat to update these fields).

    Get more help adding a custom domain in [Resend's documentation](/docs/dashboard/domains/introduction).
  </Step>

  <Step title="Add your Resend API key and from address">
    To use Resend with Replit, you'll need to add a Resend API key, which you can create in the [Resend Dashboard](https://resend.com/api-keys). Do not share your API key with others or expose it in the browser or other client-side code.

    The from address is the email address that will be used to send emails. Use your custom domain you added in step 1 here (e.g., `hello@example.com`).

    <img alt="adding the Resend integration to a Replit chat" />

    <Note>
      Replit tracks the details of your Resend integration in the [Integrations
      page](https://replit.com/integrations).
    </Note>
  </Step>
</Steps>


# Resend Skill
Source: https://resend.com/docs/resend-skill

Send emails through the Resend API with AI agents.

The Resend skill enables AI agents to send emails through the Resend API using our official recommendations. It provides a streamlined interface for sending single and batch emails with built-in error handling and retry logic.

## Installation

This skill is part of the [resend-skills](https://github.com/resend/resend-skills) repository, which also includes the [Agent Email Inbox skill](/docs/agent-email-inbox-skill) for secure inbound email processing. When you run the install command, you'll be prompted to choose which skills to install.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
npx skills add resend/resend-skills
```

## Advantages

Build with our official recommendations for sending emails with Resend.

* **Single and batch email sending**: Send individual emails or batch up to 100 emails per request.
* **Built-in error handling and retry logic**: Automatic retries with exponential backoff for transient failures.
* **Idempotency key support**: Prevent duplicate sends with idempotency keys for safe retries.
* **Multi-language SDK support**: Works with Node.js, Python, Ruby, Go, and other supported SDKs.
* **Automatic activation for email tasks**: AI agents automatically use this skill when email sending is needed.

## Learn More

<CardGroup>
  <Card title="Agent Email Inbox" icon="inbox" href="/agent-email-inbox-skill">
    Give your agent a secure inbox to receive and act on inbound emails.
  </Card>

  <Card title="View on GitHub" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-skills">
    See the full source code and documentation.
  </Card>
</CardGroup>


# Official SDKs
Source: https://resend.com/docs/sdks

Open source client libraries for your favorite platforms.

## Official SDKs

<CardGroup>
  <Card title="Node.js" icon="github" href="https://github.com/resend/resend-node">
    github.com/resend/resend-node
  </Card>

  <Card title="PHP" icon="github" href="https://github.com/resend/resend-php">
    github.com/resend/resend-php
  </Card>

  <Card title="Laravel" icon="github" href="https://github.com/resend/resend-laravel">
    github.com/resend/resend-laravel
  </Card>

  <Card title="Python" icon="github" href="https://github.com/resend/resend-python">
    github.com/resend/resend-python
  </Card>

  <Card title="Ruby" icon="github" href="https://github.com/resend/resend-ruby">
    github.com/resend/resend-ruby
  </Card>

  <Card title="Go" icon="github" href="https://github.com/resend/resend-go">
    github.com/resend/resend-go
  </Card>

  <Card title="Java" icon="github" href="https://github.com/resend/resend-java">
    github.com/resend/resend-java
  </Card>

  <Card title="Rust" icon="github" href="https://github.com/resend/resend-rust">
    github.com/resend/resend-rust
  </Card>

  <Card title=".NET" icon="github" href="https://github.com/resend/resend-dotnet">
    github.com/resend/resend-dotnet
  </Card>

  <Card title="Chat SDK Adapter" icon="github" href="https://github.com/resend/resend-chat-sdk">
    github.com/resend/resend-chat-sdk
  </Card>
</CardGroup>

## Community SDKs

<CardGroup>
  <Card title="Elixir" icon="github" href="https://github.com/elixir-saas/resend-elixir">
    github.com/elixir-saas/resend-elixir
  </Card>

  <Card title="NestJS" icon="github" href="https://github.com/jiangtaste/nestjs-resend">
    github.com/jiangtaste/nestjs-resend
  </Card>

  <Card title="Dart" icon="github" href="https://github.com/coderaveHQ/dart_resend">
    github.com/coderaveHQ/dart\_resend
  </Card>
</CardGroup>

## OpenAPI

<CardGroup>
  <Card title="OpenAPI" icon="github" href="https://github.com/resend/resend-openapi">
    github.com/resend/resend-openapi
  </Card>
</CardGroup>


# Security
Source: https://resend.com/docs/security

An overview of Resend security features and practices.

## Governance

Resend establishes policies and controls, monitors compliance with those controls, and proves the security and compliance to third-party auditors.

Our policies are based on the following **foundational principles**:

<CardGroup>
  <Card title="Least Privilege" icon="square-1">
    Access should be limited to only those with a legitimate business needs,
    based on the principle of least privilege.
  </Card>

  <Card title="Consistency" icon="square-2">
    Security controls should be applied consistently across all areas of the
    enterprise.
  </Card>

  <Card title="Defense in Depth" icon="square-3">
    Security controls should be implemented and layered according to the
    principle of defense-in-depth.
  </Card>

  <Card title="Continuous Improvement" icon="square-4">
    The implementation of controls should be iterative, continuously improving
    effectiveness and decreasing friction.
  </Card>
</CardGroup>

### Compliance Standards

<AccordionGroup>
  <Accordion title="SOC 2 Type II" icon="hourglass-clock">
    Resend is SOC 2 Type II compliant. The audit was completed by Vanta & Advantage Partners.
    You can download a copy of the report on the [Documents](https://resend.com/settings/documents) page.
  </Accordion>

  <Accordion title="GDPR" icon="hourglass-clock">
    Resend is GDPR compliant. You can learn more about our [GDPR compliance](https://resend.com/security/gdpr) or view our [DPA](https://resend.com/legal/dpa).
  </Accordion>
</AccordionGroup>

## Data Protection

<CardGroup>
  <Card title="Data at rest" icon="server">
    All datastores are encrypted at rest. Sensitive collections and tables also
    use row-level encryption.
  </Card>

  <Card title="Data in transit" icon="network-wired">
    Resend uses TLS 1.3 or higher everywhere data is transmitted over
    potentially insecure networks.
  </Card>

  <Card title="Data backup" icon="database">
    Resend backs-up all production data using a point-in-time approach. Backups
    are persisted for 30 days, and are globally replicated for resiliency
    against regional disasters.
  </Card>
</CardGroup>

## Product Security

### Penetration testing

Resend engages with third-party firms to conduct penetration testing at least annually.

All areas of the Resend product and cloud infrastructure are in-scope for these assessments, and source code is fully available to the testers to maximize the effectiveness and coverage.

You can download the latest penetration test report on the [Documents](https://resend.com/settings/documents) page.

### Vulnerability scanning

Resend uses multiple vulnerability monitoring techniques including code-level scanning, dependency scanning, and security reviews to identify and remediate vulnerabilities.

Vulnerabilities are prioritized based on severity and risk, and are remediated according to the following schedule:

* Critical: 15 Days
* High: 30 Days
* Medium: 90 Day
* Low: 180 Days
* Informational: As needed

## Enterprise Security

<CardGroup>
  <Card title="Endpoint protection" icon="computer">
    All company devices are equipped with anti-malware protection. Endpoint security alerts are monitored with 24/7/365 coverage. We use MDM software to enforce secure configuration of endpoints, such as disk encryption, screen lock configuration, and software updates.
  </Card>

  <Card title="Security education" icon="graduation-cap">
    Resend provides comprehensive security training to all employees upon onboarding and annually.

    Resend's conducts threat briefings with employees to inform them of important security and safety-related updates that require special attention or action.
  </Card>

  <Card title="Identity and access management" icon="id-badge">
    Resend employees are granted access to applications based on their role, and automatically deprovisioned upon termination of their employment. Further access must be approved according to the policies set for each application.

    Multi-factor authentication is required for all employees to access company applications.
  </Card>
</CardGroup>

## Responsible Disclosure

To report a vulnerability, please check the guidelines on the [Responsible Disclosure](https://resend.com/security/responsible-disclosure) page.


# Send emails with Astro
Source: https://resend.com/docs/send-with-astro

Learn how to send your first email using Astro, Resend, and Node.js.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend Node.js SDK

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using the [Resend](https://resend.com/) Node.js SDK.
  **Scope:** All AI-generated advice or code related to sending email with Resend must follow these guardrails.

  ***

  ## **1. Official Resend Node.js Setup**

  ### **Prerequisites**

  Human must first create an API key and verify their domain at [https://resend.com/domains](https://resend.com/domains).

  The API key must be stored in an environment variable called `RESEND_API_KEY`.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  The domain should be verified at [https://resend.com/domains](https://resend.com/domains) and added to the `from` address.

  ### **Install the SDK**

  Use the project's existing package manager to install the Resend Node.js SDK.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  # or: yarn add resend / pnpm add resend / bun add resend
  ```

  ### **Initialize the Client**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  ### **Send an Email**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  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);
    return;
  }

  console.log(data); // { id: '49a3999c-...' }
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ### Idempotency

  Best practice: Add an idempotency key to prevent duplicated emails, which is useful for retrying failed emails safely.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**
  * Pattern: `<event-type>/<entity-id>`
  * Example: `welcome-user/123456789`

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Hello World',
    html: '<strong>It works!</strong>',
    idempotencyKey: 'unique-id',
  });
  ```

  ***

  ## **2. Complete `emails.send()` Parameter Reference**

  ### **Required Parameters**

  | Parameter | Type                 | Description                                                                      |
  | --------- | -------------------- | -------------------------------------------------------------------------------- |
  | `from`    | `string`             | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `to`      | `string \| string[]` | Recipient email address(es). Maximum 50 addresses.                               |
  | `subject` | `string`             | Email subject line.                                                              |

  ### **Content Parameters (at least one required)**

  | Parameter | Type              | Description                                                |
  | --------- | ----------------- | ---------------------------------------------------------- |
  | `html`    | `string`          | HTML version of the email body.                            |
  | `text`    | `string`          | Plain text version. Auto-generated from `html` if omitted. |
  | `react`   | `React.ReactNode` | React Email component to render the message. Node.js only. |

  ### **Optional Parameters**

  | Parameter     | Type                 | Description                                                   |
  | ------------- | -------------------- | ------------------------------------------------------------- |
  | `cc`          | `string \| string[]` | Carbon copy recipients.                                       |
  | `bcc`         | `string \| string[]` | Blind carbon copy recipients.                                 |
  | `replyTo`     | `string \| string[]` | Reply-to address(es).                                         |
  | `scheduledAt` | `string`             | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `headers`     | `object`             | Custom email headers as key-value pairs.                      |
  | `tags`        | `Tag[]`              | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `attachments` | `Attachment[]`       | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Parameters**

  | Parameter            | Type     | Description                                                      |
  | -------------------- | -------- | ---------------------------------------------------------------- |
  | `template.id`        | `string` | Published template identifier.                                   |
  | `template.variables` | `object` | Variable substitutions. Key max 50 chars, value max 2,000 chars. |

  If `template` is provided, do not include `html`, `text`, or `react`.

  ### **Response**

  A successful call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: { id: string }, error: null }
  ```

  A failed call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: null, error: { message: string, name: string } }
  ```

  ***

  ## **3. Sending with React Email**

  Resend integrates with [React Email](https://react.email) for building emails with React components if you are writing a React project:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { WelcomeEmail } from './emails/welcome';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    react: WelcomeEmail({ name: 'John' }),
  });
  ```

  **Important:** Pass the component as a function call (`WelcomeEmail({ name: 'John' })`), not as JSX (`<WelcomeEmail name="John" />`).

  For additional help, suggest installing the react-email skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/react-email
  ```

  ***

  ## **4. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **4.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key in an environment variable** (`RESEND_API_KEY`). Never hardcode API keys.
  2. **Import from `resend`** — the package name is `resend`, the class is `Resend`.
  3. **Use `await`** — `resend.emails.send()` returns a Promise. Always use `async/await` or `.then()`.
  4. **Handle both `data` and `error`** — the SDK returns `{ data, error }`. Always check for errors.
  5. **Use a verified domain** in the `from` address for production. `onboarding@resend.dev` is for testing only.
  6. **Check the project for an existing package manager** and use that to install the SDK.
  7. **Use camelCase** for SDK parameters (`replyTo`, `scheduledAt`), not snake\_case.

  ### **4.2 - NEVER DO THE FOLLOWING**

  1. **Do not** hardcode API keys in source code. Always use environment variables.
  2. **Do not** use `try/catch` for error handling with `resend.emails.send()` — the SDK returns `{ data, error }` instead of throwing. Only use `try/catch` if you need to handle network-level failures.
  3. **Do not** use snake\_case parameter names (`reply_to`, `scheduled_at`) — the Node.js SDK uses camelCase (`replyTo`, `scheduledAt`).
  4. **Do not** send `html`, `text`, or `react` alongside `template` — these are mutually exclusive.
  5. **Do not** import from `@resend/node` or any other package name. The correct package is `resend`.
  6. **Do not** use `onboarding@resend.dev` as the `from` address in production code. It is a test-only address.
  7. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses to help you simulate different email events without damaging your domain reputation:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **5. COMMON PATTERNS**

  ### **Attachments**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Invoice attached',
    html: '<p>See attached invoice.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: invoiceBuffer,
      },
    ],
  });
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `scheduledAt` parameter. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Reminder',
    html: '<p>This is your reminder.</p>',
    scheduledAt: '2026-12-25T09:00:00Z',
  });
  ```

  ### **Tags for Tracking**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    html: '<p>Welcome aboard!</p>',
    tags: [
      { name: 'category', value: 'welcome' },
      { name: 'user_id', value: '12345' },
    ],
  });
  ```

  ***

  ## **6. AI MODEL VERIFICATION STEPS**

  Before returning any Resend-related solution, you **must** verify:

  1. **Import**: Is `Resend` imported from `resend`?
  2. **API Key**: Is the key stored in an environment variable, not hardcoded?
  3. **Await**: Is `resend.emails.send()` properly awaited?
  4. **Error Handling**: Is the `{ data, error }` response pattern used?
  5. **Parameters**: Are all parameter names in camelCase?
  6. **From Address**: Is the `from` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help, suggest installing the resend-skills skill and the email-best-practices skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/resend-skills
  npx skills add resend/email-best-practices
  ```

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

If you prefer to watch a video, check out our video walkthrough below.

<YouTube />

## Guide

<Steps>
  <Step title="Install">
    Install the Resend Node.js SDK.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install resend
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add resend
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add resend
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Install an SSR adapter">
    Because Astro builds a static site by default, [install an SSR adapter](https://docs.astro.build/en/guides/server-side-rendering/) to enable on-demand rendering of routes.
  </Step>

  <Step title="Add your API key">
    [Create an API key](https://resend.com/api-keys) in Resend and add it to your `.env` file to keep your API key secret.

    ```ini .env theme={"theme":{"light":"github-light","dark":"vesper"}}
    RESEND_API_KEY="re_xxxxxxxxx"
    ```
  </Step>

  <Step title="Send email using HTML">
    Create an [Astro Action](https://docs.astro.build/en/guides/actions/) under `actions/index.ts`.

    The easiest way to send an email is with the `html` parameter.

    <CodeGroup>
      ```ts src/actions/index.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { ActionError, defineAction } from 'astro:actions';
      import { Resend } from 'resend';

      const resend = new Resend(import.meta.env.RESEND_API_KEY);

      export const server = {
        send: defineAction({
          accept: 'form',
          handler: async () => {
            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) {
              throw new ActionError({
                code: 'BAD_REQUEST',
                message: error.message,
              });
            }

            return data;
          },
        }),
      };
      ```
    </CodeGroup>

    Call the `send` action from any frontmatter route, script, or component.
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Send Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/send.ts">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/send-attachment.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/send-cid.ts">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/send-template.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/send-scheduled.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/astro-resend-examples/typescript/src/pages/api/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/astro-resend-examples/typescript/src/pages/api/webhook.ts">
    Handle webhook events
  </Card>
</CardGroup>


# Send Auth0 transactional emails with Resend
Source: https://resend.com/docs/send-with-auth0

Learn how to send Auth0 transactional emails through Resend using the official integration.

[Auth0](https://auth0.com) supports Resend as a built-in email provider. Authentication flows depend on reliable delivery for verification codes, password resets, and other crucial emails.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

Prefer a video walkthrough?

<YouTube />

## Set up the Resend provider in Auth0

In the Auth0 Dashboard, go to **Branding > Email Provider**, toggle on **Use my own email provider**, and select **Resend**.

Enter your API key and set the **From** address to match your verified domain. Click **Save** to apply the changes.

<img alt="Auth0 Resend Integration" />

To test that it's working, click **Send Test Email**. The email will appear in your Resend dashboard and email inbox.

<Info>
  For the full setup guide, see the [Auth0
  documentation](https://auth0.com/docs/customize/email/smtp-email-providers/resend).
</Info>

## Send emails with Auth0 Actions (optional)

For more control over delivery, like per-organization sender addresses, conditional routing, or custom logic, you can use an Auth0 Action instead.

In the Auth0 Dashboard, go to **Actions > Library**, create a new Custom action.

<img alt="Auth0 Custom Action" />

To enable Resend in the Action:

1. Add `resend` as a dependency.
   <img alt="Auth0 Custom Action" />
2. Store your API key as a secret named `RESEND_API_KEY`.
   <img alt="Auth0 Custom Action" />

Here's a working example that sends a security alert on first login:

```javascript theme={"theme":{"light":"github-light","dark":"vesper"}}
const { Resend } = require('resend');

exports.onExecutePostLogin = async (event, api) => {
  const resend = new Resend(event.secrets.RESEND_API_KEY);

  if (event.stats.logins_count === 1) {
    await resend.emails.send({
      from: 'Security <security@example.com>',
      to: event.user.email,
      subject: 'New login detected',
      html: `<p>Hi ${event.user.name}, a new login was detected from ${event.request.ip}.</p>`,
    });
  }
};
```

Deploy it by adding the action to the **Post Login** trigger under **Actions > Triggers**.

## Customize Email Templates

To customize the email templates that Auth0 sends out, go to **Branding > Email Templates** in the Auth0 Dashboard and make your changes to the existing templates.

For more advanced templating, consider either [React Email](#react-email) or [Resend Templates](#resend-templates).

### React Email

Auth0 email templates use Liquid syntax for dynamic variables like `{{ user.email }}` and `{{ url }}`. You can author templates with [React Email](https://react.email) and inject Liquid variables before pasting the rendered HTML into Auth0.

Define your Liquid variables as constants to avoid HTML encoding issues during rendering:

```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
export const VARIABLES = {
  url: '{{ url }}',
  user: { email: '{{ user.email }}' },
  application: { name: '{{ application.name }}' },
};
```

Use them in your React Email components, render to static HTML, and paste the output into **Branding > Email Templates** in Auth0.

### Resend Templates

To use Resend templates with Auth0, define your templates in the [Resend Dashboard](https://resend.com/templates) and reference them in your [Custom OAuth Actions](#send-emails-with-auth0-actions-optional).

For instance, the following code uses a Resend template with the id of `login-detected` that contains two variables (`first_name` and `ip_address`) to be passed in the call. [Learn more about Resend templates](/docs/dashboard/templates/introduction).

```javascript theme={"theme":{"light":"github-light","dark":"vesper"}}
const { Resend } = require('resend');

exports.onExecutePostLogin = async (event, api) => {
  const resend = new Resend(event.secrets.RESEND_API_KEY);

  if (event.stats.logins_count === 1) {
    await resend.emails.send({
      from: 'Security <security@example.com>',
      to: event.user.email,
      template: {
        id: 'login-detected',
        variables: {
          first_name: event.user.name,
          ip_address: event.request.ip,
        },
      },
    });
  }
};
```

## Debugging Email Delivery

When something goes wrong, it's helpful to see detailed logs across both sides:

* **Auth0 Logs** (**Monitoring > Logs**) shows send events and any errors raised from the Resend integration.
* [**Resend Logs**](https://resend.com/logs) show the delivery side: accepted, delivered, opened, bounced.

Together, you get end-to-end visibility across the entire delivery chain.


# Send emails with AWS Lambda
Source: https://resend.com/docs/send-with-aws-lambda

Learn how to send your first email using AWS Lambda.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Create an AWS Lambda function">
    Go to [aws.amazon.com](https://aws.amazon.com) and create a new Lambda function using the Node.js 20.x or later runtime.

    <img alt="AWS Lambda - New Function" />
  </Step>

  <Step title="Edit the handler function">
    Paste the following code into the browser editor:

    ```js index.mjs theme={"theme":{"light":"github-light","dark":"vesper"}}
    const RESEND_API_KEY = 're_xxxxxxxxx';

    export const handler = async (event) => {
      const res = await fetch('https://api.resend.com/emails', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${RESEND_API_KEY}`,
        },
        body: JSON.stringify({
          from: 'Acme <onboarding@resend.dev>',
          to: ['delivered@resend.dev'],
          subject: 'hello world',
          html: '<strong>it works!</strong>',
        }),
      });

      if (res.ok) {
        const data = await res.json();

        return {
          statusCode: 200,
          body: data,
        };
      }
    };
    ```
  </Step>

  <Step title="Deploy and send email">
    Click on `Deploy` and then `Test` at the top of the screen.

    <img alt="AWS Lambda - Edit Function" />
  </Step>
</Steps>

## Examples

<Card title="AWS Lambda Example" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-aws-lambda-example">
  See the full source code.
</Card>


# Send emails with Axum
Source: https://resend.com/docs/send-with-axum

Send your first email using Axum and the Resend Rust SDK.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Rust SDK and the [Tokio](https://tokio.rs) runtime.

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    cargo add resend-rs
    cargo add tokio -F macros,rt-multi-thread
    ```
  </Step>

  <Step title="Send an Email">
    ```rust theme={"theme":{"light":"github-light","dark":"vesper"}}
    use std::sync::Arc;

    use axum::{extract::State, http::StatusCode, routing::get, Router};
    use resend_rs::types::CreateEmailBaseOptions;
    use resend_rs::{Resend, Result};

    // Cloning the Resend client is fine and cheap as the internal HTTP client is
    // not cloned.
    #[derive(Clone)]
    struct AppState {
      resend: Resend,
    }

    #[tokio::main]
    async fn main() {
      let shared_state = Arc::new(AppState {
        resend: Resend::new("re_xxxxxxxxx"),
      });

      // build our application with a single route
      let app = Router::new()
        .route("/", get(endpoint))
        // provide the state so the router can access it
        .with_state(shared_state);

      // run our app with hyper, listening globally on port 3000
      let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
      axum::serve(listener, app).await.unwrap();
    }

    async fn endpoint(State(state): State<Arc<AppState>>) -> Result<String, StatusCode> {
      let from = "Acme <onboarding@resend.dev>";
      let to = ["delivered@resend.dev"];
      let subject = "Hello World";

      let email = CreateEmailBaseOptions::new(from, to, subject)
        .with_html("<strong>It works!</strong>");

      // access the state via the `State` extractor and handle the error
      match state.resend.emails.send(email).await {
        Ok(email) => Ok(email.id.to_string()),
        Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR),
      }
    }
    ```

    Opening your browser at `http://localhost:3000` (or running `curl localhost:3000`) sends an
    email and returns its id!
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Axum App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/rust-resend-examples/axum_app">
    Full Axum web framework application
  </Card>

  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/basic_send.rs">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/with_attachments.rs">
    Send emails with file attachments
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/with_template.rs">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/scheduled_send.rs">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/audiences.rs">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/domains.rs">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/inbound.rs">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/double_optin_subscribe.rs">
    Double opt-in subscription flow
  </Card>
</CardGroup>


# Send Better Auth emails with Resend
Source: https://resend.com/docs/send-with-better-auth

Learn how to send Better Auth transactional emails through Resend using email hooks.

[Better Auth](https://better-auth.com) is a framework-agnostic authentication library for TypeScript. It relies on transactional email for password resets, email verification, magic links, and one-time codes, all of which you can deliver with Resend.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)
* A project with [Better Auth installed](https://better-auth.com/docs/installation)

## Install the Resend SDK

<CodeGroup>
  ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  ```

  ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
  pnpm add resend
  ```

  ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
  yarn add resend
  ```
</CodeGroup>

Add your API key to the environment:

```bash .env theme={"theme":{"light":"github-light","dark":"vesper"}}
RESEND_API_KEY=re_xxxxxxxxx
```

<Note>
  The hook examples below call `void resend.emails.send(...)` instead of
  awaiting it, [as Better Auth
  recommends](https://better-auth.com/docs/concepts/email), so the response time
  doesn't reveal whether an account exists. On serverless platforms, wrap the
  send in `waitUntil` (or your platform's equivalent) so the function doesn't
  terminate before the email is sent.
</Note>

## Send password reset and verification emails

Better Auth calls your `sendResetPassword` and `sendVerificationEmail` hooks when a user requests a reset or needs to confirm their address. Send the email with Resend inside each hook.

```typescript auth.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { betterAuth } from 'better-auth';
import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    sendResetPassword: ({ user, url }) => {
      void resend.emails.send({
        from: 'Acme <onboarding@example.com>',
        to: user.email,
        subject: 'Reset your password',
        html: `Click <a href="${url}">here</a> to reset your password.`,
      });
    },
  },
  emailVerification: {
    sendVerificationEmail: ({ user, url }) => {
      void resend.emails.send({
        from: 'Acme <onboarding@example.com>',
        to: user.email,
        subject: 'Verify your email address',
        html: `Click <a href="${url}">here</a> to verify your email.`,
      });
    },
  },
});
```

<Info>
  Set the `from` address to match your [verified domain](/docs/add-a-domain).
</Info>

## Send magic links (optional)

If you use the [magic link plugin](https://better-auth.com/docs/plugins/magic-link), send the sign-in link through the `sendMagicLink` hook.

```typescript auth.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { betterAuth } from 'better-auth';
import { magicLink } from 'better-auth/plugins';
import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);

export const auth = betterAuth({
  plugins: [
    magicLink({
      sendMagicLink: ({ email, url }) => {
        void resend.emails.send({
          from: 'Acme <onboarding@example.com>',
          to: email,
          subject: 'Sign in to Acme',
          html: `Click <a href="${url}">here</a> to sign in.`,
        });
      },
    }),
  ],
});
```

<Info>
  Set the `from` address to match your [verified domain](/docs/add-a-domain).
</Info>

## Send one-time codes (optional)

The [email OTP plugin](https://better-auth.com/docs/plugins/email-otp) sends a one-time password (OTP), a numeric code, instead of a link. The `type` argument tells you which flow triggered the request so you can tailor the subject line.

```typescript auth.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { betterAuth } from 'better-auth';
import { emailOTP } from 'better-auth/plugins';
import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);

export const auth = betterAuth({
  plugins: [
    emailOTP({
      sendVerificationOTP: ({ email, otp, type }) => {
        void resend.emails.send({
          from: 'Acme <onboarding@example.com>',
          to: email,
          subject:
            type === 'sign-in' ? 'Your sign-in code' : 'Your verification code',
          html: `Your code is <strong>${otp}</strong>.`,
        });
      },
    }),
  ],
});
```

<Info>
  Set the `from` address to match your [verified domain](/docs/add-a-domain).
</Info>

## Customize email templates

For richer, reusable emails, author your templates with [React Email](https://react.email) and pass the rendered component to Resend's `react` field, or reference a [Resend template](/docs/dashboard/templates/introduction) by `id`.

```typescript auth.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { ResetPasswordEmail } from './emails/reset-password';

sendResetPassword: ({ user, url }) => {
  void resend.emails.send({
    from: 'Acme <onboarding@example.com>',
    to: user.email,
    subject: 'Reset your password',
    react: ResetPasswordEmail({ url }),
  });
},
```

<Info>
  Set the `from` address to match your [verified domain](/docs/add-a-domain).
</Info>

## Debugging email delivery

When a flow doesn't behave as expected, check both sides:

* **Better Auth logs** show the hook invocation and any errors thrown while sending.
* [**Resend Logs**](https://resend.com/logs) show the delivery side: accepted, delivered, opened, bounced.

Together, you get end-to-end visibility across the entire delivery chain.


# Send emails with Bun
Source: https://resend.com/docs/send-with-bun

Learn how to send your first email using Bun and the Resend Node.js SDK.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend Node.js SDK

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using the [Resend](https://resend.com/) Node.js SDK.
  **Scope:** All AI-generated advice or code related to sending email with Resend must follow these guardrails.

  ***

  ## **1. Official Resend Node.js Setup**

  ### **Prerequisites**

  Human must first create an API key and verify their domain at [https://resend.com/domains](https://resend.com/domains).

  The API key must be stored in an environment variable called `RESEND_API_KEY`.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  The domain should be verified at [https://resend.com/domains](https://resend.com/domains) and added to the `from` address.

  ### **Install the SDK**

  Use the project's existing package manager to install the Resend Node.js SDK.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  # or: yarn add resend / pnpm add resend / bun add resend
  ```

  ### **Initialize the Client**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  ### **Send an Email**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  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);
    return;
  }

  console.log(data); // { id: '49a3999c-...' }
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ### Idempotency

  Best practice: Add an idempotency key to prevent duplicated emails, which is useful for retrying failed emails safely.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**
  * Pattern: `<event-type>/<entity-id>`
  * Example: `welcome-user/123456789`

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Hello World',
    html: '<strong>It works!</strong>',
    idempotencyKey: 'unique-id',
  });
  ```

  ***

  ## **2. Complete `emails.send()` Parameter Reference**

  ### **Required Parameters**

  | Parameter | Type                 | Description                                                                      |
  | --------- | -------------------- | -------------------------------------------------------------------------------- |
  | `from`    | `string`             | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `to`      | `string \| string[]` | Recipient email address(es). Maximum 50 addresses.                               |
  | `subject` | `string`             | Email subject line.                                                              |

  ### **Content Parameters (at least one required)**

  | Parameter | Type              | Description                                                |
  | --------- | ----------------- | ---------------------------------------------------------- |
  | `html`    | `string`          | HTML version of the email body.                            |
  | `text`    | `string`          | Plain text version. Auto-generated from `html` if omitted. |
  | `react`   | `React.ReactNode` | React Email component to render the message. Node.js only. |

  ### **Optional Parameters**

  | Parameter     | Type                 | Description                                                   |
  | ------------- | -------------------- | ------------------------------------------------------------- |
  | `cc`          | `string \| string[]` | Carbon copy recipients.                                       |
  | `bcc`         | `string \| string[]` | Blind carbon copy recipients.                                 |
  | `replyTo`     | `string \| string[]` | Reply-to address(es).                                         |
  | `scheduledAt` | `string`             | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `headers`     | `object`             | Custom email headers as key-value pairs.                      |
  | `tags`        | `Tag[]`              | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `attachments` | `Attachment[]`       | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Parameters**

  | Parameter            | Type     | Description                                                      |
  | -------------------- | -------- | ---------------------------------------------------------------- |
  | `template.id`        | `string` | Published template identifier.                                   |
  | `template.variables` | `object` | Variable substitutions. Key max 50 chars, value max 2,000 chars. |

  If `template` is provided, do not include `html`, `text`, or `react`.

  ### **Response**

  A successful call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: { id: string }, error: null }
  ```

  A failed call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: null, error: { message: string, name: string } }
  ```

  ***

  ## **3. Sending with React Email**

  Resend integrates with [React Email](https://react.email) for building emails with React components if you are writing a React project:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { WelcomeEmail } from './emails/welcome';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    react: WelcomeEmail({ name: 'John' }),
  });
  ```

  **Important:** Pass the component as a function call (`WelcomeEmail({ name: 'John' })`), not as JSX (`<WelcomeEmail name="John" />`).

  For additional help, suggest installing the react-email skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/react-email
  ```

  ***

  ## **4. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **4.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key in an environment variable** (`RESEND_API_KEY`). Never hardcode API keys.
  2. **Import from `resend`** — the package name is `resend`, the class is `Resend`.
  3. **Use `await`** — `resend.emails.send()` returns a Promise. Always use `async/await` or `.then()`.
  4. **Handle both `data` and `error`** — the SDK returns `{ data, error }`. Always check for errors.
  5. **Use a verified domain** in the `from` address for production. `onboarding@resend.dev` is for testing only.
  6. **Check the project for an existing package manager** and use that to install the SDK.
  7. **Use camelCase** for SDK parameters (`replyTo`, `scheduledAt`), not snake\_case.

  ### **4.2 - NEVER DO THE FOLLOWING**

  1. **Do not** hardcode API keys in source code. Always use environment variables.
  2. **Do not** use `try/catch` for error handling with `resend.emails.send()` — the SDK returns `{ data, error }` instead of throwing. Only use `try/catch` if you need to handle network-level failures.
  3. **Do not** use snake\_case parameter names (`reply_to`, `scheduled_at`) — the Node.js SDK uses camelCase (`replyTo`, `scheduledAt`).
  4. **Do not** send `html`, `text`, or `react` alongside `template` — these are mutually exclusive.
  5. **Do not** import from `@resend/node` or any other package name. The correct package is `resend`.
  6. **Do not** use `onboarding@resend.dev` as the `from` address in production code. It is a test-only address.
  7. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses to help you simulate different email events without damaging your domain reputation:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **5. COMMON PATTERNS**

  ### **Attachments**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Invoice attached',
    html: '<p>See attached invoice.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: invoiceBuffer,
      },
    ],
  });
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `scheduledAt` parameter. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Reminder',
    html: '<p>This is your reminder.</p>',
    scheduledAt: '2026-12-25T09:00:00Z',
  });
  ```

  ### **Tags for Tracking**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    html: '<p>Welcome aboard!</p>',
    tags: [
      { name: 'category', value: 'welcome' },
      { name: 'user_id', value: '12345' },
    ],
  });
  ```

  ***

  ## **6. AI MODEL VERIFICATION STEPS**

  Before returning any Resend-related solution, you **must** verify:

  1. **Import**: Is `Resend` imported from `resend`?
  2. **API Key**: Is the key stored in an environment variable, not hardcoded?
  3. **Await**: Is `resend.emails.send()` properly awaited?
  4. **Error Handling**: Is the `{ data, error }` response pattern used?
  5. **Parameters**: Are all parameter names in camelCase?
  6. **From Address**: Is the `from` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help, suggest installing the resend-skills skill and the email-best-practices skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/resend-skills
  npx skills add resend/email-best-practices
  ```

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Node.js SDK.

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    bun install resend
    ```
  </Step>

  <Step title="Create an email template">
    Start by creating your email template on `email-template.tsx`.

    ```tsx email-template.tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
    import * as React from 'react';

    interface EmailTemplateProps {
      firstName: string;
    }

    export const EmailTemplate = ({ firstName }: EmailTemplateProps) => (
      <div>
        <h1>Welcome, {firstName}!</h1>
      </div>
    );
    ```
  </Step>

  <Step title="Send email using React">
    Create a new file `index.tsx` and send your first email.

    ```tsx index.tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { Resend } from 'resend';
    import { EmailTemplate } from './email-template';

    const resend = new Resend(process.env.RESEND_API_KEY);

    const server = Bun.serve({
      port: 3000,
      async fetch() {
        const data = await resend.emails.send({
          from: 'Acme <onboarding@resend.dev>',
          to: ['delivered@resend.dev'],
          subject: 'Hello World',
          react: EmailTemplate({ firstName: 'Vitor' }),
        });

        return new Response(JSON.stringify(data));
      },
    });

    console.log(`Listening on http://localhost:${server.port} ...`);
    ```

    Start the local server by running `bun index.tsx` and navigate to `http://localhost:3000`.
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/basic-send.ts">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/with-attachments.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/with-cid-attachments.ts">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/with-template.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/scheduled-send.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/prevent-threading.ts">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/audiences.ts">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/inbound.ts">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/bun-resend-examples/typescript/examples/double-optin-subscribe.ts">
    Double opt-in subscription flow
  </Card>
</CardGroup>


# Send emails with Cloudflare Workers
Source: https://resend.com/docs/send-with-cloudflare-workers

Learn how to send your first email using Cloudflare Workers.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend Node.js SDK

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using the [Resend](https://resend.com/) Node.js SDK.
  **Scope:** All AI-generated advice or code related to sending email with Resend must follow these guardrails.

  ***

  ## **1. Official Resend Node.js Setup**

  ### **Prerequisites**

  Human must first create an API key and verify their domain at [https://resend.com/domains](https://resend.com/domains).

  The API key must be stored in an environment variable called `RESEND_API_KEY`.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  The domain should be verified at [https://resend.com/domains](https://resend.com/domains) and added to the `from` address.

  ### **Install the SDK**

  Use the project's existing package manager to install the Resend Node.js SDK.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  # or: yarn add resend / pnpm add resend / bun add resend
  ```

  ### **Initialize the Client**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  ### **Send an Email**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  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);
    return;
  }

  console.log(data); // { id: '49a3999c-...' }
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ### Idempotency

  Best practice: Add an idempotency key to prevent duplicated emails, which is useful for retrying failed emails safely.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**
  * Pattern: `<event-type>/<entity-id>`
  * Example: `welcome-user/123456789`

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Hello World',
    html: '<strong>It works!</strong>',
    idempotencyKey: 'unique-id',
  });
  ```

  ***

  ## **2. Complete `emails.send()` Parameter Reference**

  ### **Required Parameters**

  | Parameter | Type                 | Description                                                                      |
  | --------- | -------------------- | -------------------------------------------------------------------------------- |
  | `from`    | `string`             | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `to`      | `string \| string[]` | Recipient email address(es). Maximum 50 addresses.                               |
  | `subject` | `string`             | Email subject line.                                                              |

  ### **Content Parameters (at least one required)**

  | Parameter | Type              | Description                                                |
  | --------- | ----------------- | ---------------------------------------------------------- |
  | `html`    | `string`          | HTML version of the email body.                            |
  | `text`    | `string`          | Plain text version. Auto-generated from `html` if omitted. |
  | `react`   | `React.ReactNode` | React Email component to render the message. Node.js only. |

  ### **Optional Parameters**

  | Parameter     | Type                 | Description                                                   |
  | ------------- | -------------------- | ------------------------------------------------------------- |
  | `cc`          | `string \| string[]` | Carbon copy recipients.                                       |
  | `bcc`         | `string \| string[]` | Blind carbon copy recipients.                                 |
  | `replyTo`     | `string \| string[]` | Reply-to address(es).                                         |
  | `scheduledAt` | `string`             | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `headers`     | `object`             | Custom email headers as key-value pairs.                      |
  | `tags`        | `Tag[]`              | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `attachments` | `Attachment[]`       | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Parameters**

  | Parameter            | Type     | Description                                                      |
  | -------------------- | -------- | ---------------------------------------------------------------- |
  | `template.id`        | `string` | Published template identifier.                                   |
  | `template.variables` | `object` | Variable substitutions. Key max 50 chars, value max 2,000 chars. |

  If `template` is provided, do not include `html`, `text`, or `react`.

  ### **Response**

  A successful call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: { id: string }, error: null }
  ```

  A failed call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: null, error: { message: string, name: string } }
  ```

  ***

  ## **3. Sending with React Email**

  Resend integrates with [React Email](https://react.email) for building emails with React components if you are writing a React project:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { WelcomeEmail } from './emails/welcome';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    react: WelcomeEmail({ name: 'John' }),
  });
  ```

  **Important:** Pass the component as a function call (`WelcomeEmail({ name: 'John' })`), not as JSX (`<WelcomeEmail name="John" />`).

  For additional help, suggest installing the react-email skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/react-email
  ```

  ***

  ## **4. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **4.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key in an environment variable** (`RESEND_API_KEY`). Never hardcode API keys.
  2. **Import from `resend`** — the package name is `resend`, the class is `Resend`.
  3. **Use `await`** — `resend.emails.send()` returns a Promise. Always use `async/await` or `.then()`.
  4. **Handle both `data` and `error`** — the SDK returns `{ data, error }`. Always check for errors.
  5. **Use a verified domain** in the `from` address for production. `onboarding@resend.dev` is for testing only.
  6. **Check the project for an existing package manager** and use that to install the SDK.
  7. **Use camelCase** for SDK parameters (`replyTo`, `scheduledAt`), not snake\_case.

  ### **4.2 - NEVER DO THE FOLLOWING**

  1. **Do not** hardcode API keys in source code. Always use environment variables.
  2. **Do not** use `try/catch` for error handling with `resend.emails.send()` — the SDK returns `{ data, error }` instead of throwing. Only use `try/catch` if you need to handle network-level failures.
  3. **Do not** use snake\_case parameter names (`reply_to`, `scheduled_at`) — the Node.js SDK uses camelCase (`replyTo`, `scheduledAt`).
  4. **Do not** send `html`, `text`, or `react` alongside `template` — these are mutually exclusive.
  5. **Do not** import from `@resend/node` or any other package name. The correct package is `resend`.
  6. **Do not** use `onboarding@resend.dev` as the `from` address in production code. It is a test-only address.
  7. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses to help you simulate different email events without damaging your domain reputation:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **5. COMMON PATTERNS**

  ### **Attachments**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Invoice attached',
    html: '<p>See attached invoice.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: invoiceBuffer,
      },
    ],
  });
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `scheduledAt` parameter. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Reminder',
    html: '<p>This is your reminder.</p>',
    scheduledAt: '2026-12-25T09:00:00Z',
  });
  ```

  ### **Tags for Tracking**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    html: '<p>Welcome aboard!</p>',
    tags: [
      { name: 'category', value: 'welcome' },
      { name: 'user_id', value: '12345' },
    ],
  });
  ```

  ***

  ## **6. AI MODEL VERIFICATION STEPS**

  Before returning any Resend-related solution, you **must** verify:

  1. **Import**: Is `Resend` imported from `resend`?
  2. **API Key**: Is the key stored in an environment variable, not hardcoded?
  3. **Await**: Is `resend.emails.send()` properly awaited?
  4. **Error Handling**: Is the `{ data, error }` response pattern used?
  5. **Parameters**: Are all parameter names in camelCase?
  6. **From Address**: Is the `from` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help, suggest installing the resend-skills skill and the email-best-practices skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/resend-skills
  npx skills add resend/email-best-practices
  ```

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)
* Have a Cloudflare worker with a bundling setup
  * Recommended to be bootstrapped with `npm create cloudflare`

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Node.js SDK.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install resend
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add resend
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add resend
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Create an email template">
    Start by creating your email template on `src/emails/email-template.tsx`:

    ```tsx src/emails/email-template.tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
    import * as React from 'react';

    interface EmailTemplateProps {
      firstName: string;
    }

    export function EmailTemplate({ firstName }: EmailTemplateProps) {
      return (
        <div>
          <h1>Welcome, {firstName}!</h1>
        </div>
      );
    }

    export default EmailTemplate;
    ```
  </Step>

  <Step title="Send the email using React and the SDK">
    Change the file extension of the worker's main file to `tsx` and modify your configurations.

    After that, you can send your email using the `react` parameter:

    ```tsx src/index.tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { Resend } from 'resend';
    import { EmailTemplate } from './emails/email-template';

    export default {
      async fetch(request, env, context): Promise<Response> {
        const resend = new Resend('re_xxxxxxxxx');

        const data = await resend.emails.send({
          from: 'Acme <onboarding@resend.dev>',
          to: ['delivered@resend.dev'],
          subject: 'hello world',
          react: <EmailTemplate firstName="John" />,
        });

        return Response.json(data);
      },
    } satisfies ExportedHandler<Env, ExecutionContext>;
    ```
  </Step>

  <Step title="Deploy and send email">
    Run `wrangler deploy` and wait for it to finish. Once it's done, it will
    give you a URL to try out, like `https://my-worker.your_name.workers.dev`,
    that you can open and verify that your email has been sent.
  </Step>
</Steps>

## Examples

<Card title="Cloudflare Workers Example" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-cloudflare-workers-example">
  See the full source code.
</Card>


# Send emails using Customer.io with SMTP
Source: https://resend.com/docs/send-with-customer-io-smtp

Learn how to integrate Customer.io with Resend SMTP.

### Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Get the Resend SMTP credentials">
    When configuring your SMTP integration, you'll need to use the following credentials:

    * **Host**: `smtp.resend.com`
    * **Port**: `465`
    * **Username**: `resend`
    * **Password**: `YOUR_API_KEY`
  </Step>

  <Step title="Integrate with Customer.io SMTP">
    After logging into your [Customer.io](https://customer.io) account, you'll need to enable the SMTP integration.

    1. Go to **Settings** > **Workspace Settings**.

    <img alt="Customer.io SMTP - Workspace Settings" />

    2. Go to the Messaging tab and select **Email**.

    <img alt="Customer.io SMTP - Email" />

    3. Select the **Custom SMTP** tab and click **Add Custom SMTP Server**.

    <img alt="Customer.io SMTP - Add Custom SMTP Server" />

    4. Select **Other SMTP** and click **Continue to set up**.

    <img alt="Customer.io SMTP - Other SMTP" />

    5. Copy-and-paste the SMTP credentials from Resend to Customer.io.

    <img alt="Customer.io SMTP integration" />
  </Step>
</Steps>


# Send emails with Deno Deploy
Source: https://resend.com/docs/send-with-deno-deploy

Learn how to send your first email using Deno Deploy.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Create a Deno Deploy project">
    Go to [dash.deno.com/projects](https://dash.deno.com/projects) and create a new playground project.

    <img alt="Deno Deploy - New Project" />
  </Step>

  <Step title="Edit the handler function">
    Paste the following code into the browser editor:

    ```ts main.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { Resend } from 'npm:resend';

    const resend = new Resend('re_123456789');

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

        return new Response(JSON.stringify(response), {
          status: response.error ? 500 : 200,
          headers: {
            'Content-Type': 'application/json',
          },
        });
      } catch (error) {
        console.error(error);
        return new Response(null, {
          status: 500,
        });
      }
    });
    ```
  </Step>

  <Step title="Deploy and send email">
    Click on `Save & Deploy` at the top of the screen.

    <img alt="Deno Deploy - Playground" />
  </Step>
</Steps>

## Examples

<Card title="Deno Deploy Example" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-deno-deploy-example">
  See the full source code.
</Card>


# Send emails with Django
Source: https://resend.com/docs/send-with-django

Learn how to send your first email using Django and the Resend Python SDK.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the [django-anymail](https://anymail.dev/en/stable/esps/resend/) package with Resend support.

    <CodeGroup>
      ```bash Pip theme={"theme":{"light":"github-light","dark":"vesper"}}
      pip install django-anymail[resend]
      ```
    </CodeGroup>
  </Step>

  <Step title="Configure">
    Add Anymail to your Django settings.

    ```py settings.py theme={"theme":{"light":"github-light","dark":"vesper"}}
    import os

    INSTALLED_APPS = [
        # ...
        "anymail",
    ]

    EMAIL_BACKEND = "anymail.backends.resend.EmailBackend"
    ANYMAIL = {
        "RESEND_API_KEY": os.environ.get("RESEND_API_KEY"),
    }
    DEFAULT_FROM_EMAIL = "onboarding@resend.dev"
    ```
  </Step>

  <Step title="Send email using HTML">
    The easiest way to send an email is by using the `html_message` parameter.

    ```py views.py theme={"theme":{"light":"github-light","dark":"vesper"}}
    from django.core.mail import send_mail
    from django.http import JsonResponse

    def send_email(request):
        send_mail(
            subject="Hello from Django + Resend",
            message="This is a plain text message.",
            from_email="Acme <onboarding@resend.dev>",
            recipient_list=["delivered@resend.dev"],
            html_message="<strong>it works!</strong>",
        )

        return JsonResponse({"message": "Email sent successfully"})
    ```
  </Step>

  <Step title="Send email using a template">
    For more complex emails, you can use Django's template system.

    First, create an HTML template at `templates/emails/welcome.html`:

    ```html templates/emails/welcome.html theme={"theme":{"light":"github-light","dark":"vesper"}}
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>Welcome Email</title>
      </head>
      <body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
        <h1>Welcome, {{ user_name }}!</h1>
        <p>Thank you for joining our service.</p>
        <p>Your account email: <strong>{{ user_email }}</strong></p>
        <p>
          <a
            href="{{ dashboard_url }}"
            style="background-color: #007bff; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px;"
          >
            Go to Dashboard
          </a>
        </p>
      </body>
    </html>
    ```

    Then render and send the template:

    ```py views.py theme={"theme":{"light":"github-light","dark":"vesper"}}
    from django.core.mail import EmailMessage
    from django.http import JsonResponse
    from django.template.loader import render_to_string

    def send_template_email(request):
        html_content = render_to_string('emails/welcome.html', {
            'user_name': 'Django Developer',
            'user_email': 'delivered@resend.dev',
            'dashboard_url': 'https://example.com/dashboard',
        })

        message = EmailMessage(
            subject="Welcome to Our Service!",
            body=html_content,
            from_email="Acme <onboarding@resend.dev>",
            to=["delivered@resend.dev"],
        )
        message.content_subtype = "html"
        message.send()

        return JsonResponse({"message": "Email sent successfully"})
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Django App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/python-resend-examples/django_app">
    Full Django web application
  </Card>

  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/basic_send.py">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/with_attachments.py">
    Send emails with file attachments
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/with_template.py">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/scheduled_send.py">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/audiences.py">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/domains.py">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/inbound.py">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/double_optin_subscribe.py">
    Double opt-in subscription flow
  </Card>
</CardGroup>


# Send emails using Django with SMTP
Source: https://resend.com/docs/send-with-django-smtp

Learn how to integrate Django with Resend SMTP.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)
* Install `virtualenv` by running `pip install virtualenv`

## Guide

<Steps>
  <Step title="Setup your environment">
    Create and activate your new virtualenv.

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    virtualenv venv
    source venv/bin/activate
    ```

    Install dependencies.

    ```sh theme={"theme":{"light":"github-light","dark":"vesper"}}
    pip install -r requirements.txt
    ```

    Set your `RESEND_API_KEY` environment variable by running.

    ```sh theme={"theme":{"light":"github-light","dark":"vesper"}}
    export RESEND_API_KEY="re_xxxxxxxxx"
    ```
  </Step>

  <Step title="Send email using Django's SMTP EmailMessage">
    Set the necessary attributes in your `settings.py` file.

    ```py theme={"theme":{"light":"github-light","dark":"vesper"}}
    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
    RESEND_SMTP_PORT = 587
    RESEND_SMTP_USERNAME = 'resend'
    RESEND_SMTP_HOST = 'smtp.resend.com'
    ```

    Use Django's `get_connection` and `EmailMessage`

    ```py theme={"theme":{"light":"github-light","dark":"vesper"}}
    import os
    from django.conf import settings
    from django.http import JsonResponse
    from django.core.mail import EmailMessage, get_connection

    # Sample Django view
    def index(request):

        subject = "Hello from Django SMTP"
        recipient_list = ["delivered@resend.dev"]
        from_email = "onboarding@resend.dev"
        message = "<strong>it works!</strong>"

        with get_connection(
            host=settings.RESEND_SMTP_HOST,
            port=settings.RESEND_SMTP_PORT,
            username=settings.RESEND_SMTP_USERNAME,
            password=os.environ["RESEND_API_KEY"],
            use_tls=True,
            ) as connection:
                r = EmailMessage(
                      subject=subject,
                      body=message,
                      to=recipient_list,
                      from_email=from_email,
                      connection=connection).send()
        return JsonResponse({"status": "ok"})
    ```
  </Step>
</Steps>

## Examples

<Card title="Django SMTP Example" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-django-smtp-example">
  See the full source code.
</Card>


# Send emails with .NET
Source: https://resend.com/docs/send-with-dotnet

Learn how to send your first email using the Resend .NET SDK.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

Prefer watching a video? Check out our video walkthrough below.

<YouTube />

## Guide

<Steps>
  <Step title="Install">
    <CodeGroup>
      ```bash dotnet CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
      dotnet add package Resend
      ```

      ```bash Visual Studio (Package Manager Console) theme={"theme":{"light":"github-light","dark":"vesper"}}
      PM> Install-Package Resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Send emails using HTML">
    In the startup of your application, configure the DI container as follows:

    ```csharp theme={"theme":{"light":"github-light","dark":"vesper"}}
    using Resend;

    builder.Services.AddOptions();
    builder.Services.AddHttpClient<ResendClient>();
    builder.Services.Configure<ResendClientOptions>( o =>
    {
        o.ApiToken = Environment.GetEnvironmentVariable( "RESEND_APITOKEN" )!;
    } );
    builder.Services.AddTransient<IResend, ResendClient>();
    ```

    Send an email using the injected `IResend` instance:

    ```csharp theme={"theme":{"light":"github-light","dark":"vesper"}}
    using Resend;

    public class FeatureImplementation
    {
        private readonly IResend _resend;


        public FeatureImplementation( IResend resend )
        {
            _resend = resend;
        }


        public Task Execute()
        {
            var message = new EmailMessage();
            message.From = "Acme <onboarding@resend.dev>";
            message.To.Add( "delivered@resend.dev" );
            message.Subject = "hello world";
            message.HtmlBody = "<strong>it works!</strong>";

            await _resend.EmailSendAsync( message );
        }
    }
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/BasicSend.cs">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/WithAttachments.cs">
    Send emails with file attachments
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/WithTemplate.cs">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/ScheduledSend.cs">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/Audiences.cs">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/Domains.cs">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/Inbound.cs">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/dotnet-resend-examples/Examples/DoubleOptinSubscribe.cs">
    Double opt-in subscription flow
  </Card>

  <Card title="Minimal API App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/dotnet-resend-examples/MinimalApiApp">
    ASP.NET Minimal API application
  </Card>

  <Card title="MVC App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/dotnet-resend-examples/MvcApp">
    ASP.NET MVC application
  </Card>
</CardGroup>


# Send emails with Elixir
Source: https://resend.com/docs/send-with-elixir

Learn how to send your first email using the Resend Elixir SDK.

<Info>
  This guides utilizes an [open source
  library](https://github.com/elixir-saas/resend-elixir) contributed by a
  community member. It's not developed, maintained, or supported by Resend
  directly.
</Info>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Install by adding `resend` to your list of dependencies in `mix.exs`:

    <CodeGroup>
      ```elixir mix.exs theme={"theme":{"light":"github-light","dark":"vesper"}}
      def deps do
        [
          {:resend, "~> 0.4.0"}
        ]
      end
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using HTML">
    The easiest way to send an email is by using the `html` parameter.

    ```elixir send.exs theme={"theme":{"light":"github-light","dark":"vesper"}}
    client = Resend.client(api_key: System.get_env("RESEND_API_KEY"))

    Resend.Emails.send(client, %{
      from: "Acme <onboarding@resend.dev>",
      to: ["delivered@resend.dev"],
      subject: "hello world",
      html: "<strong>it works!</strong>"
    })
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/basic_send.exs">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/with_attachments.exs">
    Send emails with file attachments
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/with_template.exs">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/scheduled_send.exs">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/audiences.exs">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/domains.exs">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/inbound.exs">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/elixir-resend-examples/examples/double_optin">
    Double opt-in subscription flow
  </Card>

  <Card title="Phoenix App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/elixir-resend-examples/phoenix_app">
    Full Phoenix web framework application
  </Card>
</CardGroup>


# Send emails with Encore
Source: https://resend.com/docs/send-with-encore-go

Learn how to send your first email using Encore and the Resend Go SDK.

[Encore](https://encore.dev) is an open-source Go framework that provisions infrastructure directly from your application code, with built-in observability and cloud deployment.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend and Encore Go

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using [Resend](https://resend.com/) with the [Encore Go](https://encore.dev) backend framework.
  **Scope:** All AI-generated advice or code related to sending email with Resend inside an Encore Go application must follow these guardrails.

  ***

  ## **1. Official Resend + Encore Go Setup**

  ### **Prerequisites**

  Human must first:

  * Install [Encore](https://encore.dev/docs/go/install) (`brew install encoredev/tap/encore` or `curl -L https://encore.dev/install.sh | bash`)
  * Create a Resend API key at [https://resend.com/api-keys](https://resend.com/api-keys)
  * Verify a sending domain at [https://resend.com/domains](https://resend.com/domains)

  The API key must be stored as an **Encore secret** (not an environment variable or `.env` file):

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  encore secret set --type dev,local,pr,production ResendAPIKey
  ```

  ### **Install the SDK**

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  go get github.com/resend/resend-go/v3
  ```

  ### **Define Secrets**

  Encore Go uses an unexported `secrets` struct to securely inject secrets at runtime. Do not use `os.Getenv()`.

  ```go theme={"theme":{"light":"github-light","dark":"vesper"}}
  var secrets struct {
      ResendAPIKey string
  }
  ```

  ### **Initialize the Client and Send an Email**

  ```go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package email

  import (
      "context"

      "github.com/resend/resend-go/v3"
  )

  var secrets struct {
      ResendAPIKey string
  }

  type SendRequest struct {
      To      string `json:"to"`
      Subject string `json:"subject"`
      HTML    string `json:"html"`
  }

  type SendResponse struct {
      ID string `json:"id"`
  }

  //encore:api public method=POST path=/email/send
  func Send(ctx context.Context, req *SendRequest) (*SendResponse, error) {
      client := resend.NewClient(secrets.ResendAPIKey)

      sent, err := client.Emails.Send(&resend.SendEmailRequest{
          From:    "Acme <onboarding@resend.dev>",
          To:      []string{req.To},
          Subject: req.Subject,
          Html:    req.HTML,
      })
      if err != nil {
          return nil, err
      }

      return &SendResponse{ID: sent.Id}, nil
  }
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ***

  ## **2. Complete `SendEmailRequest` Field Reference**

  ### **Required Fields**

  | Field     | Type       | Description                                                                      |
  | --------- | ---------- | -------------------------------------------------------------------------------- |
  | `From`    | `string`   | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `To`      | `[]string` | Recipient email address(es). Maximum 50 addresses.                               |
  | `Subject` | `string`   | Email subject line.                                                              |

  ### **Content Fields (at least one required)**

  | Field  | Type     | Description                                                |
  | ------ | -------- | ---------------------------------------------------------- |
  | `Html` | `string` | HTML version of the email body.                            |
  | `Text` | `string` | Plain text version. Auto-generated from `Html` if omitted. |

  ### **Optional Fields**

  | Field         | Type                | Description                                                   |
  | ------------- | ------------------- | ------------------------------------------------------------- |
  | `Cc`          | `[]string`          | Carbon copy recipients.                                       |
  | `Bcc`         | `[]string`          | Blind carbon copy recipients.                                 |
  | `ReplyTo`     | `string`            | Reply-to address.                                             |
  | `ScheduledAt` | `string`            | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `Headers`     | `map[string]string` | Custom email headers as key-value pairs.                      |
  | `Tags`        | `[]Tag`             | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `Attachments` | `[]*Attachment`     | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Fields**

  | Field      | Type             | Description                |
  | ---------- | ---------------- | -------------------------- |
  | `Template` | `*EmailTemplate` | Published template to use. |

  If `Template` is provided, do not include `Html` or `Text`.

  ### **Response**

  A successful call returns:

  ```go theme={"theme":{"light":"github-light","dark":"vesper"}}
  &SendEmailResponse{Id: "49a3999c-..."}
  ```

  A failed call returns an `error`.

  ***

  ## **3. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **3.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key as an Encore secret** using `encore secret set`. Access it via `var secrets struct { ResendAPIKey string }`. Never use `os.Getenv()` or `.env` files.
  2. **Import from `github.com/resend/resend-go/v3`** — the current version is v3.
  3. **Use `resend.NewClient(secrets.ResendAPIKey)`** to create the client.
  4. **Use `//encore:api` annotations** to define HTTP endpoints — not `net/http`, Gin, Chi, or any other router.
  5. **Check the `error` return value** from `client.Emails.Send()`.
  6. **Use a verified domain** in the `From` address for production. `onboarding@resend.dev` is for testing only.
  7. **Use exported field names** (`From`, `To`, `Html`, `ReplyTo`) — Go structs use PascalCase.

  ### **3.2 - NEVER DO THE FOLLOWING**

  1. **Do not** use `os.Getenv("RESEND_API_KEY")` or `.env` files — Encore has its own secrets management.
  2. **Do not** hardcode API keys in source code.
  3. **Do not** import from `github.com/resend/resend-go` (v1) or `github.com/resend/resend-go/v2` — use v3.
  4. **Do not** use `net/http`, Gin, Chi, Echo, or any other HTTP framework — Encore Go provides its own API routing via `//encore:api` annotations.
  5. **Do not** use `onboarding@resend.dev` as the `From` address in production code. It is a test-only address.
  6. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **4. COMMON PATTERNS**

  ### **Attachments**

  ```go theme={"theme":{"light":"github-light","dark":"vesper"}}
  sent, err := client.Emails.Send(&resend.SendEmailRequest{
      From:    "Acme <hello@example.com>",
      To:      []string{"delivered@resend.dev"},
      Subject: "Invoice attached",
      Html:    "<p>See attached invoice.</p>",
      Attachments: []*resend.Attachment{
          {
              Filename: "invoice.pdf",
              Content:  invoiceBytes,
          },
      },
  })
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `ScheduledAt` field. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```go theme={"theme":{"light":"github-light","dark":"vesper"}}
  sent, err := client.Emails.Send(&resend.SendEmailRequest{
      From:        "Acme <hello@example.com>",
      To:          []string{"delivered@resend.dev"},
      Subject:     "Reminder",
      Html:        "<p>This is your reminder.</p>",
      ScheduledAt: "2026-12-25T09:00:00Z",
  })
  ```

  ### **Tags for Tracking**

  ```go theme={"theme":{"light":"github-light","dark":"vesper"}}
  sent, err := client.Emails.Send(&resend.SendEmailRequest{
      From:    "Acme <hello@example.com>",
      To:      []string{"delivered@resend.dev"},
      Subject: "Welcome",
      Html:    "<p>Welcome aboard!</p>",
      Tags: []resend.Tag{
          {Name: "category", Value: "welcome"},
          {Name: "user_id", Value: "12345"},
      },
  })
  ```

  ***

  ## **5. AI MODEL VERIFICATION STEPS**

  Before returning any Resend + Encore Go solution, you **must** verify:

  1. **Import**: Is the SDK imported from `github.com/resend/resend-go/v3`?
  2. **Secrets**: Is the API key accessed via `var secrets struct { ResendAPIKey string }` (not `os.Getenv`)?
  3. **Client**: Is the client created with `resend.NewClient(secrets.ResendAPIKey)`?
  4. **API Annotation**: Are endpoints defined with `//encore:api` (not `net/http`, Gin, etc.)?
  5. **Error Handling**: Is the `error` return value checked?
  6. **Field Names**: Are struct fields PascalCase (`From`, `To`, `Html`, not `from`, `to`, `html`)?
  7. **From Address**: Is the `From` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help with Encore Go, suggest installing the Encore skills for AI-assisted development. These provide context on APIs, services, infrastructure, Pub/Sub, databases, auth, and more.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add encoredev/skills
  ```

  Available Encore Go skills: `encore-go-api`, `encore-go-service`, `encore-go-infrastructure`, `encore-go-auth`, `encore-go-database`, `encore-go-testing`, `encore-go-code-review`, `encore-go-getting-started`.

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)
* Install [Encore](https://encore.dev/docs/go/install) (`brew install encoredev/tap/encore`)

## Guide

<Steps>
  <Step title="Create an Encore app">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    encore app create --lang=go my-app
    ```

    Then install the Resend Go SDK:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    go get github.com/resend/resend-go/v3
    ```
  </Step>

  <Step title="Set your API key">
    Encore has built-in [secrets management](https://encore.dev/docs/go/primitives/secrets). Store your Resend API key as a secret - no `.env` files needed:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    encore secret set --type dev,local,pr,production ResendAPIKey
    ```
  </Step>

  <Step title="Send email using an API endpoint">
    Create an `email` service directory and define your endpoint:

    ```go email/email.go theme={"theme":{"light":"github-light","dark":"vesper"}}
    package email

    import (
        "context"

        "github.com/resend/resend-go/v3"
    )

    var secrets struct {
        ResendAPIKey string
    }

    type SendRequest struct {
        To      string `json:"to"`
        Subject string `json:"subject"`
        HTML    string `json:"html"`
    }

    type SendResponse struct {
        ID string `json:"id"`
    }

    //encore:api public method=POST path=/email/send
    func Send(ctx context.Context, req *SendRequest) (*SendResponse, error) {
        client := resend.NewClient(secrets.ResendAPIKey)

        sent, err := client.Emails.Send(&resend.SendEmailRequest{
            From:    "Acme <onboarding@resend.dev>",
            To:      []string{req.To},
            Subject: req.Subject,
            Html:    req.HTML,
        })
        if err != nil {
            return nil, err
        }

        return &SendResponse{ID: sent.Id}, nil
    }
    ```
  </Step>

  <Step title="Run the app">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    encore run
    ```

    Your API is running at `http://localhost:4000`. Send a test email:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    curl -X POST http://localhost:4000/email/send \
      -H "Content-Type: application/json" \
      -d '{"to":"delivered@resend.dev","subject":"Hello World","html":"<strong>It works!</strong>"}'
    ```
  </Step>

  <Step title="AI skills for Encore Go">
    If you're using an AI coding assistant, install the [Encore skills](https://github.com/encoredev/skills). They provide context-aware help with topics such as APIs, services, Pub/Sub, databases, and auth:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    npx skills add encoredev/skills
    ```
  </Step>
</Steps>

# Examples

<CardGroup>
  <Card title="Encore Go Docs" icon="arrow-up-right-from-square" href="https://encore.dev/docs/go">
    Encore Go documentation
  </Card>

  <Card title="Resend Go SDK" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-go">
    Resend Go SDK on GitHub
  </Card>
</CardGroup>


# Send emails with Encore
Source: https://resend.com/docs/send-with-encore-ts

Learn how to send your first email using Encore and the Resend Node.js SDK.

[Encore](https://encore.dev) is an open-source TypeScript framework that provisions infrastructure directly from your application code, with built-in observability and cloud deployment.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend and Encore.ts

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using [Resend](https://resend.com/) with the [Encore.ts](https://encore.dev) backend framework.
  **Scope:** All AI-generated advice or code related to sending email with Resend inside an Encore.ts application must follow these guardrails.

  ***

  ## **1. Official Resend + Encore.ts Setup**

  ### **Prerequisites**

  Human must first:

  * Install [Encore](https://encore.dev/docs/ts/install) (`brew install encoredev/tap/encore` or `curl -L https://encore.dev/install.sh | bash`)
  * Create a Resend API key at [https://resend.com/api-keys](https://resend.com/api-keys)
  * Verify a sending domain at [https://resend.com/domains](https://resend.com/domains)

  The API key must be stored as an **Encore secret** (not an environment variable or `.env` file):

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  encore secret set --type dev,local,pr,production ResendAPIKey
  ```

  ### **Install the SDK**

  Use the project's existing package manager to install the Resend Node.js SDK.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  # or: yarn add resend / pnpm add resend
  ```

  ### **Initialize the Client**

  Encore.ts uses `secret()` from `encore.dev/config` to securely inject secrets at runtime. Do not use `process.env`.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { secret } from 'encore.dev/config';

  const resendApiKey = secret('ResendAPIKey');

  export const resend = new Resend(resendApiKey());
  ```

  ### **Define a Service**

  Every Encore.ts service needs an `encore.service.ts` file:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Service } from 'encore.dev/service';

  export default new Service('email');
  ```

  ### **Send an Email**

  Create a type-safe API endpoint using Encore's `api()` function:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { api } from 'encore.dev/api';
  import { resend } from './resend';

  interface SendRequest {
    to: string;
    subject: string;
    html: string;
  }

  interface SendResponse {
    id: string;
  }

  export const sendEmail = api(
    { expose: true, method: 'POST', path: '/email/send' },
    async (req: SendRequest): Promise<SendResponse> => {
      const { data, error } = await resend.emails.send({
        from: 'Your App <hello@example.com>',
        to: req.to,
        subject: req.subject,
        html: req.html,
      });

      if (error) {
        throw new Error(`Failed to send email: ${error.message}`);
      }

      return { id: data!.id };
    },
  );
  ```

  ### **Async Delivery with Pub/Sub**

  For production, use Encore's built-in [Pub/Sub](https://encore.dev/docs/ts/primitives/pubsub) to send emails asynchronously with automatic retries:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Topic, Subscription } from 'encore.dev/pubsub';
  import { resend } from './resend';

  interface EmailEvent {
    to: string;
    subject: string;
    html: string;
  }

  export const emailTopic = new Topic<EmailEvent>('emails', {
    deliveryGuarantee: 'at-least-once',
  });

  const _ = new Subscription(emailTopic, 'send-email', {
    handler: async (event) => {
      const { data, error } = await resend.emails.send({
        from: 'Your App <hello@example.com>',
        to: event.to,
        subject: event.subject,
        html: event.html,
      });

      if (error) {
        throw new Error(error.message);
      }

      console.log('Email sent:', data?.id);
    },
  });
  ```

  Then publish from any endpoint:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  await emailTopic.publish({
    to: 'user@example.com',
    subject: 'Welcome!',
    html: '<p>Thanks for signing up.</p>',
  });
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ### Idempotency

  Best practice: Add an idempotency key to prevent duplicated emails, which is useful for retrying failed emails safely.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**
  * Pattern: `<event-type>/<entity-id>`
  * Example: `welcome-user/123456789`

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Hello World',
    html: '<strong>It works!</strong>',
    idempotencyKey: 'unique-id',
  });
  ```

  ***

  ## **2. Complete `emails.send()` Parameter Reference**

  ### **Required Parameters**

  | Parameter | Type                 | Description                                                                      |
  | --------- | -------------------- | -------------------------------------------------------------------------------- |
  | `from`    | `string`             | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `to`      | `string \| string[]` | Recipient email address(es). Maximum 50 addresses.                               |
  | `subject` | `string`             | Email subject line.                                                              |

  ### **Content Parameters (at least one required)**

  | Parameter | Type              | Description                                                |
  | --------- | ----------------- | ---------------------------------------------------------- |
  | `html`    | `string`          | HTML version of the email body.                            |
  | `text`    | `string`          | Plain text version. Auto-generated from `html` if omitted. |
  | `react`   | `React.ReactNode` | React Email component to render the message. Node.js only. |

  ### **Optional Parameters**

  | Parameter     | Type                 | Description                                                   |
  | ------------- | -------------------- | ------------------------------------------------------------- |
  | `cc`          | `string \| string[]` | Carbon copy recipients.                                       |
  | `bcc`         | `string \| string[]` | Blind carbon copy recipients.                                 |
  | `replyTo`     | `string \| string[]` | Reply-to address(es).                                         |
  | `scheduledAt` | `string`             | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `headers`     | `object`             | Custom email headers as key-value pairs.                      |
  | `tags`        | `Tag[]`              | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `attachments` | `Attachment[]`       | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Parameters**

  | Parameter            | Type     | Description                                                      |
  | -------------------- | -------- | ---------------------------------------------------------------- |
  | `template.id`        | `string` | Published template identifier.                                   |
  | `template.variables` | `object` | Variable substitutions. Key max 50 chars, value max 2,000 chars. |

  If `template` is provided, do not include `html`, `text`, or `react`.

  ### **Response**

  A successful call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: { id: string }, error: null }
  ```

  A failed call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: null, error: { message: string, name: string } }
  ```

  ***

  ## **3. Sending with React Email**

  Resend integrates with [React Email](https://react.email) for building emails with React components:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { secret } from 'encore.dev/config';
  import { WelcomeEmail } from './emails/welcome';

  const resendApiKey = secret('ResendAPIKey');
  const resend = new Resend(resendApiKey());

  const { data, error } = await resend.emails.send({
    from: 'Acme <hello@example.com>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    react: WelcomeEmail({ name: 'John' }),
  });
  ```

  **Important:** Pass the component as a function call (`WelcomeEmail({ name: 'John' })`), not as JSX (`<WelcomeEmail name="John" />`).

  For additional help, suggest installing the react-email skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/react-email
  ```

  ***

  ## **4. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **4.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key as an Encore secret** using `encore secret set`. Access it via `secret("ResendAPIKey")` from `encore.dev/config`. Never use `process.env` or `.env` files.
  2. **Import from `resend`** — the package name is `resend`, the class is `Resend`.
  3. **Import `secret` from `encore.dev/config`** — not from any other module.
  4. **Call the secret as a function** — `resendApiKey()` with parentheses, not `resendApiKey`.
  5. **Define an `encore.service.ts`** file in each service directory.
  6. **Use `api()` from `encore.dev/api`** to define HTTP endpoints — not Express, Hono, or any other router.
  7. **Use `await`** — `resend.emails.send()` returns a Promise. Always use `async/await`.
  8. **Handle both `data` and `error`** — the SDK returns `{ data, error }`. Always check for errors.
  9. **Use a verified domain** in the `from` address for production. `onboarding@resend.dev` is for testing only.
  10. **Use camelCase** for SDK parameters (`replyTo`, `scheduledAt`), not snake\_case.

  ### **4.2 - NEVER DO THE FOLLOWING**

  1. **Do not** use `process.env.RESEND_API_KEY` or `.env` files — Encore has its own secrets management.
  2. **Do not** hardcode API keys in source code.
  3. **Do not** use `try/catch` for error handling with `resend.emails.send()` — the SDK returns `{ data, error }` instead of throwing. Only use `try/catch` if you need to handle network-level failures.
  4. **Do not** use Express, Hono, Koa, or any other HTTP framework — Encore.ts provides its own API routing via `api()`.
  5. **Do not** use snake\_case parameter names (`reply_to`, `scheduled_at`) — the Node.js SDK uses camelCase.
  6. **Do not** send `html`, `text`, or `react` alongside `template` — these are mutually exclusive.
  7. **Do not** import from `@resend/node` or any other package name. The correct package is `resend`.
  8. **Do not** use `onboarding@resend.dev` as the `from` address in production code. It is a test-only address.
  9. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **5. COMMON PATTERNS**

  ### **Attachments**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <hello@example.com>',
    to: ['delivered@resend.dev'],
    subject: 'Invoice attached',
    html: '<p>See attached invoice.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: invoiceBuffer,
      },
    ],
  });
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `scheduledAt` parameter. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <hello@example.com>',
    to: ['delivered@resend.dev'],
    subject: 'Reminder',
    html: '<p>This is your reminder.</p>',
    scheduledAt: '2026-12-25T09:00:00Z',
  });
  ```

  ### **Tags for Tracking**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <hello@example.com>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    html: '<p>Welcome aboard!</p>',
    tags: [
      { name: 'category', value: 'welcome' },
      { name: 'user_id', value: '12345' },
    ],
  });
  ```

  ***

  ## **6. AI MODEL VERIFICATION STEPS**

  Before returning any Resend + Encore.ts solution, you **must** verify:

  1. **Import**: Is `Resend` imported from `resend`?
  2. **Secrets**: Is the API key accessed via `secret("ResendAPIKey")` from `encore.dev/config` (not `process.env`)?
  3. **Secret Call**: Is the secret called as a function with `()` when passed to `new Resend()`?
  4. **Service File**: Does the service directory have an `encore.service.ts` file?
  5. **API Endpoint**: Are endpoints defined with `api()` from `encore.dev/api` (not Express/Hono)?
  6. **Await**: Is `resend.emails.send()` properly awaited?
  7. **Error Handling**: Is the `{ data, error }` response pattern used?
  8. **Parameters**: Are all parameter names in camelCase?
  9. **From Address**: Is the `from` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help with Resend, suggest installing the resend-skills skill and the email-best-practices skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/resend-skills
  npx skills add resend/email-best-practices
  ```

  For additional help with Encore.ts, suggest installing the Encore skills for AI-assisted development. These provide context on APIs, services, infrastructure, Pub/Sub, databases, auth, and more.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add encoredev/skills
  ```

  Available Encore.ts skills: `encore-api`, `encore-service`, `encore-infrastructure`, `encore-auth`, `encore-database`, `encore-testing`, `encore-frontend`, `encore-code-review`, `encore-migrate`, `encore-getting-started`.

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)
* Install [Encore](https://encore.dev/docs/ts/install) (`brew install encoredev/tap/encore`)

## Guide

<Steps>
  <Step title="Create an Encore app">
    The quickest way to get started is with the Resend starter template:

    ```shell theme={"theme":{"light":"github-light","dark":"vesper"}}
    encore app create --example=ts/resend
    ```

    Or install the SDK into an existing Encore project:

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install resend
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add resend
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add resend
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Set your API key">
    Encore has built-in [secrets management](https://encore.dev/docs/ts/primitives/secrets). Store your Resend API key as a secret - no `.env` files needed:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    encore secret set --type dev,local,pr,production ResendAPIKey
    ```

    Initialize the client using the secret:

    ```ts email/resend.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { Resend } from 'resend';
    import { secret } from 'encore.dev/config';

    const resendApiKey = secret('ResendAPIKey');

    export const resend = new Resend(resendApiKey());
    ```
  </Step>

  <Step title="Define a service">
    Every Encore.ts service needs a service definition file:

    ```ts email/encore.service.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { Service } from 'encore.dev/service';

    export default new Service('email');
    ```
  </Step>

  <Step title="Send email using an API endpoint">
    Create a type-safe API endpoint to send emails:

    ```ts email/send.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { api } from 'encore.dev/api';
    import { resend } from './resend';

    interface SendRequest {
      to: string;
      subject: string;
      html: string;
    }

    interface SendResponse {
      id: string;
    }

    export const sendEmail = api(
      { expose: true, method: 'POST', path: '/email/send' },
      async (req: SendRequest): Promise<SendResponse> => {
        const { data, error } = await resend.emails.send({
          from: 'Acme <onboarding@resend.dev>',
          to: req.to,
          subject: req.subject,
          html: req.html,
        });

        if (error) {
          throw new Error(`Failed to send email: ${error.message}`);
        }

        return { id: data!.id };
      },
    );
    ```
  </Step>

  <Step title="Async delivery with Pub/Sub (optional)">
    For production, use Encore's built-in [Pub/Sub](https://encore.dev/docs/ts/primitives/pubsub) to send emails asynchronously with automatic retries:

    ```ts email/topic.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { Topic, Subscription } from 'encore.dev/pubsub';
    import { resend } from './resend';

    interface EmailEvent {
      to: string;
      subject: string;
      html: string;
    }

    export const emailTopic = new Topic<EmailEvent>('emails', {
      deliveryGuarantee: 'at-least-once',
    });

    const _ = new Subscription(emailTopic, 'send-email', {
      handler: async (event) => {
        const { data, error } = await resend.emails.send({
          from: 'Acme <onboarding@resend.dev>',
          to: event.to,
          subject: event.subject,
          html: event.html,
        });

        if (error) {
          throw new Error(error.message);
        }

        console.log('Email sent:', data?.id);
      },
    });
    ```

    Then publish from any endpoint:

    ```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { emailTopic } from './topic';

    await emailTopic.publish({
      to: 'delivered@resend.dev',
      subject: 'Welcome!',
      html: '<p>Thanks for signing up.</p>',
    });
    ```
  </Step>

  <Step title="Run the app">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    encore run
    ```

    Your API is running at `http://localhost:4000`. Send a test email:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    curl -X POST http://localhost:4000/email/send \
      -H "Content-Type: application/json" \
      -d '{"to":"delivered@resend.dev","subject":"Hello World","html":"<strong>It works!</strong>"}'
    ```
  </Step>

  <Step title="AI skills for Encore.ts">
    If you're using an AI coding assistant, install the [Encore skills](https://github.com/encoredev/skills). They provide context-aware help with topics such as APIs, services, Pub/Sub, databases, and auth:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    npx skills add encoredev/skills
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Resend Starter" icon="arrow-up-right-from-square" href="https://github.com/encoredev/examples/tree/main/ts/resend">
    Full example with Pub/Sub email delivery
  </Card>

  <Card title="Encore.ts Docs" icon="arrow-up-right-from-square" href="https://encore.dev/docs/ts">
    Encore.ts documentation
  </Card>
</CardGroup>


# Send emails with Express
Source: https://resend.com/docs/send-with-express

Learn how to send your first email using Express and the Resend Node.js SDK.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend Node.js SDK

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using the [Resend](https://resend.com/) Node.js SDK.
  **Scope:** All AI-generated advice or code related to sending email with Resend must follow these guardrails.

  ***

  ## **1. Official Resend Node.js Setup**

  ### **Prerequisites**

  Human must first create an API key and verify their domain at [https://resend.com/domains](https://resend.com/domains).

  The API key must be stored in an environment variable called `RESEND_API_KEY`.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  The domain should be verified at [https://resend.com/domains](https://resend.com/domains) and added to the `from` address.

  ### **Install the SDK**

  Use the project's existing package manager to install the Resend Node.js SDK.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  # or: yarn add resend / pnpm add resend / bun add resend
  ```

  ### **Initialize the Client**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  ### **Send an Email**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  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);
    return;
  }

  console.log(data); // { id: '49a3999c-...' }
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ### Idempotency

  Best practice: Add an idempotency key to prevent duplicated emails, which is useful for retrying failed emails safely.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**
  * Pattern: `<event-type>/<entity-id>`
  * Example: `welcome-user/123456789`

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Hello World',
    html: '<strong>It works!</strong>',
    idempotencyKey: 'unique-id',
  });
  ```

  ***

  ## **2. Complete `emails.send()` Parameter Reference**

  ### **Required Parameters**

  | Parameter | Type                 | Description                                                                      |
  | --------- | -------------------- | -------------------------------------------------------------------------------- |
  | `from`    | `string`             | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `to`      | `string \| string[]` | Recipient email address(es). Maximum 50 addresses.                               |
  | `subject` | `string`             | Email subject line.                                                              |

  ### **Content Parameters (at least one required)**

  | Parameter | Type              | Description                                                |
  | --------- | ----------------- | ---------------------------------------------------------- |
  | `html`    | `string`          | HTML version of the email body.                            |
  | `text`    | `string`          | Plain text version. Auto-generated from `html` if omitted. |
  | `react`   | `React.ReactNode` | React Email component to render the message. Node.js only. |

  ### **Optional Parameters**

  | Parameter     | Type                 | Description                                                   |
  | ------------- | -------------------- | ------------------------------------------------------------- |
  | `cc`          | `string \| string[]` | Carbon copy recipients.                                       |
  | `bcc`         | `string \| string[]` | Blind carbon copy recipients.                                 |
  | `replyTo`     | `string \| string[]` | Reply-to address(es).                                         |
  | `scheduledAt` | `string`             | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `headers`     | `object`             | Custom email headers as key-value pairs.                      |
  | `tags`        | `Tag[]`              | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `attachments` | `Attachment[]`       | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Parameters**

  | Parameter            | Type     | Description                                                      |
  | -------------------- | -------- | ---------------------------------------------------------------- |
  | `template.id`        | `string` | Published template identifier.                                   |
  | `template.variables` | `object` | Variable substitutions. Key max 50 chars, value max 2,000 chars. |

  If `template` is provided, do not include `html`, `text`, or `react`.

  ### **Response**

  A successful call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: { id: string }, error: null }
  ```

  A failed call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: null, error: { message: string, name: string } }
  ```

  ***

  ## **3. Sending with React Email**

  Resend integrates with [React Email](https://react.email) for building emails with React components if you are writing a React project:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { WelcomeEmail } from './emails/welcome';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    react: WelcomeEmail({ name: 'John' }),
  });
  ```

  **Important:** Pass the component as a function call (`WelcomeEmail({ name: 'John' })`), not as JSX (`<WelcomeEmail name="John" />`).

  For additional help, suggest installing the react-email skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/react-email
  ```

  ***

  ## **4. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **4.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key in an environment variable** (`RESEND_API_KEY`). Never hardcode API keys.
  2. **Import from `resend`** — the package name is `resend`, the class is `Resend`.
  3. **Use `await`** — `resend.emails.send()` returns a Promise. Always use `async/await` or `.then()`.
  4. **Handle both `data` and `error`** — the SDK returns `{ data, error }`. Always check for errors.
  5. **Use a verified domain** in the `from` address for production. `onboarding@resend.dev` is for testing only.
  6. **Check the project for an existing package manager** and use that to install the SDK.
  7. **Use camelCase** for SDK parameters (`replyTo`, `scheduledAt`), not snake\_case.

  ### **4.2 - NEVER DO THE FOLLOWING**

  1. **Do not** hardcode API keys in source code. Always use environment variables.
  2. **Do not** use `try/catch` for error handling with `resend.emails.send()` — the SDK returns `{ data, error }` instead of throwing. Only use `try/catch` if you need to handle network-level failures.
  3. **Do not** use snake\_case parameter names (`reply_to`, `scheduled_at`) — the Node.js SDK uses camelCase (`replyTo`, `scheduledAt`).
  4. **Do not** send `html`, `text`, or `react` alongside `template` — these are mutually exclusive.
  5. **Do not** import from `@resend/node` or any other package name. The correct package is `resend`.
  6. **Do not** use `onboarding@resend.dev` as the `from` address in production code. It is a test-only address.
  7. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses to help you simulate different email events without damaging your domain reputation:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **5. COMMON PATTERNS**

  ### **Attachments**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Invoice attached',
    html: '<p>See attached invoice.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: invoiceBuffer,
      },
    ],
  });
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `scheduledAt` parameter. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Reminder',
    html: '<p>This is your reminder.</p>',
    scheduledAt: '2026-12-25T09:00:00Z',
  });
  ```

  ### **Tags for Tracking**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    html: '<p>Welcome aboard!</p>',
    tags: [
      { name: 'category', value: 'welcome' },
      { name: 'user_id', value: '12345' },
    ],
  });
  ```

  ***

  ## **6. AI MODEL VERIFICATION STEPS**

  Before returning any Resend-related solution, you **must** verify:

  1. **Import**: Is `Resend` imported from `resend`?
  2. **API Key**: Is the key stored in an environment variable, not hardcoded?
  3. **Await**: Is `resend.emails.send()` properly awaited?
  4. **Error Handling**: Is the `{ data, error }` response pattern used?
  5. **Parameters**: Are all parameter names in camelCase?
  6. **From Address**: Is the `from` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help, suggest installing the resend-skills skill and the email-best-practices skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/resend-skills
  npx skills add resend/email-best-practices
  ```

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Node.js SDK.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install resend
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add resend
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add resend
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using HTML">
    The easiest way to send an email is by using the `html` parameter.

    ```js server.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import express, { Request, Response } from "express";
    import { Resend } from "resend";

    const app = express();
    const resend = new Resend("re_xxxxxxxxx");

    app.get("/", async (req: Request, res: Response) => {
      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) {
        return res.status(400).json({ error });
      }

      res.status(200).json({ data });
    });

    app.listen(3000, () => {
      console.log("Listening on http://localhost:3000");
    });
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/basic-send.ts">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/with-attachments.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/with-cid-attachments.ts">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/with-template.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/scheduled-send.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/prevent-threading.ts">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/audiences.ts">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/inbound.ts">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/double-optin-subscribe.ts">
    Double opt-in subscription flow
  </Card>
</CardGroup>


# Send emails with FastAPI
Source: https://resend.com/docs/send-with-fastapi

Learn how to send your first email using FastAPI and the Resend Python SDK.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Python SDK.

    <CodeGroup>
      ```bash Pip theme={"theme":{"light":"github-light","dark":"vesper"}}
      pip install resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using HTML">
    The easiest way to send an email is by using the `html` parameter.

    ```py main.py theme={"theme":{"light":"github-light","dark":"vesper"}}
    import os
    from typing import Dict
    from fastapi import FastAPI
    import resend

    resend.api_key = os.environ["RESEND_API_KEY"]

    app = FastAPI()

    @app.post("/")
    def send_mail() -> Dict:
        params: resend.Emails.SendParams = {
            "from": "Acme <onboarding@resend.dev>",
            "to": ["delivered@resend.dev"],
            "subject": "hello world",
            "html": "<strong>it works!</strong>",
        }
        email: resend.Emails.SendResponse = resend.Emails.send(params)
        return email
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="FastAPI App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/fastapi_app.py">
    Full FastAPI web application
  </Card>

  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/basic_send.py">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/with_attachments.py">
    Send emails with file attachments
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/with_template.py">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/scheduled_send.py">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/audiences.py">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/domains.py">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/inbound.py">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/double_optin_subscribe.py">
    Double opt-in subscription flow
  </Card>
</CardGroup>


# Send emails with Flask
Source: https://resend.com/docs/send-with-flask

Learn how to send your first email using Flask and the Resend Python SDK.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Python SDK.

    <CodeGroup>
      ```bash Pip theme={"theme":{"light":"github-light","dark":"vesper"}}
      pip install resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using HTML">
    The easiest way to send an email is by using the `html` parameter.

    ```py index.py theme={"theme":{"light":"github-light","dark":"vesper"}}
    import resend
    import os
    from flask import Flask, jsonify

    resend.api_key = os.environ["RESEND_API_KEY"]

    app = Flask(__name__)


    @app.route("/")
    def index():
        params: resend.Emails.SendParams = {
            "from": "Acme <onboarding@resend.dev>",
            "to": ["delivered@resend.dev"],
            "subject": "hello world",
            "html": "<strong>it works!</strong>",
        }

        r = resend.Emails.send(params)
        return jsonify(r)


    if __name__ == "__main__":
        app.run()
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Flask App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/flask_app.py">
    Full Flask web application
  </Card>

  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/basic_send.py">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/with_attachments.py">
    Send emails with file attachments
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/with_template.py">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/scheduled_send.py">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/audiences.py">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/domains.py">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/inbound.py">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/double_optin_subscribe.py">
    Double opt-in subscription flow
  </Card>
</CardGroup>


# Send emails with Go
Source: https://resend.com/docs/send-with-go

Learn how to send your first email using the Resend Go SDK.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Go SDK.

    <CodeGroup>
      ```bash bash theme={"theme":{"light":"github-light","dark":"vesper"}}
      go get github.com/resend/resend-go/v3
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using HTML">
    The easiest way to send an email is by using the `html` parameter.

    ```Go main.go theme={"theme":{"light":"github-light","dark":"vesper"}}
    package main

    import (
    	"fmt"

    	"github.com/resend/resend-go/v3"
    )

    func main() {
        client := resend.NewClient("re_xxxxxxxxx")

        params := &resend.SendEmailRequest{
            From:    "Acme <onboarding@resend.dev>",
            To:      []string{"delivered@resend.dev"},
            Html:    "<strong>hello world</strong>",
            Subject: "Hello from Golang",
            Cc:      []string{"cc@example.com"},
            Bcc:     []string{"bcc@example.com"},
            ReplyTo: "replyto@example.com",
        }

        sent, err := client.Emails.Send(params)
        if err != nil {
            fmt.Println(err.Error())
            return
        }
        fmt.Println(sent.Id)
    }
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/basic_send">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/with_attachments">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/with_cid_attachments">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/with_template">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/scheduled_send">
    Schedule emails for future delivery
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/prevent_threading">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/domains">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/inbound">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/examples/double_optin">
    Double opt-in subscription flow
  </Card>

  <Card title="Chi App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/chi_app">
    Full Chi web framework application
  </Card>

  <Card title="Gin App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/go-resend-examples/gin_app">
    Full Gin web framework application
  </Card>
</CardGroup>


# Send emails with Hono
Source: https://resend.com/docs/send-with-hono

Learn how to send your first email using Hono and the Resend Node.js SDK.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend Node.js SDK

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using the [Resend](https://resend.com/) Node.js SDK.
  **Scope:** All AI-generated advice or code related to sending email with Resend must follow these guardrails.

  ***

  ## **1. Official Resend Node.js Setup**

  ### **Prerequisites**

  Human must first create an API key and verify their domain at [https://resend.com/domains](https://resend.com/domains).

  The API key must be stored in an environment variable called `RESEND_API_KEY`.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  The domain should be verified at [https://resend.com/domains](https://resend.com/domains) and added to the `from` address.

  ### **Install the SDK**

  Use the project's existing package manager to install the Resend Node.js SDK.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  # or: yarn add resend / pnpm add resend / bun add resend
  ```

  ### **Initialize the Client**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  ### **Send an Email**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  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);
    return;
  }

  console.log(data); // { id: '49a3999c-...' }
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ### Idempotency

  Best practice: Add an idempotency key to prevent duplicated emails, which is useful for retrying failed emails safely.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**
  * Pattern: `<event-type>/<entity-id>`
  * Example: `welcome-user/123456789`

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Hello World',
    html: '<strong>It works!</strong>',
    idempotencyKey: 'unique-id',
  });
  ```

  ***

  ## **2. Complete `emails.send()` Parameter Reference**

  ### **Required Parameters**

  | Parameter | Type                 | Description                                                                      |
  | --------- | -------------------- | -------------------------------------------------------------------------------- |
  | `from`    | `string`             | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `to`      | `string \| string[]` | Recipient email address(es). Maximum 50 addresses.                               |
  | `subject` | `string`             | Email subject line.                                                              |

  ### **Content Parameters (at least one required)**

  | Parameter | Type              | Description                                                |
  | --------- | ----------------- | ---------------------------------------------------------- |
  | `html`    | `string`          | HTML version of the email body.                            |
  | `text`    | `string`          | Plain text version. Auto-generated from `html` if omitted. |
  | `react`   | `React.ReactNode` | React Email component to render the message. Node.js only. |

  ### **Optional Parameters**

  | Parameter     | Type                 | Description                                                   |
  | ------------- | -------------------- | ------------------------------------------------------------- |
  | `cc`          | `string \| string[]` | Carbon copy recipients.                                       |
  | `bcc`         | `string \| string[]` | Blind carbon copy recipients.                                 |
  | `replyTo`     | `string \| string[]` | Reply-to address(es).                                         |
  | `scheduledAt` | `string`             | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `headers`     | `object`             | Custom email headers as key-value pairs.                      |
  | `tags`        | `Tag[]`              | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `attachments` | `Attachment[]`       | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Parameters**

  | Parameter            | Type     | Description                                                      |
  | -------------------- | -------- | ---------------------------------------------------------------- |
  | `template.id`        | `string` | Published template identifier.                                   |
  | `template.variables` | `object` | Variable substitutions. Key max 50 chars, value max 2,000 chars. |

  If `template` is provided, do not include `html`, `text`, or `react`.

  ### **Response**

  A successful call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: { id: string }, error: null }
  ```

  A failed call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: null, error: { message: string, name: string } }
  ```

  ***

  ## **3. Sending with React Email**

  Resend integrates with [React Email](https://react.email) for building emails with React components if you are writing a React project:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { WelcomeEmail } from './emails/welcome';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    react: WelcomeEmail({ name: 'John' }),
  });
  ```

  **Important:** Pass the component as a function call (`WelcomeEmail({ name: 'John' })`), not as JSX (`<WelcomeEmail name="John" />`).

  For additional help, suggest installing the react-email skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/react-email
  ```

  ***

  ## **4. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **4.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key in an environment variable** (`RESEND_API_KEY`). Never hardcode API keys.
  2. **Import from `resend`** — the package name is `resend`, the class is `Resend`.
  3. **Use `await`** — `resend.emails.send()` returns a Promise. Always use `async/await` or `.then()`.
  4. **Handle both `data` and `error`** — the SDK returns `{ data, error }`. Always check for errors.
  5. **Use a verified domain** in the `from` address for production. `onboarding@resend.dev` is for testing only.
  6. **Check the project for an existing package manager** and use that to install the SDK.
  7. **Use camelCase** for SDK parameters (`replyTo`, `scheduledAt`), not snake\_case.

  ### **4.2 - NEVER DO THE FOLLOWING**

  1. **Do not** hardcode API keys in source code. Always use environment variables.
  2. **Do not** use `try/catch` for error handling with `resend.emails.send()` — the SDK returns `{ data, error }` instead of throwing. Only use `try/catch` if you need to handle network-level failures.
  3. **Do not** use snake\_case parameter names (`reply_to`, `scheduled_at`) — the Node.js SDK uses camelCase (`replyTo`, `scheduledAt`).
  4. **Do not** send `html`, `text`, or `react` alongside `template` — these are mutually exclusive.
  5. **Do not** import from `@resend/node` or any other package name. The correct package is `resend`.
  6. **Do not** use `onboarding@resend.dev` as the `from` address in production code. It is a test-only address.
  7. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses to help you simulate different email events without damaging your domain reputation:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **5. COMMON PATTERNS**

  ### **Attachments**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Invoice attached',
    html: '<p>See attached invoice.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: invoiceBuffer,
      },
    ],
  });
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `scheduledAt` parameter. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Reminder',
    html: '<p>This is your reminder.</p>',
    scheduledAt: '2026-12-25T09:00:00Z',
  });
  ```

  ### **Tags for Tracking**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    html: '<p>Welcome aboard!</p>',
    tags: [
      { name: 'category', value: 'welcome' },
      { name: 'user_id', value: '12345' },
    ],
  });
  ```

  ***

  ## **6. AI MODEL VERIFICATION STEPS**

  Before returning any Resend-related solution, you **must** verify:

  1. **Import**: Is `Resend` imported from `resend`?
  2. **API Key**: Is the key stored in an environment variable, not hardcoded?
  3. **Await**: Is `resend.emails.send()` properly awaited?
  4. **Error Handling**: Is the `{ data, error }` response pattern used?
  5. **Parameters**: Are all parameter names in camelCase?
  6. **From Address**: Is the `from` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help, suggest installing the resend-skills skill and the email-best-practices skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/resend-skills
  npx skills add resend/email-best-practices
  ```

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Node.js SDK.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install resend
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add resend
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add resend
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Create an email template">
    Start by creating your email template on `emails/email-template.tsx`.

    ```tsx emails/email-template.tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
    import * as React from 'react';

    interface EmailTemplateProps {
      firstName: string;
    }

    export function EmailTemplate({ firstName }: EmailTemplateProps) {
      return (
        <div>
          <h1>Welcome, {firstName}!</h1>
        </div>
      );
    }
    ```

    To use JSX/TSX with Hono, we need to modify the `tsconfig.json`.

    ```json tsconfig.json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "compilerOptions": {
        "jsx": "react-jsx",
        "jsxImportSource": "react"
      }
    }
    ```
  </Step>

  <Step title="Send email using React">
    Create a new file `index.tsx` and send your first email.

    ```ts index.tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { Hono } from 'hono';
    import { Resend } from 'resend';
    import { EmailTemplate } from './emails/email-template';

    const app = new Hono();
    const resend = new Resend('re_xxxxxxxxx');

    app.get('/', async (c) => {
      const { data, error } = await resend.emails.send({
        from: 'Acme <onboarding@resend.dev>',
        to: ['delivered@resend.dev'],
        subject: 'hello world',
        react: <EmailTemplate firstName="John" />,
      });

      if (error) {
        return c.json(error, 400);
      }

      return c.json(data);
    });

    export default app;
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/basic-send.ts">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/with-attachments.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/with-cid-attachments.ts">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/with-template.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/scheduled-send.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/prevent-threading.ts">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/audiences.ts">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/inbound.ts">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/hono-resend-examples/typescript/examples/double-optin-subscribe.ts">
    Double opt-in subscription flow
  </Card>
</CardGroup>


# Send emails with Java
Source: https://resend.com/docs/send-with-java

Learn how to send your first email using the Resend Java SDK.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    <CodeGroup>
      ```bash Gradle theme={"theme":{"light":"github-light","dark":"vesper"}}
      implementation 'com.resend:resend-java:+'
      ```

      ```xml Maven theme={"theme":{"light":"github-light","dark":"vesper"}}
      <dependency>
          <groupId>com.resend</groupId>
          <artifactId>resend-java</artifactId>
          <version>LATEST</version>
      </dependency>
      ```
    </CodeGroup>
  </Step>

  <Step title="Send emails using HTML">
    ```java Main.java theme={"theme":{"light":"github-light","dark":"vesper"}}
    import com.resend.*;

    public class Main {
        public static void main(String[] args) {
            Resend resend = new Resend("re_xxxxxxxxx");

            CreateEmailOptions params = CreateEmailOptions.builder()
                    .from("Acme <onboarding@resend.dev>")
                    .to("delivered@resend.dev")
                    .subject("it works!")
                    .html("<strong>hello world</strong>")
                    .build();

             try {
                CreateEmailResponse data = resend.emails().send(params);
                System.out.println(data.getId());
            } catch (ResendException e) {
                e.printStackTrace();
            }
        }
    }
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/BasicSend.java">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/WithAttachments.java">
    Send emails with file attachments
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/WithTemplate.java">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/ScheduledSend.java">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/Audiences.java">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/Domains.java">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/Inbound.java">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/java-resend-examples/src/main/java/com/resend/examples/DoubleOptinSubscribe.java">
    Double opt-in subscription flow
  </Card>

  <Card title="Javalin App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/java-resend-examples/javalin_app">
    Full Javalin web framework application
  </Card>

  <Card title="Spring Boot App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/java-resend-examples/spring_boot_app">
    Full Spring Boot application
  </Card>
</CardGroup>


# Send emails with Laravel
Source: https://resend.com/docs/send-with-laravel

Learn how to send your first email using Laravel.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

Prefer watching a video? Check out this video walkthrough below.

<YouTube />

## Guide

<Steps>
  <Step title="Install">
    First, install Resend for Laravel using the Composer package manager:

    ```bash Composer theme={"theme":{"light":"github-light","dark":"vesper"}}
    composer require resend/resend-laravel
    ```
  </Step>

  <Step title="Configuration">
    ### API key

    Next, configure your Resend API key in your application's `.env` file:

    ```ini .env theme={"theme":{"light":"github-light","dark":"vesper"}}
    RESEND_API_KEY=re_xxxxxxxxx
    ```

    <Note>
      If you've upgraded your Laravel project from an older version (pre-5.5) and haven't enabled auto service provider discovery, you'll need to manually register the Resend service provider. Add the provider to the `providers` array in your `config/app.php` file:

      ```php config/app.php theme={"theme":{"light":"github-light","dark":"vesper"}}
      'providers' => [
          // ... other providers
          Resend\Laravel\ResendServiceProvider::class,
      ],
      ```

      Without this registration, the Facade may reference the core Resend PHP client instead of the Resend Laravel library, causing unexpected behavior.
    </Note>

    ### Mail driver

    To use Resend as your mail driver, first create a new mailer definition, in the `mailers` array within your application's `config/mail.php` configuration file:

    ```php mail.php theme={"theme":{"light":"github-light","dark":"vesper"}}
    'resend' => [
        'transport' => 'resend',
    ],
    ```

    Next, update your application's `.env` file to use the Resend mail driver:

    ```ini .env theme={"theme":{"light":"github-light","dark":"vesper"}}
    MAIL_MAILER=resend
    MAIL_FROM_ADDRESS=onboarding@resend.dev
    MAIL_FROM_NAME=Acme
    ```
  </Step>

  <Step title="Send an email">
    Resend for Laravel provides two convenient ways to send emails, using Laravel's email service or the `Resend` API facade.

    ### Using the Mail Facade

    ```php OrderShipmentController.php theme={"theme":{"light":"github-light","dark":"vesper"}}
    <?php

    namespace App\Http\Controllers;

    use App\Http\Controllers\Controller;
    use App\Mail\OrderShipped;
    use App\Models\Order;
    use Illuminate\Http\RedirectResponse;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Mail;

    class OrderShipmentController extends Controller
    {
        /**
         * Ship the given order.
         */
        public function store(Request $request): RedirectResponse
        {
            $order = Order::findOrFail($request->order_id);

            // Ship the order...

            Mail::to($request->user())->send(new OrderShipped($order));

            return redirect('/orders');
        }
    }
    ```

    ### Using the Resend Facade

    ```php OrderShipmentController.php theme={"theme":{"light":"github-light","dark":"vesper"}}
    <?php

    namespace App\Http\Controllers;

    use App\Http\Controllers\Controller;
    use App\Mail\OrderShipped;
    use App\Models\Order;
    use Illuminate\Http\RedirectResponse;
    use Illuminate\Http\Request;
    use Resend\Laravel\Facades\Resend;

    class OrderShipmentController extends Controller
    {
        /**
         * Ship the given order.
         */
        public function store(Request $request): RedirectResponse
        {
            $order = Order::findOrFail($request->order_id);

            // Ship the order...

            Resend::emails()->send([
                'from' => 'Acme <onboarding@resend.dev>',
                'to' => [$request->user()->email],
                'subject' => 'hello world',
                'html' => (new OrderShipped($order))->render(),
            ])

            return redirect('/orders');
        }
    }
    ```
  </Step>

  <Step title="Receiving webhook requests">
    By default, Resend for Laravel includes a webhook controller to respond to the `/resend/webhook` URL path. The controller will dispatch a Laravel event that corresponds to a Resend event. For example, an `email.delivered` event type will send an `EmailDelivered` Laravel event.

    ### Register the webhook endpoint

    Register your publicly accessible HTTPS URL in the Resend dashboard.

    <Tip>
      For development, you can create a tunnel to your localhost server using a tool like
      [ngrok](https://ngrok.com/download) or [VS Code Port Forwarding](https://code.visualstudio.com/docs/debugtest/port-forwarding). These tools serve your local dev environment at a public URL you can use to test your local webhook endpoint.

      Example: `https://example123.ngrok.io/api/webhook`
    </Tip>

    <img alt="Add Webhook" />

    ### CSRF protection

    Webhook requests from Resend need to bypass Laravel's CSRF protection. Be sure to list the URI as an exception in your application's `App\Http\Middleware\VerifyCsrfToken` middleware or list the route outside of the web middleware group:

    ```php theme={"theme":{"light":"github-light","dark":"vesper"}}
    protected $except = [
        'resend/*',
    ];
    ```

    ### Verifying webhook signatures

    To enable webhook verification, ensure that the `RESEND_WEBHOOK_SECRET` environment variable is set in your application's `.env` file. The **Signing secret** can be retrieved from your [Resend dashboard](https://resend.com/webhooks).
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Email Sending" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/EmailController.php">
    Basic, scheduled, attachments, CID, templates, and prevent threading
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/WebhookController.php">
    Handle webhook events
  </Card>

  <Card title="Inbound Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/InboundController.php">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/DoubleOptinController.php">
    Double opt-in subscription flow
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/AudienceController.php">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/DomainController.php">
    Create and manage sending domains
  </Card>
</CardGroup>


# Send emails using Laravel with SMTP
Source: https://resend.com/docs/send-with-laravel-smtp

Learn how to send your first email using Laravel with SMTP.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Setup your environment">
    First, configure your Resend SMTP details in your application's `.env` file:

    ```ini .env theme={"theme":{"light":"github-light","dark":"vesper"}}
    MAIL_MAILER=smtp
    MAIL_HOST=smtp.resend.com
    MAIL_PORT=587
    MAIL_USERNAME=resend
    MAIL_PASSWORD=re_xxxxxxxxx
    MAIL_ENCRYPTION=tls
    MAIL_FROM_ADDRESS=onboarding@resend.dev
    MAIL_FROM_NAME=Acme
    ```
  </Step>

  <Step title="Send an email">
    Now you're ready to send emails with Laravel's powerful email service. Here's an example of how to send your first email using Resend SMTP:

    ```php OrderShipmentController.php theme={"theme":{"light":"github-light","dark":"vesper"}}
    <?php

    namespace App\Http\Controllers;

    use App\Http\Controllers\Controller;
    use App\Mail\OrderShipped;
    use App\Models\Order;
    use Illuminate\Http\RedirectResponse;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Mail;

    class OrderShipmentController extends Controller
    {
        /**
         * Ship the given order.
         */
        public function store(Request $request): RedirectResponse
        {
            $order = Order::findOrFail($request->order_id);

            // Ship the order...

            Mail::to($request->user())->send(new OrderShipped($order));

            return redirect('/orders');
        }
    }
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Email Sending" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/EmailController.php">
    Basic, scheduled, attachments, CID, templates, and prevent threading
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/WebhookController.php">
    Handle webhook events
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/DoubleOptinController.php">
    Double opt-in subscription flow
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/AudienceController.php">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/laravel-resend-examples/app/Http/Controllers/DomainController.php">
    Create and manage sending domains
  </Card>
</CardGroup>


# Send emails using Liferay with SMTP
Source: https://resend.com/docs/send-with-liferay-smtp

Learn how to integrate Liferay with Resend SMTP.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Get the Resend SMTP credentials">
    When configuring your SMTP integration, you'll need to use the following credentials:

    * **Host**: `smtp.resend.com`
    * **Port**: `465`
    * **Username**: `resend`
    * **Password**: `YOUR_API_KEY`
  </Step>

  <Step title="Integrate with Liferay">
    After logging into your Liferay instance as the admin user, you'll need to enable the SMTP integration.

    1. Navigate to **Control Panel** → **Server Administration** → **Mail**.

    <img alt="Liferay - SMTP" />

    2. Copy-and-paste the SMTP credentials from Resend to Liferay.

    * **Outgoing SMTP Server**: `smtp.resend.com`
    * **Outgoing Port**: `465`
    * **Enable StartTLS**: `True`
    * **User Name**: `resend`
    * **Password**: `YOUR_API_KEY`

    Make sure to replace `YOUR_API_KEY` with an existing key or create a new [API Key](https://resend.com/api-keys).

    For the additional JavaMail properties, you can use:

    ```
    mail.smtp.auth=true
    mail.smtp.starttls.enable=true
    mail.smtp.starttls.required=true
    ```
  </Step>
</Steps>


# Send emails using Metabase with SMTP
Source: https://resend.com/docs/send-with-metabase-smtp

Learn how to integrate Metabase with Resend SMTP.

### Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Get the Resend SMTP credentials">
    When configuring your SMTP integration, you'll need to use the following credentials:

    * **Host**: `smtp.resend.com`
    * **Port**: `465`
    * **Username**: `resend`
    * **Password**: `YOUR_API_KEY`
  </Step>

  <Step title="Integrate with Metabase SMTP">
    After logging into your [Metabase Cloud](https://www.metabase.com/cloud/login) account, you’ll need to enable the SMTP integration.

    1. From your Metabase Cloud Admin Panel, go to **Settings > Email** in the left menu. You'll see the form below.

    <img alt="Metabase Cloud SMTP" />

    2. Copy-and-paste the SMTP credentials from Resend to Metabase Cloud. Finally, click the **Save** button and all of your emails will be sent through Resend.

    <img alt="Metabase Cloud SMTP" />
  </Step>
</Steps>


# Send emails using NextAuth with SMTP
Source: https://resend.com/docs/send-with-nextauth-smtp

Learn how to send your first email using NextAuth.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Install the [NextAuth](https://next-auth.js.org/getting-started/example#install-nextauth) package.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install next-auth
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add next-auth
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add next-auth
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add next-auth
      ```
    </CodeGroup>

    Then, install the [Nodemailer](https://www.npmjs.com/package/nodemailer) package.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install nodemailer
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add nodemailer
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add nodemailer
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add nodemailer
      ```
    </CodeGroup>
  </Step>

  <Step title="Configure SMTP credentials">
    Add your Resend SMTP crendentials in your application's `.env` file:

    ```ini .env theme={"theme":{"light":"github-light","dark":"vesper"}}
    EMAIL_SERVER_USER=resend
    EMAIL_SERVER_PASSWORD=YOUR_API_KEY
    EMAIL_SERVER_HOST=smtp.resend.com
    EMAIL_SERVER_PORT=465
    EMAIL_FROM=onboarding@resend.dev
    ```
  </Step>

  <Step title="Configure Email Provider">
    Finally, in your \[...nextauth].js file (typically located in pages/api/auth), configure the Email provider with your SMTP settings:

    ```js index.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import NextAuth from 'next-auth';
    import EmailProvider from 'next-auth/providers/email';
    import nodemailer from 'nodemailer';

    export default NextAuth({
      providers: [
        EmailProvider({
          server: {
            host: process.env.EMAIL_SERVER_HOST,
            port: process.env.EMAIL_SERVER_PORT,
            auth: {
              user: process.env.EMAIL_SERVER_USER,
              pass: process.env.EMAIL_SERVER_PASSWORD,
            },
          },
          from: process.env.EMAIL_FROM,
        }),
        // ... other providers as needed
      ],
      // ... any other NextAuth.js configs
    });
    ```
  </Step>
</Steps>


# Send emails with Next.js
Source: https://resend.com/docs/send-with-nextjs

Learn how to send your first email using Next.js and the Resend Node.js SDK.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend Node.js SDK

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using the [Resend](https://resend.com/) Node.js SDK.
  **Scope:** All AI-generated advice or code related to sending email with Resend must follow these guardrails.

  ***

  ## **1. Official Resend Node.js Setup**

  ### **Prerequisites**

  Human must first create an API key and verify their domain at [https://resend.com/domains](https://resend.com/domains).

  The API key must be stored in an environment variable called `RESEND_API_KEY`.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  The domain should be verified at [https://resend.com/domains](https://resend.com/domains) and added to the `from` address.

  ### **Install the SDK**

  Use the project's existing package manager to install the Resend Node.js SDK.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  # or: yarn add resend / pnpm add resend / bun add resend
  ```

  ### **Initialize the Client**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  ### **Send an Email**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  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);
    return;
  }

  console.log(data); // { id: '49a3999c-...' }
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ### Idempotency

  Best practice: Add an idempotency key to prevent duplicated emails, which is useful for retrying failed emails safely.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**
  * Pattern: `<event-type>/<entity-id>`
  * Example: `welcome-user/123456789`

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Hello World',
    html: '<strong>It works!</strong>',
    idempotencyKey: 'unique-id',
  });
  ```

  ***

  ## **2. Complete `emails.send()` Parameter Reference**

  ### **Required Parameters**

  | Parameter | Type                 | Description                                                                      |
  | --------- | -------------------- | -------------------------------------------------------------------------------- |
  | `from`    | `string`             | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `to`      | `string \| string[]` | Recipient email address(es). Maximum 50 addresses.                               |
  | `subject` | `string`             | Email subject line.                                                              |

  ### **Content Parameters (at least one required)**

  | Parameter | Type              | Description                                                |
  | --------- | ----------------- | ---------------------------------------------------------- |
  | `html`    | `string`          | HTML version of the email body.                            |
  | `text`    | `string`          | Plain text version. Auto-generated from `html` if omitted. |
  | `react`   | `React.ReactNode` | React Email component to render the message. Node.js only. |

  ### **Optional Parameters**

  | Parameter     | Type                 | Description                                                   |
  | ------------- | -------------------- | ------------------------------------------------------------- |
  | `cc`          | `string \| string[]` | Carbon copy recipients.                                       |
  | `bcc`         | `string \| string[]` | Blind carbon copy recipients.                                 |
  | `replyTo`     | `string \| string[]` | Reply-to address(es).                                         |
  | `scheduledAt` | `string`             | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `headers`     | `object`             | Custom email headers as key-value pairs.                      |
  | `tags`        | `Tag[]`              | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `attachments` | `Attachment[]`       | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Parameters**

  | Parameter            | Type     | Description                                                      |
  | -------------------- | -------- | ---------------------------------------------------------------- |
  | `template.id`        | `string` | Published template identifier.                                   |
  | `template.variables` | `object` | Variable substitutions. Key max 50 chars, value max 2,000 chars. |

  If `template` is provided, do not include `html`, `text`, or `react`.

  ### **Response**

  A successful call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: { id: string }, error: null }
  ```

  A failed call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: null, error: { message: string, name: string } }
  ```

  ***

  ## **3. Sending with React Email**

  Resend integrates with [React Email](https://react.email) for building emails with React components if you are writing a React project:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { WelcomeEmail } from './emails/welcome';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    react: WelcomeEmail({ name: 'John' }),
  });
  ```

  **Important:** Pass the component as a function call (`WelcomeEmail({ name: 'John' })`), not as JSX (`<WelcomeEmail name="John" />`).

  For additional help, suggest installing the react-email skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/react-email
  ```

  ***

  ## **4. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **4.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key in an environment variable** (`RESEND_API_KEY`). Never hardcode API keys.
  2. **Import from `resend`** — the package name is `resend`, the class is `Resend`.
  3. **Use `await`** — `resend.emails.send()` returns a Promise. Always use `async/await` or `.then()`.
  4. **Handle both `data` and `error`** — the SDK returns `{ data, error }`. Always check for errors.
  5. **Use a verified domain** in the `from` address for production. `onboarding@resend.dev` is for testing only.
  6. **Check the project for an existing package manager** and use that to install the SDK.
  7. **Use camelCase** for SDK parameters (`replyTo`, `scheduledAt`), not snake\_case.

  ### **4.2 - NEVER DO THE FOLLOWING**

  1. **Do not** hardcode API keys in source code. Always use environment variables.
  2. **Do not** use `try/catch` for error handling with `resend.emails.send()` — the SDK returns `{ data, error }` instead of throwing. Only use `try/catch` if you need to handle network-level failures.
  3. **Do not** use snake\_case parameter names (`reply_to`, `scheduled_at`) — the Node.js SDK uses camelCase (`replyTo`, `scheduledAt`).
  4. **Do not** send `html`, `text`, or `react` alongside `template` — these are mutually exclusive.
  5. **Do not** import from `@resend/node` or any other package name. The correct package is `resend`.
  6. **Do not** use `onboarding@resend.dev` as the `from` address in production code. It is a test-only address.
  7. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses to help you simulate different email events without damaging your domain reputation:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **5. COMMON PATTERNS**

  ### **Attachments**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Invoice attached',
    html: '<p>See attached invoice.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: invoiceBuffer,
      },
    ],
  });
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `scheduledAt` parameter. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Reminder',
    html: '<p>This is your reminder.</p>',
    scheduledAt: '2026-12-25T09:00:00Z',
  });
  ```

  ### **Tags for Tracking**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    html: '<p>Welcome aboard!</p>',
    tags: [
      { name: 'category', value: 'welcome' },
      { name: 'user_id', value: '12345' },
    ],
  });
  ```

  ***

  ## **6. AI MODEL VERIFICATION STEPS**

  Before returning any Resend-related solution, you **must** verify:

  1. **Import**: Is `Resend` imported from `resend`?
  2. **API Key**: Is the key stored in an environment variable, not hardcoded?
  3. **Await**: Is `resend.emails.send()` properly awaited?
  4. **Error Handling**: Is the `{ data, error }` response pattern used?
  5. **Parameters**: Are all parameter names in camelCase?
  6. **From Address**: Is the `from` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help, suggest installing the resend-skills skill and the email-best-practices skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/resend-skills
  npx skills add resend/email-best-practices
  ```

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

Prefer watching a video? Check out our video walkthrough below.

<YouTube />

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Node.js SDK.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install resend
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add resend
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add resend
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Create an email template">
    Start by creating your email template on `components/email-template.tsx`.

    ```tsx components/email-template.tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
    import * as React from 'react';

    interface EmailTemplateProps {
      firstName: string;
    }

    export function EmailTemplate({ firstName }: EmailTemplateProps) {
      return (
        <div>
          <h1>Welcome, {firstName}!</h1>
        </div>
      );
    }
    ```
  </Step>

  <Step title="Send email using React">
    Create a route file under `app/api/send/route.ts` (or `pages/api/send.ts` if you're using [Pages Router](https://nextjs.org/docs/pages/building-your-application/routing/api-routes)).

    Import the React email template and send an email using the `react` parameter.

    <CodeGroup>
      ```ts app/api/send/route.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { EmailTemplate } from '../../../components/email-template';
      import { Resend } from 'resend';

      const resend = new Resend(process.env.RESEND_API_KEY);

      export async function POST() {
        try {
          const { data, error } = await resend.emails.send({
            from: 'Acme <onboarding@resend.dev>',
            to: ['delivered@resend.dev'],
            subject: 'Hello world',
            react: EmailTemplate({ firstName: 'John' }),
          });

          if (error) {
            return Response.json({ error }, { status: 500 });
          }

          return Response.json(data);
        } catch (error) {
          return Response.json({ error }, { status: 500 });
        }
      }
      ```

      ```ts pages/api/send.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
      import type { NextApiRequest, NextApiResponse } from 'next';
      import { EmailTemplate } from '../../components/email-template';
      import { Resend } from 'resend';

      const resend = new Resend(process.env.RESEND_API_KEY);

      export default async (req: NextApiRequest, res: NextApiResponse) => {
        const { data, error } = await resend.emails.send({
          from: 'Acme <onboarding@resend.dev>',
          to: ['delivered@resend.dev'],
          subject: 'Hello world',
          react: EmailTemplate({ firstName: 'John' }),
        });

        if (error) {
          return res.status(400).json(error);
        }

        res.status(200).json(data);
      };
      ```
    </CodeGroup>
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Next.js (TypeScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript">
    Full-stack Next.js app with TypeScript
  </Card>

  <Card title="Next.js (JavaScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript">
    Full-stack Next.js app with JavaScript
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/attachments">
    Send emails with file attachments
  </Card>

  <Card title="React Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/react-email">
    Send emails with React Email components
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/templates">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/scheduling">
    Schedule emails for future delivery
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/double-optin">
    Double opt-in subscription flow
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/inbound">
    Receive and process inbound emails
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/prevent-threading">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/domains">
    Create and manage sending domains
  </Card>

  <Card title="Better Auth" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/better-auth">
    Email authentication with Better Auth
  </Card>
</CardGroup>


# Send emails with Node.js
Source: https://resend.com/docs/send-with-nodejs

Learn how to send your first email using the Resend Node.js SDK.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend Node.js SDK

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using the [Resend](https://resend.com/) Node.js SDK.
  **Scope:** All AI-generated advice or code related to sending email with Resend must follow these guardrails.

  ***

  ## **1. Official Resend Node.js Setup**

  ### **Prerequisites**

  Human must first create an API key and verify their domain at [https://resend.com/domains](https://resend.com/domains).

  The API key must be stored in an environment variable called `RESEND_API_KEY`.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  The domain should be verified at [https://resend.com/domains](https://resend.com/domains) and added to the `from` address.

  ### **Install the SDK**

  Use the project's existing package manager to install the Resend Node.js SDK.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  # or: yarn add resend / pnpm add resend / bun add resend
  ```

  ### **Initialize the Client**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  ### **Send an Email**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  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);
    return;
  }

  console.log(data); // { id: '49a3999c-...' }
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ### Idempotency

  Best practice: Add an idempotency key to prevent duplicated emails, which is useful for retrying failed emails safely.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**
  * Pattern: `<event-type>/<entity-id>`
  * Example: `welcome-user/123456789`

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Hello World',
    html: '<strong>It works!</strong>',
    idempotencyKey: 'unique-id',
  });
  ```

  ***

  ## **2. Complete `emails.send()` Parameter Reference**

  ### **Required Parameters**

  | Parameter | Type                 | Description                                                                      |
  | --------- | -------------------- | -------------------------------------------------------------------------------- |
  | `from`    | `string`             | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `to`      | `string \| string[]` | Recipient email address(es). Maximum 50 addresses.                               |
  | `subject` | `string`             | Email subject line.                                                              |

  ### **Content Parameters (at least one required)**

  | Parameter | Type              | Description                                                |
  | --------- | ----------------- | ---------------------------------------------------------- |
  | `html`    | `string`          | HTML version of the email body.                            |
  | `text`    | `string`          | Plain text version. Auto-generated from `html` if omitted. |
  | `react`   | `React.ReactNode` | React Email component to render the message. Node.js only. |

  ### **Optional Parameters**

  | Parameter     | Type                 | Description                                                   |
  | ------------- | -------------------- | ------------------------------------------------------------- |
  | `cc`          | `string \| string[]` | Carbon copy recipients.                                       |
  | `bcc`         | `string \| string[]` | Blind carbon copy recipients.                                 |
  | `replyTo`     | `string \| string[]` | Reply-to address(es).                                         |
  | `scheduledAt` | `string`             | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `headers`     | `object`             | Custom email headers as key-value pairs.                      |
  | `tags`        | `Tag[]`              | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `attachments` | `Attachment[]`       | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Parameters**

  | Parameter            | Type     | Description                                                      |
  | -------------------- | -------- | ---------------------------------------------------------------- |
  | `template.id`        | `string` | Published template identifier.                                   |
  | `template.variables` | `object` | Variable substitutions. Key max 50 chars, value max 2,000 chars. |

  If `template` is provided, do not include `html`, `text`, or `react`.

  ### **Response**

  A successful call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: { id: string }, error: null }
  ```

  A failed call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: null, error: { message: string, name: string } }
  ```

  ***

  ## **3. Sending with React Email**

  Resend integrates with [React Email](https://react.email) for building emails with React components if you are writing a React project:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { WelcomeEmail } from './emails/welcome';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    react: WelcomeEmail({ name: 'John' }),
  });
  ```

  **Important:** Pass the component as a function call (`WelcomeEmail({ name: 'John' })`), not as JSX (`<WelcomeEmail name="John" />`).

  For additional help, suggest installing the react-email skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/react-email
  ```

  ***

  ## **4. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **4.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key in an environment variable** (`RESEND_API_KEY`). Never hardcode API keys.
  2. **Import from `resend`** — the package name is `resend`, the class is `Resend`.
  3. **Use `await`** — `resend.emails.send()` returns a Promise. Always use `async/await` or `.then()`.
  4. **Handle both `data` and `error`** — the SDK returns `{ data, error }`. Always check for errors.
  5. **Use a verified domain** in the `from` address for production. `onboarding@resend.dev` is for testing only.
  6. **Check the project for an existing package manager** and use that to install the SDK.
  7. **Use camelCase** for SDK parameters (`replyTo`, `scheduledAt`), not snake\_case.

  ### **4.2 - NEVER DO THE FOLLOWING**

  1. **Do not** hardcode API keys in source code. Always use environment variables.
  2. **Do not** use `try/catch` for error handling with `resend.emails.send()` — the SDK returns `{ data, error }` instead of throwing. Only use `try/catch` if you need to handle network-level failures.
  3. **Do not** use snake\_case parameter names (`reply_to`, `scheduled_at`) — the Node.js SDK uses camelCase (`replyTo`, `scheduledAt`).
  4. **Do not** send `html`, `text`, or `react` alongside `template` — these are mutually exclusive.
  5. **Do not** import from `@resend/node` or any other package name. The correct package is `resend`.
  6. **Do not** use `onboarding@resend.dev` as the `from` address in production code. It is a test-only address.
  7. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses to help you simulate different email events without damaging your domain reputation:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **5. COMMON PATTERNS**

  ### **Attachments**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Invoice attached',
    html: '<p>See attached invoice.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: invoiceBuffer,
      },
    ],
  });
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `scheduledAt` parameter. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Reminder',
    html: '<p>This is your reminder.</p>',
    scheduledAt: '2026-12-25T09:00:00Z',
  });
  ```

  ### **Tags for Tracking**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    html: '<p>Welcome aboard!</p>',
    tags: [
      { name: 'category', value: 'welcome' },
      { name: 'user_id', value: '12345' },
    ],
  });
  ```

  ***

  ## **6. AI MODEL VERIFICATION STEPS**

  Before returning any Resend-related solution, you **must** verify:

  1. **Import**: Is `Resend` imported from `resend`?
  2. **API Key**: Is the key stored in an environment variable, not hardcoded?
  3. **Await**: Is `resend.emails.send()` properly awaited?
  4. **Error Handling**: Is the `{ data, error }` response pattern used?
  5. **Parameters**: Are all parameter names in camelCase?
  6. **From Address**: Is the `from` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help, suggest installing the resend-skills skill and the email-best-practices skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/resend-skills
  npx skills add resend/email-best-practices
  ```

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Node.js SDK.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install resend
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add resend
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add resend
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Set your API key">
    Store your API key in an environment variable in your `.env` file.

    <CodeGroup>
      ```sh .env theme={"theme":{"light":"github-light","dark":"vesper"}}
      RESEND_API_KEY=re_xxxxxxxxx
      ```
    </CodeGroup>

    Pass it to the constructor with `process.env.RESEND_API_KEY`. See [Create an API key](/docs/create-an-api-key) for the full setup.
  </Step>

  <Step title="Send email using HTML">
    The easiest way to send an email is by using the `html` parameter.

    ```js server.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { Resend } from 'resend';

    const resend = new Resend(process.env.RESEND_API_KEY);

    (async function () {
      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) {
        return console.error({ error });
      }

      console.log({ data });
    })();
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Express (TypeScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/express-resend-examples/typescript">
    Full Express app with TypeScript
  </Card>

  <Card title="Express (JavaScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/express-resend-examples/javascript">
    Full Express app with JavaScript
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/with-attachments.ts">
    Send emails with file attachments
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/with-template.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/scheduled-send.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/audiences.ts">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/inbound.ts">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/express-resend-examples/typescript/examples/double-optin-subscribe.ts">
    Double opt-in subscription flow
  </Card>
</CardGroup>


# Send emails using Nodemailer with SMTP
Source: https://resend.com/docs/send-with-nodemailer-smtp

Learn how to send your first email using Nodemailer with SMTP.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

<Steps>
  <Step title="Install">
    Get the [Nodemailer](https://www.npmjs.com/package/nodemailer) package.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install nodemailer
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add nodemailer
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add nodemailer
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add nodemailer
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using SMTP">
    When configuring your SMTP integration, you'll need to use the following credentials:

    * **Host**: `smtp.resend.com`
    * **Port**: `465`
    * **Username**: `resend`
    * **Password**: `YOUR_API_KEY`

    Then use these credentials to create a transport:

    ```js index.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import nodemailer from 'nodemailer';

    async function main() {
      const transporter = nodemailer.createTransport({
        host: 'smtp.resend.com',
        secure: true,
        port: 465,
        auth: {
          user: 'resend',
          pass: 're_xxxxxxxxx',
        },
      });

      const info = await transporter.sendMail({
        from: 'onboarding@resend.dev',
        to: 'delivered@resend.dev',
        subject: 'Hello World',
        html: '<strong>It works!</strong>',
      });

      console.log('Message sent: %s', info.messageId);
    }

    main().catch(console.error);
    ```
  </Step>
</Steps>

## Examples

<Card title="Nodemailer SMTP Example" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-nodemailer-smtp-example">
  See the full source code.
</Card>


# Send emails with Nuxt
Source: https://resend.com/docs/send-with-nuxt

Learn how to send your first email using Nuxt and the Resend Node.js SDK.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend Node.js SDK

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using the [Resend](https://resend.com/) Node.js SDK.
  **Scope:** All AI-generated advice or code related to sending email with Resend must follow these guardrails.

  ***

  ## **1. Official Resend Node.js Setup**

  ### **Prerequisites**

  Human must first create an API key and verify their domain at [https://resend.com/domains](https://resend.com/domains).

  The API key must be stored in an environment variable called `RESEND_API_KEY`.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  The domain should be verified at [https://resend.com/domains](https://resend.com/domains) and added to the `from` address.

  ### **Install the SDK**

  Use the project's existing package manager to install the Resend Node.js SDK.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  # or: yarn add resend / pnpm add resend / bun add resend
  ```

  ### **Initialize the Client**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  ### **Send an Email**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  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);
    return;
  }

  console.log(data); // { id: '49a3999c-...' }
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ### Idempotency

  Best practice: Add an idempotency key to prevent duplicated emails, which is useful for retrying failed emails safely.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**
  * Pattern: `<event-type>/<entity-id>`
  * Example: `welcome-user/123456789`

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Hello World',
    html: '<strong>It works!</strong>',
    idempotencyKey: 'unique-id',
  });
  ```

  ***

  ## **2. Complete `emails.send()` Parameter Reference**

  ### **Required Parameters**

  | Parameter | Type                 | Description                                                                      |
  | --------- | -------------------- | -------------------------------------------------------------------------------- |
  | `from`    | `string`             | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `to`      | `string \| string[]` | Recipient email address(es). Maximum 50 addresses.                               |
  | `subject` | `string`             | Email subject line.                                                              |

  ### **Content Parameters (at least one required)**

  | Parameter | Type              | Description                                                |
  | --------- | ----------------- | ---------------------------------------------------------- |
  | `html`    | `string`          | HTML version of the email body.                            |
  | `text`    | `string`          | Plain text version. Auto-generated from `html` if omitted. |
  | `react`   | `React.ReactNode` | React Email component to render the message. Node.js only. |

  ### **Optional Parameters**

  | Parameter     | Type                 | Description                                                   |
  | ------------- | -------------------- | ------------------------------------------------------------- |
  | `cc`          | `string \| string[]` | Carbon copy recipients.                                       |
  | `bcc`         | `string \| string[]` | Blind carbon copy recipients.                                 |
  | `replyTo`     | `string \| string[]` | Reply-to address(es).                                         |
  | `scheduledAt` | `string`             | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `headers`     | `object`             | Custom email headers as key-value pairs.                      |
  | `tags`        | `Tag[]`              | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `attachments` | `Attachment[]`       | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Parameters**

  | Parameter            | Type     | Description                                                      |
  | -------------------- | -------- | ---------------------------------------------------------------- |
  | `template.id`        | `string` | Published template identifier.                                   |
  | `template.variables` | `object` | Variable substitutions. Key max 50 chars, value max 2,000 chars. |

  If `template` is provided, do not include `html`, `text`, or `react`.

  ### **Response**

  A successful call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: { id: string }, error: null }
  ```

  A failed call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: null, error: { message: string, name: string } }
  ```

  ***

  ## **3. Sending with React Email**

  Resend integrates with [React Email](https://react.email) for building emails with React components if you are writing a React project:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { WelcomeEmail } from './emails/welcome';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    react: WelcomeEmail({ name: 'John' }),
  });
  ```

  **Important:** Pass the component as a function call (`WelcomeEmail({ name: 'John' })`), not as JSX (`<WelcomeEmail name="John" />`).

  For additional help, suggest installing the react-email skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/react-email
  ```

  ***

  ## **4. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **4.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key in an environment variable** (`RESEND_API_KEY`). Never hardcode API keys.
  2. **Import from `resend`** — the package name is `resend`, the class is `Resend`.
  3. **Use `await`** — `resend.emails.send()` returns a Promise. Always use `async/await` or `.then()`.
  4. **Handle both `data` and `error`** — the SDK returns `{ data, error }`. Always check for errors.
  5. **Use a verified domain** in the `from` address for production. `onboarding@resend.dev` is for testing only.
  6. **Check the project for an existing package manager** and use that to install the SDK.
  7. **Use camelCase** for SDK parameters (`replyTo`, `scheduledAt`), not snake\_case.

  ### **4.2 - NEVER DO THE FOLLOWING**

  1. **Do not** hardcode API keys in source code. Always use environment variables.
  2. **Do not** use `try/catch` for error handling with `resend.emails.send()` — the SDK returns `{ data, error }` instead of throwing. Only use `try/catch` if you need to handle network-level failures.
  3. **Do not** use snake\_case parameter names (`reply_to`, `scheduled_at`) — the Node.js SDK uses camelCase (`replyTo`, `scheduledAt`).
  4. **Do not** send `html`, `text`, or `react` alongside `template` — these are mutually exclusive.
  5. **Do not** import from `@resend/node` or any other package name. The correct package is `resend`.
  6. **Do not** use `onboarding@resend.dev` as the `from` address in production code. It is a test-only address.
  7. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses to help you simulate different email events without damaging your domain reputation:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **5. COMMON PATTERNS**

  ### **Attachments**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Invoice attached',
    html: '<p>See attached invoice.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: invoiceBuffer,
      },
    ],
  });
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `scheduledAt` parameter. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Reminder',
    html: '<p>This is your reminder.</p>',
    scheduledAt: '2026-12-25T09:00:00Z',
  });
  ```

  ### **Tags for Tracking**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    html: '<p>Welcome aboard!</p>',
    tags: [
      { name: 'category', value: 'welcome' },
      { name: 'user_id', value: '12345' },
    ],
  });
  ```

  ***

  ## **6. AI MODEL VERIFICATION STEPS**

  Before returning any Resend-related solution, you **must** verify:

  1. **Import**: Is `Resend` imported from `resend`?
  2. **API Key**: Is the key stored in an environment variable, not hardcoded?
  3. **Await**: Is `resend.emails.send()` properly awaited?
  4. **Error Handling**: Is the `{ data, error }` response pattern used?
  5. **Parameters**: Are all parameter names in camelCase?
  6. **From Address**: Is the `from` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help, suggest installing the resend-skills skill and the email-best-practices skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/resend-skills
  npx skills add resend/email-best-practices
  ```

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Node.js SDK.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install resend
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add resend
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add resend
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using HTML">
    Create a [Server Route](https://nuxt.com/docs/guide/directory-structure/server) under `server/api/send.ts`.

    The easiest way to send an email is by using the `html` parameter.

    <CodeGroup>
      ```ts server/api/send.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';

      const resend = new Resend(process.env.RESEND_API_KEY);

      export default defineEventHandler(async () => {
        const response = await resend.emails.send({
          from: 'Acme <onboarding@resend.dev>',
          to: ['delivered@resend.dev'],
          subject: 'Hello world',
          html: '<strong>It works!</strong>',
        });

        if (response.error) {
          throw createError({
            statusCode: 500,
            message: 'Error sending email',
          });
        }

        return response;
      });
      ```
    </CodeGroup>
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Send Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/send.post.ts">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/send-attachment.post.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/send-cid.post.ts">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/send-template.post.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/send-scheduled.post.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nuxt-resend-examples/typescript/server/api/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/domains.post.ts">
    Create and manage sending domains
  </Card>

  <Card title="Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/nuxt-resend-examples/typescript/server/api/webhook.post.ts">
    Handle webhook events
  </Card>
</CardGroup>


# Send emails with Phoenix
Source: https://resend.com/docs/send-with-phoenix

Learn how to send your first email using Phoenix and the Resend Elixir SDK.

<Info>
  This guides utilizes an [open source
  library](https://github.com/elixir-saas/resend-elixir) contributed by a
  community member. It's not developed, maintained, or supported by Resend
  directly.
</Info>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Install by adding `resend` to your list of dependencies in `mix.exs`:

    <CodeGroup>
      ```elixir mix.exs theme={"theme":{"light":"github-light","dark":"vesper"}}
      def deps do
        [
          {:resend, "~> 0.4.5"}
        ]
      end
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using Swoosh">
    This library includes a Swoosh adapter to make using Resend with a new Phoenix project straightforward. Configure your Mailer:

    ```elixir theme={"theme":{"light":"github-light","dark":"vesper"}}
    config :my_app, MyApp.Mailer,
      adapter: Resend.Swoosh.Adapter,
      api_key: System.fetch_env!("RESEND_API_KEY")
    ```

    If you're configuring your app for production, configure your adapter in `prod.exs`, and your API key from the environment in `runtime.exs`:

    <CodeGroup>
      ```elixir prod.exs theme={"theme":{"light":"github-light","dark":"vesper"}}
      config :my_app, MyApp.Mailer, adapter: Resend.Swoosh.Adapter
      ```

      ```elixir runtime.exs theme={"theme":{"light":"github-light","dark":"vesper"}}
      config :my_app, MyApp.Mailer, api_key: "re_xxxxxxxxx"
      ```
    </CodeGroup>
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Phoenix App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/elixir-resend-examples/phoenix_app">
    Full Phoenix web framework application
  </Card>

  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/basic_send.exs">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/with_attachments.exs">
    Send emails with file attachments
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/with_template.exs">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/scheduled_send.exs">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/audiences.exs">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/domains.exs">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/elixir-resend-examples/examples/inbound.exs">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/elixir-resend-examples/examples/double_optin">
    Double opt-in subscription flow
  </Card>
</CardGroup>


# Send emails with PHP
Source: https://resend.com/docs/send-with-php

Learn how to send your first email using the Resend PHP SDK.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

Prefer watching a video? Check out this video walkthrough below.

<YouTube />

## Guide

<Steps>
  <Step title="Install">
    Get the Resend PHP SDK.

    ```bash Composer theme={"theme":{"light":"github-light","dark":"vesper"}}
    composer require resend/resend-php
    ```
  </Step>

  <Step title="Send email using HTML">
    The easiest way to send an email is by using the `html` parameter.

    ```php index.php theme={"theme":{"light":"github-light","dark":"vesper"}}
    <?php

    require __DIR__ . '/vendor/autoload.php';

    $resend = Resend::client('re_xxxxxxxxx');

    $resend->emails->send([
      'from' => 'Acme <onboarding@resend.dev>',
      'to' => ['delivered@resend.dev'],
      'subject' => 'hello world',
      'html' => '<strong>it works!</strong>',
    ]);
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/send">
    Basic, batch, and prevent-threading send
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/attachments">
    File attachments and inline images (CID)
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/scheduling">
    Schedule emails for future delivery
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/templates">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/double-optin">
    Double opt-in subscription flow
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/inbound">
    Receive and process inbound emails
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/domains">
    Create and manage sending domains
  </Card>

  <Card title="Symfony App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/symfony_app">
    Full Symfony web application
  </Card>
</CardGroup>


# Send emails using PHPMailer with SMTP
Source: https://resend.com/docs/send-with-phpmailer-smtp

Learn how to send your first email using PHPMailer with SMTP.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the [PHPMailer](https://github.com/PHPMailer/PHPMailer) package.

    <CodeGroup>
      ```bash php theme={"theme":{"light":"github-light","dark":"vesper"}}
      composer require phpmailer/phpmailer
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using SMTP">
    When configuring your SMTP integration, you'll need to use the following credentials:

    * **Host**: `smtp.resend.com`
    * **Port**: `587`
    * **Username**: `resend`
    * **Password**: `YOUR_API_KEY`

    Then use these credentials to send with PHPMailer:

    ```php theme={"theme":{"light":"github-light","dark":"vesper"}}
    <?php

    // Include Composer autoload file to load PHPMailer classes
    require __DIR__ . '/vendor/autoload.php';

    use PHPMailer\PHPMailer\PHPMailer;
    use PHPMailer\PHPMailer\Exception;

    $mail = new PHPMailer(true);

    try {
        $mail->isSMTP();
        $mail->Host = 'smtp.resend.com';
        $mail->SMTPAuth = true;
        $mail->Username = 'resend';
        $mail->Password = 're_xxxxxxxxx';
        $mail->SMTPSecure = 'tls';
        $mail->Port = 587;

        // Set email format to HTML
        $mail->isHTML(true);

        $mail->setFrom('onboarding@resend.dev');
        $mail->addAddress('delivered@resend.dev');
        $mail->Subject = 'Hello World';
        $mail->Body = '<strong>It works!</strong>';

        $mail->send();

        // Log the successfully sent message
        echo 'Email successfully sent';
    } catch (Exception $e) {
        // Log the detailed error for debugging
        error_log('Mailer Error: ' . $mail->ErrorInfo);
        // Show a generic error message to the user
        echo 'There was an error sending the email.';
    }
    ```
  </Step>
</Steps>

## Examples

<Card title="PHPMailer SMTP Example" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-phpmailer-smtp-example">
  See the full source code.
</Card>


# Send emails with Python
Source: https://resend.com/docs/send-with-python

Learn how to send your first email using the Resend Python SDK.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Python SDK.

    <CodeGroup>
      ```bash Pip theme={"theme":{"light":"github-light","dark":"vesper"}}
      pip install resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using HTML">
    The easiest way to send an email is by using the `html` parameter.

    ```py index.py theme={"theme":{"light":"github-light","dark":"vesper"}}
    import os
    import resend

    resend.api_key = os.environ["RESEND_API_KEY"]

    params: resend.Emails.SendParams = {
        "from": "Acme <onboarding@resend.dev>",
        "to": ["delivered@resend.dev"],
        "subject": "hello world",
        "html": "<strong>it works!</strong>",
    }

    email = resend.Emails.send(params)
    print(email)
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/basic_send.py">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/with_attachments.py">
    Send emails with file attachments
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/with_template.py">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/scheduled_send.py">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/audiences.py">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/domains.py">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/inbound.py">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/double_optin_subscribe.py">
    Double opt-in subscription flow
  </Card>

  <Card title="Flask App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/flask_app.py">
    Full Flask web application
  </Card>

  <Card title="FastAPI App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/python-resend-examples/examples/fastapi_app.py">
    Full FastAPI web application
  </Card>

  <Card title="Django App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/python-resend-examples/django_app">
    Full Django web application
  </Card>
</CardGroup>


# Send emails with Rails
Source: https://resend.com/docs/send-with-rails

Learn how to send your first email using Rails and the Resend Ruby SDK.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Ruby SDK.

    <CodeGroup>
      ```bash RubyGems theme={"theme":{"light":"github-light","dark":"vesper"}}
      gem install resend
      ```

      ```bash Gemfile theme={"theme":{"light":"github-light","dark":"vesper"}}
      gem 'resend'
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using Rails Action Mailer">
    This gem can be used as an Action Mailer delivery method.

    First, let's update or create your mailer initializer file with your Resend API Key.

    ```rb config/initializers/mailer.rb theme={"theme":{"light":"github-light","dark":"vesper"}}
    Resend.api_key = "re_xxxxxxxxx"
    ```

    Add these lines of code into your environment config file.

    ```rb config/environments/environment.rb theme={"theme":{"light":"github-light","dark":"vesper"}}
    config.action_mailer.delivery_method = :resend
    ```

    Then create a `UserMailer` class definition.

    ```rb app/mailers/user_mailer.rb theme={"theme":{"light":"github-light","dark":"vesper"}}
    class UserMailer < ApplicationMailer
      default from: 'Acme <onboarding@resend.dev>' # this domain must be verified with Resend
      def welcome_email
        @user = params[:user]
        @url = 'http://example.com/login'
        mail(to: ["delivered@resend.dev"], subject: 'hello world')
      end
    end
    ```

    And create your ERB email template.

    ```html app/views/user_mailer/welcome_email.html.erb theme={"theme":{"light":"github-light","dark":"vesper"}}
    <!doctype html>
    <html>
      <head>
        <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
      </head>
      <body>
        <h1>Welcome to example.com, <%= @user.name %></h1>
        <p>You have successfully signed up to example.com,</p>
        <p>To log in to the site, just follow this link: <%= @url %>.</p>
        <p>Thanks for joining and have a great day!</p>
      </body>
    </html>
    ```

    Initialize your `UserMailer` class. This returns an `ActionMailer::MessageDelivery` instance.

    ```rb theme={"theme":{"light":"github-light","dark":"vesper"}}
    u = User.new name: "derich"
    mailer = UserMailer.with(user: u).welcome_email

    # => #<ActionMailer::MessageDelivery:153700, @mail_message=#<Mail::Message...>, @processed_mailer=...>
    ```

    Finally, you can now send emails using the `deliver_now!` method:

    ```rb theme={"theme":{"light":"github-light","dark":"vesper"}}
    mailer.deliver_now!

    # => {:id=>"a193c81e-9ac5-4708-a569-5caf14220539", :from=>....}
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Rails App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/rails_app">
    Full Rails web application
  </Card>

  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/basic_send.rb">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/with_attachments.rb">
    Send emails with file attachments
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/with_template.rb">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/scheduled_send.rb">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/audiences.rb">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/domains.rb">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/inbound.rb">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/examples/double_optin">
    Double opt-in subscription flow
  </Card>
</CardGroup>


# Send emails using Rails with SMTP
Source: https://resend.com/docs/send-with-rails-smtp

Learn how to integrate Rails with Resend SMTP.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Setup your environment">
    Add these lines of code into your environment config file.

    ```rb config/environments/environment.rb theme={"theme":{"light":"github-light","dark":"vesper"}}
    config.action_mailer.delivery_method = :smtp
    config.action_mailer.smtp_settings = {
      :address   => 'smtp.resend.com',
      :port      => 465,
      :user_name => 'resend',
      :password  => ENV['RESEND_API_KEY'],
      :tls => true
    }
    ```
  </Step>

  <Step title="Send email using Rails Action Mailer">
    Then create a `UserMailer` class definition.

    ```rb app/mailers/user_mailer.rb theme={"theme":{"light":"github-light","dark":"vesper"}}
    class UserMailer < ApplicationMailer
      default from: 'Acme <onboarding@resend.dev>' # this domain must be verified with Resend
      def welcome_email
        @user = params[:user]
        @url = 'http://example.com/login'
        mail(to: ["delivered@resend.dev"], subject: 'hello world')
      end
    end
    ```

    And create your ERB email template.

    ```html app/views/user_mailer/welcome_email.html.erb theme={"theme":{"light":"github-light","dark":"vesper"}}
    <!doctype html>
    <html>
      <head>
        <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
      </head>
      <body>
        <h1>Welcome to example.com, <%= @user.name %></h1>
        <p>You have successfully signed up to example.com,</p>
        <p>To log in to the site, just follow this link: <%= @url %>.</p>
        <p>Thanks for joining and have a great day!</p>
      </body>
    </html>
    ```

    Initialize your `UserMailer` class. This returns an `ActionMailer::MessageDelivery` instance.

    ```rb theme={"theme":{"light":"github-light","dark":"vesper"}}
    u = User.new name: "derich"
    mailer = UserMailer.with(user: u).welcome_email

    # => #<ActionMailer::MessageDelivery:153700, @mail_message=#<Mail::Message...>, @processed_mailer=...>
    ```

    Finally, you can now send emails using the `deliver_now!` method:

    ```rb theme={"theme":{"light":"github-light","dark":"vesper"}}
    mailer.deliver_now!

    # => {:id=>"a193c81e-9ac5-4708-a569-5caf14220539", :from=>....}
    ```
  </Step>
</Steps>

## Examples

<Card title="Rails SMTP Example" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-rails-smtp-example">
  See the full source code.
</Card>


# Send emails with Railway
Source: https://resend.com/docs/send-with-railway

Learn how to send your first email using Railway and the Resend Node.js SDK.

[Railway](https://railway.com/?referralCode=resend) enables you to focus on building product instead of managing infrastructure, automatically scaling to support your needs as you grow.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    We've created a [Resend template](https://railway.com/deploy/resend?referralCode=resend\&utm_medium=integration\&utm_source=template\&utm_campaign=generic) using the Resend Node.js SDK as an introduction to using Resend on Railway.

    To get started, you deploy the template to Railway.

    [![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/resend?referralCode=resend\&utm_medium=integration\&utm_source=template\&utm_campaign=generic)

    <img alt="Deploy button highlighted on Railway" />
  </Step>

  <Step title="Add your API key">
    [Add an API key](https://resend.com/api-keys) from Resend and click **Deploy**.

    <img alt="Template modal with API key field highlighted" />
  </Step>

  <Step title="Send your first email">
    Once your deployment finishes, click the deploy URL to open the app and send your first email.

    <img alt="Deployment link highlighted" />

    While this example uses the [Resend Node.js SDK](https://www.npmjs.com/package/@resend/node), you can add Resend using [any of our Official SDKs](https://resend.com/docs/sdks) that Railway supports.

    <Info>
      Keep in mind that as a basic project, this template sends an email with your
      account each time someone visits your deployment URL, so share the link with
      discretion.
    </Info>

    You can also [set up the project locally](https://docs.railway.com/develop/cli) and make changes to the projectusing the Railway CLI.
  </Step>
</Steps>

## Examples

<Card title="Railway Template" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-node-railway-starter">
  See the full source code.
</Card>


# Send emails with RedwoodJS
Source: https://resend.com/docs/send-with-redwoodjs

Learn how to send your first email using Redwood.js and the Resend Node.js SDK.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend Node.js SDK

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using the [Resend](https://resend.com/) Node.js SDK.
  **Scope:** All AI-generated advice or code related to sending email with Resend must follow these guardrails.

  ***

  ## **1. Official Resend Node.js Setup**

  ### **Prerequisites**

  Human must first create an API key and verify their domain at [https://resend.com/domains](https://resend.com/domains).

  The API key must be stored in an environment variable called `RESEND_API_KEY`.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  The domain should be verified at [https://resend.com/domains](https://resend.com/domains) and added to the `from` address.

  ### **Install the SDK**

  Use the project's existing package manager to install the Resend Node.js SDK.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  # or: yarn add resend / pnpm add resend / bun add resend
  ```

  ### **Initialize the Client**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  ### **Send an Email**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  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);
    return;
  }

  console.log(data); // { id: '49a3999c-...' }
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ### Idempotency

  Best practice: Add an idempotency key to prevent duplicated emails, which is useful for retrying failed emails safely.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**
  * Pattern: `<event-type>/<entity-id>`
  * Example: `welcome-user/123456789`

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Hello World',
    html: '<strong>It works!</strong>',
    idempotencyKey: 'unique-id',
  });
  ```

  ***

  ## **2. Complete `emails.send()` Parameter Reference**

  ### **Required Parameters**

  | Parameter | Type                 | Description                                                                      |
  | --------- | -------------------- | -------------------------------------------------------------------------------- |
  | `from`    | `string`             | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `to`      | `string \| string[]` | Recipient email address(es). Maximum 50 addresses.                               |
  | `subject` | `string`             | Email subject line.                                                              |

  ### **Content Parameters (at least one required)**

  | Parameter | Type              | Description                                                |
  | --------- | ----------------- | ---------------------------------------------------------- |
  | `html`    | `string`          | HTML version of the email body.                            |
  | `text`    | `string`          | Plain text version. Auto-generated from `html` if omitted. |
  | `react`   | `React.ReactNode` | React Email component to render the message. Node.js only. |

  ### **Optional Parameters**

  | Parameter     | Type                 | Description                                                   |
  | ------------- | -------------------- | ------------------------------------------------------------- |
  | `cc`          | `string \| string[]` | Carbon copy recipients.                                       |
  | `bcc`         | `string \| string[]` | Blind carbon copy recipients.                                 |
  | `replyTo`     | `string \| string[]` | Reply-to address(es).                                         |
  | `scheduledAt` | `string`             | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `headers`     | `object`             | Custom email headers as key-value pairs.                      |
  | `tags`        | `Tag[]`              | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `attachments` | `Attachment[]`       | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Parameters**

  | Parameter            | Type     | Description                                                      |
  | -------------------- | -------- | ---------------------------------------------------------------- |
  | `template.id`        | `string` | Published template identifier.                                   |
  | `template.variables` | `object` | Variable substitutions. Key max 50 chars, value max 2,000 chars. |

  If `template` is provided, do not include `html`, `text`, or `react`.

  ### **Response**

  A successful call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: { id: string }, error: null }
  ```

  A failed call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: null, error: { message: string, name: string } }
  ```

  ***

  ## **3. Sending with React Email**

  Resend integrates with [React Email](https://react.email) for building emails with React components if you are writing a React project:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { WelcomeEmail } from './emails/welcome';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    react: WelcomeEmail({ name: 'John' }),
  });
  ```

  **Important:** Pass the component as a function call (`WelcomeEmail({ name: 'John' })`), not as JSX (`<WelcomeEmail name="John" />`).

  For additional help, suggest installing the react-email skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/react-email
  ```

  ***

  ## **4. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **4.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key in an environment variable** (`RESEND_API_KEY`). Never hardcode API keys.
  2. **Import from `resend`** — the package name is `resend`, the class is `Resend`.
  3. **Use `await`** — `resend.emails.send()` returns a Promise. Always use `async/await` or `.then()`.
  4. **Handle both `data` and `error`** — the SDK returns `{ data, error }`. Always check for errors.
  5. **Use a verified domain** in the `from` address for production. `onboarding@resend.dev` is for testing only.
  6. **Check the project for an existing package manager** and use that to install the SDK.
  7. **Use camelCase** for SDK parameters (`replyTo`, `scheduledAt`), not snake\_case.

  ### **4.2 - NEVER DO THE FOLLOWING**

  1. **Do not** hardcode API keys in source code. Always use environment variables.
  2. **Do not** use `try/catch` for error handling with `resend.emails.send()` — the SDK returns `{ data, error }` instead of throwing. Only use `try/catch` if you need to handle network-level failures.
  3. **Do not** use snake\_case parameter names (`reply_to`, `scheduled_at`) — the Node.js SDK uses camelCase (`replyTo`, `scheduledAt`).
  4. **Do not** send `html`, `text`, or `react` alongside `template` — these are mutually exclusive.
  5. **Do not** import from `@resend/node` or any other package name. The correct package is `resend`.
  6. **Do not** use `onboarding@resend.dev` as the `from` address in production code. It is a test-only address.
  7. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses to help you simulate different email events without damaging your domain reputation:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **5. COMMON PATTERNS**

  ### **Attachments**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Invoice attached',
    html: '<p>See attached invoice.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: invoiceBuffer,
      },
    ],
  });
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `scheduledAt` parameter. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Reminder',
    html: '<p>This is your reminder.</p>',
    scheduledAt: '2026-12-25T09:00:00Z',
  });
  ```

  ### **Tags for Tracking**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    html: '<p>Welcome aboard!</p>',
    tags: [
      { name: 'category', value: 'welcome' },
      { name: 'user_id', value: '12345' },
    ],
  });
  ```

  ***

  ## **6. AI MODEL VERIFICATION STEPS**

  Before returning any Resend-related solution, you **must** verify:

  1. **Import**: Is `Resend` imported from `resend`?
  2. **API Key**: Is the key stored in an environment variable, not hardcoded?
  3. **Await**: Is `resend.emails.send()` properly awaited?
  4. **Error Handling**: Is the `{ data, error }` response pattern used?
  5. **Parameters**: Are all parameter names in camelCase?
  6. **From Address**: Is the `from` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help, suggest installing the resend-skills skill and the email-best-practices skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/resend-skills
  npx skills add resend/email-best-practices
  ```

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

### Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Node.js SDK.

    <CodeGroup>
      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn workspace api add resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using HTML">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    yarn rw g function send
    ```

    The easiest way to send an email is by using the `html` parameter.

    ```ts api/src/functions/send/send.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { Resend } from 'resend';
    import type { APIGatewayEvent, Context } from 'aws-lambda';

    const resend = new Resend('re_xxxxxxxxx');

    export const handler = async (event: APIGatewayEvent, context: Context) => {
      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) {
        return {
          statusCode: 500,
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ error }),
        };
      }

      return {
        statusCode: 200,
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ data }),
      };
    };
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Send Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/send.ts">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/sendAttachment.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/sendCid.ts">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/sendTemplate.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/sendScheduled.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/audiencesContacts.ts">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/webhook.ts">
    Handle webhook events
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/redwoodjs-resend-examples/typescript/api/src/functions/doubleOptinSubscribe.ts">
    Double opt-in subscription flow
  </Card>
</CardGroup>


# Send emails with Remix
Source: https://resend.com/docs/send-with-remix

Learn how to send your first email using Remix and the Resend Node.js SDK.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend Node.js SDK

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using the [Resend](https://resend.com/) Node.js SDK.
  **Scope:** All AI-generated advice or code related to sending email with Resend must follow these guardrails.

  ***

  ## **1. Official Resend Node.js Setup**

  ### **Prerequisites**

  Human must first create an API key and verify their domain at [https://resend.com/domains](https://resend.com/domains).

  The API key must be stored in an environment variable called `RESEND_API_KEY`.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  The domain should be verified at [https://resend.com/domains](https://resend.com/domains) and added to the `from` address.

  ### **Install the SDK**

  Use the project's existing package manager to install the Resend Node.js SDK.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  # or: yarn add resend / pnpm add resend / bun add resend
  ```

  ### **Initialize the Client**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  ### **Send an Email**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  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);
    return;
  }

  console.log(data); // { id: '49a3999c-...' }
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ### Idempotency

  Best practice: Add an idempotency key to prevent duplicated emails, which is useful for retrying failed emails safely.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**
  * Pattern: `<event-type>/<entity-id>`
  * Example: `welcome-user/123456789`

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Hello World',
    html: '<strong>It works!</strong>',
    idempotencyKey: 'unique-id',
  });
  ```

  ***

  ## **2. Complete `emails.send()` Parameter Reference**

  ### **Required Parameters**

  | Parameter | Type                 | Description                                                                      |
  | --------- | -------------------- | -------------------------------------------------------------------------------- |
  | `from`    | `string`             | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `to`      | `string \| string[]` | Recipient email address(es). Maximum 50 addresses.                               |
  | `subject` | `string`             | Email subject line.                                                              |

  ### **Content Parameters (at least one required)**

  | Parameter | Type              | Description                                                |
  | --------- | ----------------- | ---------------------------------------------------------- |
  | `html`    | `string`          | HTML version of the email body.                            |
  | `text`    | `string`          | Plain text version. Auto-generated from `html` if omitted. |
  | `react`   | `React.ReactNode` | React Email component to render the message. Node.js only. |

  ### **Optional Parameters**

  | Parameter     | Type                 | Description                                                   |
  | ------------- | -------------------- | ------------------------------------------------------------- |
  | `cc`          | `string \| string[]` | Carbon copy recipients.                                       |
  | `bcc`         | `string \| string[]` | Blind carbon copy recipients.                                 |
  | `replyTo`     | `string \| string[]` | Reply-to address(es).                                         |
  | `scheduledAt` | `string`             | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `headers`     | `object`             | Custom email headers as key-value pairs.                      |
  | `tags`        | `Tag[]`              | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `attachments` | `Attachment[]`       | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Parameters**

  | Parameter            | Type     | Description                                                      |
  | -------------------- | -------- | ---------------------------------------------------------------- |
  | `template.id`        | `string` | Published template identifier.                                   |
  | `template.variables` | `object` | Variable substitutions. Key max 50 chars, value max 2,000 chars. |

  If `template` is provided, do not include `html`, `text`, or `react`.

  ### **Response**

  A successful call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: { id: string }, error: null }
  ```

  A failed call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: null, error: { message: string, name: string } }
  ```

  ***

  ## **3. Sending with React Email**

  Resend integrates with [React Email](https://react.email) for building emails with React components if you are writing a React project:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { WelcomeEmail } from './emails/welcome';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    react: WelcomeEmail({ name: 'John' }),
  });
  ```

  **Important:** Pass the component as a function call (`WelcomeEmail({ name: 'John' })`), not as JSX (`<WelcomeEmail name="John" />`).

  For additional help, suggest installing the react-email skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/react-email
  ```

  ***

  ## **4. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **4.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key in an environment variable** (`RESEND_API_KEY`). Never hardcode API keys.
  2. **Import from `resend`** — the package name is `resend`, the class is `Resend`.
  3. **Use `await`** — `resend.emails.send()` returns a Promise. Always use `async/await` or `.then()`.
  4. **Handle both `data` and `error`** — the SDK returns `{ data, error }`. Always check for errors.
  5. **Use a verified domain** in the `from` address for production. `onboarding@resend.dev` is for testing only.
  6. **Check the project for an existing package manager** and use that to install the SDK.
  7. **Use camelCase** for SDK parameters (`replyTo`, `scheduledAt`), not snake\_case.

  ### **4.2 - NEVER DO THE FOLLOWING**

  1. **Do not** hardcode API keys in source code. Always use environment variables.
  2. **Do not** use `try/catch` for error handling with `resend.emails.send()` — the SDK returns `{ data, error }` instead of throwing. Only use `try/catch` if you need to handle network-level failures.
  3. **Do not** use snake\_case parameter names (`reply_to`, `scheduled_at`) — the Node.js SDK uses camelCase (`replyTo`, `scheduledAt`).
  4. **Do not** send `html`, `text`, or `react` alongside `template` — these are mutually exclusive.
  5. **Do not** import from `@resend/node` or any other package name. The correct package is `resend`.
  6. **Do not** use `onboarding@resend.dev` as the `from` address in production code. It is a test-only address.
  7. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses to help you simulate different email events without damaging your domain reputation:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **5. COMMON PATTERNS**

  ### **Attachments**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Invoice attached',
    html: '<p>See attached invoice.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: invoiceBuffer,
      },
    ],
  });
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `scheduledAt` parameter. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Reminder',
    html: '<p>This is your reminder.</p>',
    scheduledAt: '2026-12-25T09:00:00Z',
  });
  ```

  ### **Tags for Tracking**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    html: '<p>Welcome aboard!</p>',
    tags: [
      { name: 'category', value: 'welcome' },
      { name: 'user_id', value: '12345' },
    ],
  });
  ```

  ***

  ## **6. AI MODEL VERIFICATION STEPS**

  Before returning any Resend-related solution, you **must** verify:

  1. **Import**: Is `Resend` imported from `resend`?
  2. **API Key**: Is the key stored in an environment variable, not hardcoded?
  3. **Await**: Is `resend.emails.send()` properly awaited?
  4. **Error Handling**: Is the `{ data, error }` response pattern used?
  5. **Parameters**: Are all parameter names in camelCase?
  6. **From Address**: Is the `from` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help, suggest installing the resend-skills skill and the email-best-practices skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/resend-skills
  npx skills add resend/email-best-practices
  ```

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Node.js SDK.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install resend
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add resend
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add resend
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using HTML">
    Create a [Resource Route](https://remix.run/docs/en/1.16.1/guides/resource-routes) under `app/routes/send.ts`.

    The easiest way to send an email is by using the `html` parameter.

    <CodeGroup>
      ```ts app/routes/send.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { json } from '@remix-run/node';
      import { Resend } from 'resend';

      const resend = new Resend(process.env.RESEND_API_KEY);

      export const loader = async () => {
        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) {
          return json({ error }, 400);
        }

        return json(data, 200);
      };
      ```
    </CodeGroup>
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Send Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.send.ts">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.send-attachment.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.send-cid.ts">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.send-template.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.send-scheduled.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.audiences.contacts.ts">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/api.webhook.ts">
    Handle webhook events
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/double-optin.tsx">
    Double opt-in subscription flow
  </Card>

  <Card title="Inbound" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/inbound.tsx">
    Receive and process inbound emails
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/remix-resend-examples/typescript/app/routes/prevent-threading.tsx">
    Prevent email threading on Gmail
  </Card>
</CardGroup>


# Send emails using Retool with SMTP
Source: https://resend.com/docs/send-with-retool-smtp

Learn how to integrate Retool with Resend SMTP.

### Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Get the Resend SMTP credentials">
    When configuring your SMTP integration, you'll need to use the following credentials:

    * **Host**: `smtp.resend.com`
    * **Port**: `465`
    * **Username**: `resend`
    * **Password**: `YOUR_API_KEY`
  </Step>

  <Step title="Integrate with Retool SMTP">
    Log into your [Retool](https://retool.com) account and create a new SMTP Resource.

    1. Go to **Resources** and click **Create New**

    <img alt="Retool SMTP - Create new Resources" />

    2. Search for **SMTP** and select it

    <img alt="Retool SMTP - Search for SMTP" />

    3. Add name and SMTP credentials

    <img alt="Retool SMTP - Add SMTP credentials" />
  </Step>
</Steps>


# Send emails with Ruby
Source: https://resend.com/docs/send-with-ruby

Learn how to send your first email using the Resend Ruby SDK.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Ruby SDK.

    <CodeGroup>
      ```bash RubyGems theme={"theme":{"light":"github-light","dark":"vesper"}}
      gem install resend
      ```

      ```bash Gemfile theme={"theme":{"light":"github-light","dark":"vesper"}}
      gem 'resend'
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using HTML">
    The easiest way to send an email is by using the `html` parameter.

    ```rb index.rb theme={"theme":{"light":"github-light","dark":"vesper"}}
    require "resend"

    Resend.api_key = "re_xxxxxxxxx"

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

    sent = Resend::Emails.send(params)
    puts sent
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/basic_send.rb">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/with_attachments.rb">
    Send emails with file attachments
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/with_template.rb">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/scheduled_send.rb">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/audiences.rb">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/domains.rb">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/inbound.rb">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/examples/double_optin">
    Double opt-in subscription flow
  </Card>

  <Card title="Sinatra App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/sinatra_app">
    Full Sinatra web application
  </Card>

  <Card title="Rails App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/rails_app">
    Full Rails web application
  </Card>
</CardGroup>


# Send emails with Rust
Source: https://resend.com/docs/send-with-rust

Learn how to send your first email using the Resend Rust SDK.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    First, create a rust project with cargo and `cd` into it.

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    cargo init resend-rust-example
    cd resend-rust-example
    ```

    Next, add add the Rust Resend SDK as well as [Tokio](https://tokio.rs):

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    cargo add resend-rs
    cargo add tokio -F macros,rt-multi-thread
    ```

    The Rust SDK is Async-first so Tokio is needed.
  </Step>

  <Step title="Send email">
    ```rust theme={"theme":{"light":"github-light","dark":"vesper"}}
    use resend_rs::types::CreateEmailBaseOptions;
    use resend_rs::{Resend, Result};

    #[tokio::main]
    async fn main() -> Result<()> {
      let resend = Resend::new("re_xxxxxxxxx");

      let from = "Acme <onboarding@resend.dev>";
      let to = ["delivered@resend.dev"];
      let subject = "Hello World";

      let email = CreateEmailBaseOptions::new(from, to, subject)
        .with_html("<strong>It works!</strong>");

      let _email = resend.emails.send(email).await?;

      Ok(())
    }
    ```
  </Step>

  <Step title="Reading the API key">
    Instead of using `Resend::new` and hardcoding the API key, the `RESEND_API_KEY` environment variable
    can be used instead. Use `Resend::default()` in that scenario instead.

    Another popular option is to use a `.env` file for environment variables. You can use the
    [`dotenvy`](https://crates.io/crates/dotenvy) crate for that:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    cargo add dotenvy
    ```

    ```rust theme={"theme":{"light":"github-light","dark":"vesper"}}
    // main.rs
    use dotenvy::dotenv;
    use resend_rs::types::CreateEmailBaseOptions;
    use resend_rs::{Resend, Result};

    #[tokio::main]
    async fn main() -> Result<()> {
      let _env = dotenv().unwrap();

      let resend = Resend::default();

      let from = "Acme <onboarding@resend.dev>";
      let to = ["delivered@resend.dev"];
      let subject = "Hello World";

      let email = CreateEmailBaseOptions::new(from, to, subject)
        .with_html("<strong>It works!</strong>");

      let _email = resend.emails.send(email).await?;

      Ok(())
    }
    ```

    ```toml theme={"theme":{"light":"github-light","dark":"vesper"}}
    # .env
    RESEND_API_KEY=re_xxxxxxxxx
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/basic_send.rs">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/with_attachments.rs">
    Send emails with file attachments
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/with_template.rs">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/scheduled_send.rs">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/audiences.rs">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/domains.rs">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/inbound.rs">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/rust-resend-examples/examples/double_optin_subscribe.rs">
    Double opt-in subscription flow
  </Card>

  <Card title="Axum App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/rust-resend-examples/axum_app">
    Full Axum web framework application
  </Card>
</CardGroup>


# Send emails with Sinatra
Source: https://resend.com/docs/send-with-sinatra

Learn how to send your first email using Sinatra and the Resend Ruby SDK.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Ruby SDK.

    <CodeGroup>
      ```bash RubyGems theme={"theme":{"light":"github-light","dark":"vesper"}}
      gem install resend
      ```

      ```bash Gemfile theme={"theme":{"light":"github-light","dark":"vesper"}}
      gem 'resend'
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using HTML">
    The easiest way to send an email is by using the `html` parameter.

    ```rb index.rb theme={"theme":{"light":"github-light","dark":"vesper"}}
    require "sinatra"
    require "resend"

    set :port, 5000
    set :bind, "0.0.0.0"

    Resend.api_key = ENV["RESEND_API_KEY"]

    get "/" do

      content_type :json

      params = {
        from: 'Acme <onboarding@resend.dev>',
        to: ['delivered@resend.dev'],
        subject: 'hello world',
        html: '<strong>it works!</strong>',
      }

      Resend::Emails.send(params).to_hash.to_json
    end
    ```
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Sinatra App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/sinatra_app">
    Full Sinatra web application
  </Card>

  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/basic_send.rb">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/with_attachments.rb">
    Send emails with file attachments
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/with_template.rb">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/scheduled_send.rb">
    Schedule emails for future delivery
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/audiences.rb">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/domains.rb">
    Create and manage sending domains
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/ruby-resend-examples/examples/inbound.rb">
    Receive and process inbound emails
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/examples/double_optin">
    Double opt-in subscription flow
  </Card>
</CardGroup>


# Send emails with SMTP
Source: https://resend.com/docs/send-with-smtp

Learn how to integrate Resend via SMTP.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

Prefer watching a video? Check out our video walkthrough below.

<YouTube />

## SMTP Settings

When configuring your SMTP integration, use the following settings:

* **Host**: `smtp.resend.com`
* **Port**: `25`, `465`, `587`, `2465`, or `2587`
* **Username**: `resend`
* **Password**: `YOUR_API_KEY`

Ports help to instruct the type of security you want to use in your SMTP connection.

| Type     | Port                | Security                                                                  |
| -------- | ------------------- | ------------------------------------------------------------------------- |
| SMTPS    | `465`, `2465`       | Implicit SSL/TLS (Immediately connects via SSL/TLS)                       |
| STARTTLS | `25`, `587`, `2587` | Explicit SSL/TLS (First connects via plaintext, then upgrades to SSL/TLS) |

## Idempotency Key

Idempotency keys are used to prevent duplicate emails. You can add the `Resend-Idempotency-Key` header to your emails sent with SMTP to prevent duplicate emails.

```yaml SMTP {4} theme={"theme":{"light":"github-light","dark":"vesper"}}
From: Acme <onboarding@resend.dev>
To: delivered@resend.dev
Subject: hello world
Resend-Idempotency-Key: welcome-user/123456789

<p>it works!</p>
```

Learn more about [idempotency keys](/docs/dashboard/emails/idempotency-keys).

## Custom Headers

If your SMTP client supports it, you can add custom headers to your emails.

Here are some common use cases for custom headers:

* Prevent threading on Gmail with the `X-Entity-Ref-ID` header
* Include a shortcut for users to unsubscribe with the `List-Unsubscribe` header

## FAQ

Once configured, you can start sending emails via SMTP. Below are some frequently asked questions:

<AccordionGroup>
  <Accordion title="What if I need logs from the server to debug?">
    We currently don't provide SMTP server logs for debugging. If you run into
    issues, please [reach out to support](https://resend.com/help).
  </Accordion>

  <Accordion title="Where do I see the emails sent with SMTP?">
    Emails sent with SMTP will show in your [emails
    table](https://resend.com/emails).
  </Accordion>

  <Accordion title="Does the rate limit apply when sending with SMTP?">
    Yes, the rate limit is the [same as the
    API](https://resend.com/docs/api-reference/introduction#rate-limit).
  </Accordion>
</AccordionGroup>


# Send emails with Supabase Edge Functions
Source: https://resend.com/docs/send-with-supabase-edge-functions

Learn how to send your first email using Supabase Edge Functions.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

Make sure you have the latest version of the [Supabase CLI](https://supabase.com/docs/guides/cli#installation) installed.

## Guide

<Steps>
  <Step title="Create Supabase function">
    Create a new function locally:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    supabase functions new resend
    ```
  </Step>

  <Step title="Edit the handler function">
    Paste the following code into the `index.ts` file:

    ```ts index.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    const RESEND_API_KEY = Deno.env.get('RESEND_API_KEY');

    const handler = async (_request: Request): Promise<Response> => {
      const res = await fetch('https://api.resend.com/emails', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${RESEND_API_KEY}`,
        },
        body: JSON.stringify({
          from: 'Acme <onboarding@resend.dev>',
          to: ['delivered@resend.dev'],
          subject: 'hello world',
          html: '<strong>it works!</strong>',
        }),
      });

      const data = await res.json();

      return new Response(JSON.stringify(data), {
        status: 200,
        headers: {
          'Content-Type': 'application/json',
        },
      });
    };

    Deno.serve(handler);
    ```
  </Step>

  <Step title="Deploy and send email">
    Run function locally:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    supabase functions start
    supabase functions serve resend --no-verify-jwt
    ```

    Deploy function to Supabase:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    supabase functions deploy resend
    ```

    Open the endpoint URL to send an email:

    <img alt="Supabase Edge Functions - Deploy Function" />
  </Step>
</Steps>

## Examples

<Card title="Supabase Edge Functions Example" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-supabase-edge-functions-example">
  See the full source code.
</Card>


# Send emails using Supabase with SMTP
Source: https://resend.com/docs/send-with-supabase-smtp

Learn how to integrate Supabase Auth with Resend SMTP.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Get the Resend SMTP credentials">
    When configuring your SMTP integration, you'll need to use the following credentials:

    * **Host**: `smtp.resend.com`
    * **Port**: `465`
    * **Username**: `resend`
    * **Password**: `YOUR_API_KEY`
  </Step>

  <Step title="Integrate with Supabase SMTP">
    After logging into your Supabase account, you'll need to enable the SMTP integration.

    1. Go to your Supabase project
    2. Click on **Authentication** in the left sidebar
    3. Click **Email** under the **Notifications** section
    4. Click **SMTP Settings**
    5. Add your Sender email and name (these are required fields). For example: `support@example.com` and `ACME Support`.

    <img alt="Supabase Auth - SMTP Sender email and name settings" />

    6. You can copy-and-paste the [SMTP credentials](https://resend.com/settings/smtp) from Resend to Supabase.

    <img alt="Supabase Auth - SMTP Settings" />

    After that, you can click the **Save** button and all of your emails will be sent through Resend.
  </Step>
</Steps>


# Send emails with SvelteKit
Source: https://resend.com/docs/send-with-sveltekit

Learn how to send your first email using SvelteKit and the Resend Node.js SDK.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend Node.js SDK

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using the [Resend](https://resend.com/) Node.js SDK.
  **Scope:** All AI-generated advice or code related to sending email with Resend must follow these guardrails.

  ***

  ## **1. Official Resend Node.js Setup**

  ### **Prerequisites**

  Human must first create an API key and verify their domain at [https://resend.com/domains](https://resend.com/domains).

  The API key must be stored in an environment variable called `RESEND_API_KEY`.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  The domain should be verified at [https://resend.com/domains](https://resend.com/domains) and added to the `from` address.

  ### **Install the SDK**

  Use the project's existing package manager to install the Resend Node.js SDK.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  # or: yarn add resend / pnpm add resend / bun add resend
  ```

  ### **Initialize the Client**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  ### **Send an Email**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  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);
    return;
  }

  console.log(data); // { id: '49a3999c-...' }
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ### Idempotency

  Best practice: Add an idempotency key to prevent duplicated emails, which is useful for retrying failed emails safely.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**
  * Pattern: `<event-type>/<entity-id>`
  * Example: `welcome-user/123456789`

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Hello World',
    html: '<strong>It works!</strong>',
    idempotencyKey: 'unique-id',
  });
  ```

  ***

  ## **2. Complete `emails.send()` Parameter Reference**

  ### **Required Parameters**

  | Parameter | Type                 | Description                                                                      |
  | --------- | -------------------- | -------------------------------------------------------------------------------- |
  | `from`    | `string`             | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `to`      | `string \| string[]` | Recipient email address(es). Maximum 50 addresses.                               |
  | `subject` | `string`             | Email subject line.                                                              |

  ### **Content Parameters (at least one required)**

  | Parameter | Type              | Description                                                |
  | --------- | ----------------- | ---------------------------------------------------------- |
  | `html`    | `string`          | HTML version of the email body.                            |
  | `text`    | `string`          | Plain text version. Auto-generated from `html` if omitted. |
  | `react`   | `React.ReactNode` | React Email component to render the message. Node.js only. |

  ### **Optional Parameters**

  | Parameter     | Type                 | Description                                                   |
  | ------------- | -------------------- | ------------------------------------------------------------- |
  | `cc`          | `string \| string[]` | Carbon copy recipients.                                       |
  | `bcc`         | `string \| string[]` | Blind carbon copy recipients.                                 |
  | `replyTo`     | `string \| string[]` | Reply-to address(es).                                         |
  | `scheduledAt` | `string`             | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `headers`     | `object`             | Custom email headers as key-value pairs.                      |
  | `tags`        | `Tag[]`              | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `attachments` | `Attachment[]`       | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Parameters**

  | Parameter            | Type     | Description                                                      |
  | -------------------- | -------- | ---------------------------------------------------------------- |
  | `template.id`        | `string` | Published template identifier.                                   |
  | `template.variables` | `object` | Variable substitutions. Key max 50 chars, value max 2,000 chars. |

  If `template` is provided, do not include `html`, `text`, or `react`.

  ### **Response**

  A successful call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: { id: string }, error: null }
  ```

  A failed call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: null, error: { message: string, name: string } }
  ```

  ***

  ## **3. Sending with React Email**

  Resend integrates with [React Email](https://react.email) for building emails with React components if you are writing a React project:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { WelcomeEmail } from './emails/welcome';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    react: WelcomeEmail({ name: 'John' }),
  });
  ```

  **Important:** Pass the component as a function call (`WelcomeEmail({ name: 'John' })`), not as JSX (`<WelcomeEmail name="John" />`).

  For additional help, suggest installing the react-email skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/react-email
  ```

  ***

  ## **4. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **4.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key in an environment variable** (`RESEND_API_KEY`). Never hardcode API keys.
  2. **Import from `resend`** — the package name is `resend`, the class is `Resend`.
  3. **Use `await`** — `resend.emails.send()` returns a Promise. Always use `async/await` or `.then()`.
  4. **Handle both `data` and `error`** — the SDK returns `{ data, error }`. Always check for errors.
  5. **Use a verified domain** in the `from` address for production. `onboarding@resend.dev` is for testing only.
  6. **Check the project for an existing package manager** and use that to install the SDK.
  7. **Use camelCase** for SDK parameters (`replyTo`, `scheduledAt`), not snake\_case.

  ### **4.2 - NEVER DO THE FOLLOWING**

  1. **Do not** hardcode API keys in source code. Always use environment variables.
  2. **Do not** use `try/catch` for error handling with `resend.emails.send()` — the SDK returns `{ data, error }` instead of throwing. Only use `try/catch` if you need to handle network-level failures.
  3. **Do not** use snake\_case parameter names (`reply_to`, `scheduled_at`) — the Node.js SDK uses camelCase (`replyTo`, `scheduledAt`).
  4. **Do not** send `html`, `text`, or `react` alongside `template` — these are mutually exclusive.
  5. **Do not** import from `@resend/node` or any other package name. The correct package is `resend`.
  6. **Do not** use `onboarding@resend.dev` as the `from` address in production code. It is a test-only address.
  7. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses to help you simulate different email events without damaging your domain reputation:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **5. COMMON PATTERNS**

  ### **Attachments**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Invoice attached',
    html: '<p>See attached invoice.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: invoiceBuffer,
      },
    ],
  });
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `scheduledAt` parameter. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Reminder',
    html: '<p>This is your reminder.</p>',
    scheduledAt: '2026-12-25T09:00:00Z',
  });
  ```

  ### **Tags for Tracking**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    html: '<p>Welcome aboard!</p>',
    tags: [
      { name: 'category', value: 'welcome' },
      { name: 'user_id', value: '12345' },
    ],
  });
  ```

  ***

  ## **6. AI MODEL VERIFICATION STEPS**

  Before returning any Resend-related solution, you **must** verify:

  1. **Import**: Is `Resend` imported from `resend`?
  2. **API Key**: Is the key stored in an environment variable, not hardcoded?
  3. **Await**: Is `resend.emails.send()` properly awaited?
  4. **Error Handling**: Is the `{ data, error }` response pattern used?
  5. **Parameters**: Are all parameter names in camelCase?
  6. **From Address**: Is the `from` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help, suggest installing the resend-skills skill and the email-best-practices skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/resend-skills
  npx skills add resend/email-best-practices
  ```

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Node.js SDK.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install resend
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add resend
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add resend
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Send email using HTML">
    Create a [+server API route](https://svelte.dev/docs/kit/routing#server) under `src/routes/send/+server.ts`.

    The easiest way to send an email is by using the `html` parameter.

    <CodeGroup>
      ```ts src/routes/send/+server.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { Resend } from 'resend';
      import { RESEND_API_KEY } from '$env/static/private'; // define in your .env file

      const resend = new Resend(RESEND_API_KEY);

      export async function POST() {
        try {
          const { data, error } = await resend.emails.send({
            from: 'Acme <onboarding@resend.dev>',
            to: ['delivered@resend.dev'],
            subject: 'Hello world',
            html: '<p>Hello world</p>',
          });

          if (error) {
            return Response.json({ error }, { status: 500 });
          }

          return Response.json({ data });
        } catch (error) {
          return Response.json({ error }, { status: 500 });
        }
      }
      ```
    </CodeGroup>
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Send Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/send">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/send-attachment">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/send-cid">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/send-template">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/send-scheduled">
    Schedule emails for future delivery
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/send-prevent-threading">
    Prevent email threading on Gmail
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/domains">
    Create and manage sending domains
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/double-optin">
    Double opt-in subscription flow
  </Card>

  <Card title="Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/sveltekit-resend-examples/typescript/src/routes/api/webhook">
    Handle webhook events
  </Card>
</CardGroup>


# Send emails with Symfony
Source: https://resend.com/docs/send-with-symfony

Learn how to send your first email using the Symfony Resend Mailer Bridge.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Mailer Bridge package.

    ```bash Composer theme={"theme":{"light":"github-light","dark":"vesper"}}
    composer require symfony/resend-mailer
    ```

    If your application relies on Resend webhook events, also install the Symfony Webhook Component.

    ```bash Composer theme={"theme":{"light":"github-light","dark":"vesper"}}
    composer require symfony/webhook
    ```
  </Step>

  <Step title="Configuring Mailer">
    In your `.env.local` file, which you can create if needed, add the following:

    ```sh theme={"theme":{"light":"github-light","dark":"vesper"}}
    MAILER_DSN=resend+api://API_KEY@default
    MAILER_RESEND_SECRET=SIGNING_SECRET
    ```

    Replace `API_KEY` with your Resend API key, and `SIGNING_SECRET` with your webhook secret, which can be retrieved from the Resend dashboard after creating a new webhook endpoint (see below).
  </Step>

  <Step title="Send your first email">
    In a controller, inject the `Mailer`:

    ```php theme={"theme":{"light":"github-light","dark":"vesper"}}
    public function __construct(
        private readonly MailerInterface $mailer,
    ) {
    }
    ```

    In a controller action, use the `$this->mailer` to send your email:

    ```php theme={"theme":{"light":"github-light","dark":"vesper"}}
    $this->mailer->send(
        (new Email())
            ->from('Acme <onboarding@resend.dev>')
            ->to('delivered@resend.dev')
            ->subject('Hello world')
            ->html('<strong>it works!</strong>')
    );
    ```

    Learn more about sending emails with Mailer Component in [Symfony's documentation](https://symfony.com/doc/current/mailer.html#creating-sending-messages).
  </Step>

  <Step title="Receive and handle webhooks">
    Thanks to the Webhook Component, you can create a webhook listener.

    ```php src/Webhook/ResendWebhookListener.php theme={"theme":{"light":"github-light","dark":"vesper"}}
    #[AsRemoteEventConsumer('mailer_resend')]
    readonly class ResendWebhookListener implements ConsumerInterface
    {
        public function __construct(
            #[Autowire(param: 'kernel.project_dir')] private string $projectDir,
        ) {
        }

        public function consume(RemoteEvent $event): void
        {
            if ($event instanceof MailerDeliveryEvent) {
                $this->handleMailDelivery($event);
            } elseif ($event instanceof MailerEngagementEvent) {
                $this->handleMailEngagement($event);
            } else {
                // This is not an email event
                return;
            }
        }

        private function handleMailDelivery(MailerDeliveryEvent $event): void
        {
            // Todo
        }

        private function handleMailEngagement(MailerEngagementEvent $event): void
        {
            // Todo
        }
    }
    ```

    Bind your listener to the Webhook routing config:

    ```yaml config/packages/webhook.yaml theme={"theme":{"light":"github-light","dark":"vesper"}}
    framework:
      webhook:
        routing:
          mailer_resend:
            service: 'mailer.webhook.request_parser.resend'
            secret: '%env(MAILER_RESEND_SECRET)%'
    ```

    Next, register your application's webhook endpoint URL (example: `https://{app_domain}/webhook/mailer_resend`) in the [Resend Dashboard](https://resend.com/webhooks):
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="Symfony App" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/symfony_app">
    Full Symfony web application
  </Card>

  <Card title="Basic Send" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/send">
    Basic, batch, and prevent-threading send
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/attachments">
    File attachments and inline images (CID)
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/scheduling">
    Schedule emails for future delivery
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/templates">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/double-optin">
    Double opt-in subscription flow
  </Card>

  <Card title="Inbound Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/inbound">
    Receive and process inbound emails
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/audiences">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/domains">
    Create and manage sending domains
  </Card>
</CardGroup>


# Send emails with TanStack Start
Source: https://resend.com/docs/send-with-tanstack-start

Learn how to send your first email using TanStack Start and the Resend Node.js SDK.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend Node.js SDK

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using the [Resend](https://resend.com/) Node.js SDK.
  **Scope:** All AI-generated advice or code related to sending email with Resend must follow these guardrails.

  ***

  ## **1. Official Resend Node.js Setup**

  ### **Prerequisites**

  Human must first create an API key and verify their domain at [https://resend.com/domains](https://resend.com/domains).

  The API key must be stored in an environment variable called `RESEND_API_KEY`.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  The domain should be verified at [https://resend.com/domains](https://resend.com/domains) and added to the `from` address.

  ### **Install the SDK**

  Use the project's existing package manager to install the Resend Node.js SDK.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  # or: yarn add resend / pnpm add resend / bun add resend
  ```

  ### **Initialize the Client**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  ### **Send an Email**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  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);
    return;
  }

  console.log(data); // { id: '49a3999c-...' }
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ### Idempotency

  Best practice: Add an idempotency key to prevent duplicated emails, which is useful for retrying failed emails safely.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**
  * Pattern: `<event-type>/<entity-id>`
  * Example: `welcome-user/123456789`

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Hello World',
    html: '<strong>It works!</strong>',
    idempotencyKey: 'unique-id',
  });
  ```

  ***

  ## **2. Complete `emails.send()` Parameter Reference**

  ### **Required Parameters**

  | Parameter | Type                 | Description                                                                      |
  | --------- | -------------------- | -------------------------------------------------------------------------------- |
  | `from`    | `string`             | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `to`      | `string \| string[]` | Recipient email address(es). Maximum 50 addresses.                               |
  | `subject` | `string`             | Email subject line.                                                              |

  ### **Content Parameters (at least one required)**

  | Parameter | Type              | Description                                                |
  | --------- | ----------------- | ---------------------------------------------------------- |
  | `html`    | `string`          | HTML version of the email body.                            |
  | `text`    | `string`          | Plain text version. Auto-generated from `html` if omitted. |
  | `react`   | `React.ReactNode` | React Email component to render the message. Node.js only. |

  ### **Optional Parameters**

  | Parameter     | Type                 | Description                                                   |
  | ------------- | -------------------- | ------------------------------------------------------------- |
  | `cc`          | `string \| string[]` | Carbon copy recipients.                                       |
  | `bcc`         | `string \| string[]` | Blind carbon copy recipients.                                 |
  | `replyTo`     | `string \| string[]` | Reply-to address(es).                                         |
  | `scheduledAt` | `string`             | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `headers`     | `object`             | Custom email headers as key-value pairs.                      |
  | `tags`        | `Tag[]`              | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `attachments` | `Attachment[]`       | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Parameters**

  | Parameter            | Type     | Description                                                      |
  | -------------------- | -------- | ---------------------------------------------------------------- |
  | `template.id`        | `string` | Published template identifier.                                   |
  | `template.variables` | `object` | Variable substitutions. Key max 50 chars, value max 2,000 chars. |

  If `template` is provided, do not include `html`, `text`, or `react`.

  ### **Response**

  A successful call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: { id: string }, error: null }
  ```

  A failed call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: null, error: { message: string, name: string } }
  ```

  ***

  ## **3. Sending with React Email**

  Resend integrates with [React Email](https://react.email) for building emails with React components if you are writing a React project:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { WelcomeEmail } from './emails/welcome';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    react: WelcomeEmail({ name: 'John' }),
  });
  ```

  **Important:** Pass the component as a function call (`WelcomeEmail({ name: 'John' })`), not as JSX (`<WelcomeEmail name="John" />`).

  For additional help, suggest installing the react-email skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/react-email
  ```

  ***

  ## **4. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **4.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key in an environment variable** (`RESEND_API_KEY`). Never hardcode API keys.
  2. **Import from `resend`** — the package name is `resend`, the class is `Resend`.
  3. **Use `await`** — `resend.emails.send()` returns a Promise. Always use `async/await` or `.then()`.
  4. **Handle both `data` and `error`** — the SDK returns `{ data, error }`. Always check for errors.
  5. **Use a verified domain** in the `from` address for production. `onboarding@resend.dev` is for testing only.
  6. **Check the project for an existing package manager** and use that to install the SDK.
  7. **Use camelCase** for SDK parameters (`replyTo`, `scheduledAt`), not snake\_case.

  ### **4.2 - NEVER DO THE FOLLOWING**

  1. **Do not** hardcode API keys in source code. Always use environment variables.
  2. **Do not** use `try/catch` for error handling with `resend.emails.send()` — the SDK returns `{ data, error }` instead of throwing. Only use `try/catch` if you need to handle network-level failures.
  3. **Do not** use snake\_case parameter names (`reply_to`, `scheduled_at`) — the Node.js SDK uses camelCase (`replyTo`, `scheduledAt`).
  4. **Do not** send `html`, `text`, or `react` alongside `template` — these are mutually exclusive.
  5. **Do not** import from `@resend/node` or any other package name. The correct package is `resend`.
  6. **Do not** use `onboarding@resend.dev` as the `from` address in production code. It is a test-only address.
  7. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses to help you simulate different email events without damaging your domain reputation:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **5. COMMON PATTERNS**

  ### **Attachments**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Invoice attached',
    html: '<p>See attached invoice.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: invoiceBuffer,
      },
    ],
  });
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `scheduledAt` parameter. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Reminder',
    html: '<p>This is your reminder.</p>',
    scheduledAt: '2026-12-25T09:00:00Z',
  });
  ```

  ### **Tags for Tracking**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    html: '<p>Welcome aboard!</p>',
    tags: [
      { name: 'category', value: 'welcome' },
      { name: 'user_id', value: '12345' },
    ],
  });
  ```

  ***

  ## **6. AI MODEL VERIFICATION STEPS**

  Before returning any Resend-related solution, you **must** verify:

  1. **Import**: Is `Resend` imported from `resend`?
  2. **API Key**: Is the key stored in an environment variable, not hardcoded?
  3. **Await**: Is `resend.emails.send()` properly awaited?
  4. **Error Handling**: Is the `{ data, error }` response pattern used?
  5. **Parameters**: Are all parameter names in camelCase?
  6. **From Address**: Is the `from` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help, suggest installing the resend-skills skill and the email-best-practices skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/resend-skills
  npx skills add resend/email-best-practices
  ```

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install">
    Get the Resend Node.js SDK.

    <CodeGroup>
      ```bash npm theme={"theme":{"light":"github-light","dark":"vesper"}}
      npm install resend
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
      yarn add resend
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
      pnpm add resend
      ```

      ```bash bun theme={"theme":{"light":"github-light","dark":"vesper"}}
      bun add resend
      ```
    </CodeGroup>
  </Step>

  <Step title="Create an email template">
    Start by creating your email template on `src/components/email-template.tsx`.

    ```tsx src/components/email-template.tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
    import * as React from 'react';

    interface EmailTemplateProps {
      firstName: string;
    }

    export function EmailTemplate({ firstName }: EmailTemplateProps) {
      return (
        <div>
          <h1>Welcome, {firstName}!</h1>
        </div>
      );
    }
    ```
  </Step>

  <Step title="Send email using React">
    The recommended approach is a [server function](https://tanstack.com/start/latest/docs/framework/react/guide/server-functions), which runs only on the server and can be called from anywhere in your app. If you'd rather expose a REST endpoint, use a [server route](https://tanstack.com/start/latest/docs/framework/react/guide/server-routes) instead.

    Import the React email template and send an email using the `react` parameter.

    <CodeGroup>
      ```ts src/utils/send-email.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { createServerFn } from '@tanstack/react-start';
      import { Resend } from 'resend';
      import { EmailTemplate } from '../components/email-template';

      const resend = new Resend(process.env.RESEND_API_KEY);

      export const sendEmail = createServerFn({ method: 'POST' }).handler(
        async () => {
          const { data, error } = await resend.emails.send({
            from: 'Acme <onboarding@resend.dev>',
            to: ['delivered@resend.dev'],
            subject: 'Hello world',
            react: EmailTemplate({ firstName: 'John' }),
          });

          if (error) {
            throw error;
          }

          return data;
        },
      );
      ```

      ```ts src/routes/api/send.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
      import { createFileRoute } from '@tanstack/react-router';
      import { Resend } from 'resend';
      import { EmailTemplate } from '../../components/email-template';

      const resend = new Resend(process.env.RESEND_API_KEY);

      export const Route = createFileRoute('/api/send')({
        server: {
          handlers: {
            POST: async () => {
              const { data, error } = await resend.emails.send({
                from: 'Acme <onboarding@resend.dev>',
                to: ['delivered@resend.dev'],
                subject: 'Hello world',
                react: EmailTemplate({ firstName: 'John' }),
              });

              if (error) {
                return Response.json({ error }, { status: 500 });
              }

              return Response.json(data);
            },
          },
        },
      });
      ```
    </CodeGroup>
  </Step>
</Steps>

## Examples

<CardGroup>
  <Card title="TanStack Start (TypeScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/tanstack-resend-examples/typescript">
    Full-stack TanStack Start app with TypeScript
  </Card>

  <Card title="TanStack Start (JavaScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/tanstack-resend-examples/javascript">
    Full-stack TanStack Start app with JavaScript
  </Card>

  <Card title="Send Email" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/send.ts">
    Basic email sending
  </Card>

  <Card title="Attachments" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/send-attachment.ts">
    Send emails with file attachments
  </Card>

  <Card title="Inline Images (CID)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/send-cid.ts">
    Embed inline images using CID
  </Card>

  <Card title="Templates" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/send-template.ts">
    Send emails using Resend hosted templates
  </Card>

  <Card title="Scheduling" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/send-scheduled.ts">
    Schedule emails for future delivery
  </Card>

  <Card title="Batch Emails" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/send-batch.ts">
    Send multiple emails in a single request
  </Card>

  <Card title="Audiences" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/audiences/contacts.ts">
    Manage contacts and audiences
  </Card>

  <Card title="Domains" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/domains.ts">
    Create and manage sending domains
  </Card>

  <Card title="Double Opt-in" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/double-optin.tsx">
    Double opt-in subscription flow
  </Card>

  <Card title="Inbound" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/inbound.tsx">
    Receive and process inbound emails
  </Card>

  <Card title="Prevent Threading" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/prevent-threading.tsx">
    Prevent email threading on Gmail
  </Card>

  <Card title="Webhooks" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/blob/main/tanstack-resend-examples/typescript/src/routes/api/webhook.ts">
    Handle webhook events
  </Card>
</CardGroup>


# Send emails with Vercel Functions
Source: https://resend.com/docs/send-with-vercel-functions

Learn how to send your first email using Vercel Functions.

<Prompt description="Use this pre-built prompt to get started faster." icon="microchip">
  # Send Email with Resend Node.js SDK

  **Purpose:** Enforce only the **current** and **correct** instructions for sending emails using the [Resend](https://resend.com/) Node.js SDK.
  **Scope:** All AI-generated advice or code related to sending email with Resend must follow these guardrails.

  ***

  ## **1. Official Resend Node.js Setup**

  ### **Prerequisites**

  Human must first create an API key and verify their domain at [https://resend.com/domains](https://resend.com/domains).

  The API key must be stored in an environment variable called `RESEND_API_KEY`.

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  The domain should be verified at [https://resend.com/domains](https://resend.com/domains) and added to the `from` address.

  ### **Install the SDK**

  Use the project's existing package manager to install the Resend Node.js SDK.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install resend
  # or: yarn add resend / pnpm add resend / bun add resend
  ```

  ### **Initialize the Client**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';

  const resend = new Resend('YOUR_RESEND_API_KEY');
  ```

  ### **Send an Email**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  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);
    return;
  }

  console.log(data); // { id: '49a3999c-...' }
  ```

  ### Rate Limiting

  The default rate limit is 10 requests per second per team. If you exceed the rate limit, you'll receive a `429` response error code. If needed, you can request a rate increase by [contacting support](https://resend.com/contact).

  ### Idempotency

  Best practice: Add an idempotency key to prevent duplicated emails, which is useful for retrying failed emails safely.

  * Should be **unique per API request**
  * Idempotency keys expire after **24 hours**
  * Have a maximum length of **256 characters**
  * Pattern: `<event-type>/<entity-id>`
  * Example: `welcome-user/123456789`

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Hello World',
    html: '<strong>It works!</strong>',
    idempotencyKey: 'unique-id',
  });
  ```

  ***

  ## **2. Complete `emails.send()` Parameter Reference**

  ### **Required Parameters**

  | Parameter | Type                 | Description                                                                      |
  | --------- | -------------------- | -------------------------------------------------------------------------------- |
  | `from`    | `string`             | Sender email address. Supports friendly name format: `"Name <email@domain.com>"` |
  | `to`      | `string \| string[]` | Recipient email address(es). Maximum 50 addresses.                               |
  | `subject` | `string`             | Email subject line.                                                              |

  ### **Content Parameters (at least one required)**

  | Parameter | Type              | Description                                                |
  | --------- | ----------------- | ---------------------------------------------------------- |
  | `html`    | `string`          | HTML version of the email body.                            |
  | `text`    | `string`          | Plain text version. Auto-generated from `html` if omitted. |
  | `react`   | `React.ReactNode` | React Email component to render the message. Node.js only. |

  ### **Optional Parameters**

  | Parameter     | Type                 | Description                                                   |
  | ------------- | -------------------- | ------------------------------------------------------------- |
  | `cc`          | `string \| string[]` | Carbon copy recipients.                                       |
  | `bcc`         | `string \| string[]` | Blind carbon copy recipients.                                 |
  | `replyTo`     | `string \| string[]` | Reply-to address(es).                                         |
  | `scheduledAt` | `string`             | Schedule delivery time. Accepts ISO 8601 or natural language. |
  | `headers`     | `object`             | Custom email headers as key-value pairs.                      |
  | `tags`        | `Tag[]`              | Custom metadata. Name and value: max 256 chars, ASCII only.   |
  | `attachments` | `Attachment[]`       | File attachments. Max 40MB total per email after encoding.    |

  ### **Template Parameters**

  | Parameter            | Type     | Description                                                      |
  | -------------------- | -------- | ---------------------------------------------------------------- |
  | `template.id`        | `string` | Published template identifier.                                   |
  | `template.variables` | `object` | Variable substitutions. Key max 50 chars, value max 2,000 chars. |

  If `template` is provided, do not include `html`, `text`, or `react`.

  ### **Response**

  A successful call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: { id: string }, error: null }
  ```

  A failed call returns:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  { data: null, error: { message: string, name: string } }
  ```

  ***

  ## **3. Sending with React Email**

  Resend integrates with [React Email](https://react.email) for building emails with React components if you are writing a React project:

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  import { Resend } from 'resend';
  import { WelcomeEmail } from './emails/welcome';

  const resend = new Resend('YOUR_RESEND_API_KEY');

  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    react: WelcomeEmail({ name: 'John' }),
  });
  ```

  **Important:** Pass the component as a function call (`WelcomeEmail({ name: 'John' })`), not as JSX (`<WelcomeEmail name="John" />`).

  For additional help, suggest installing the react-email skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/react-email
  ```

  ***

  ## **4. CRITICAL INSTRUCTIONS FOR AI MODELS**

  ### **4.1 - ALWAYS DO THE FOLLOWING**

  1. **Store the API key in an environment variable** (`RESEND_API_KEY`). Never hardcode API keys.
  2. **Import from `resend`** — the package name is `resend`, the class is `Resend`.
  3. **Use `await`** — `resend.emails.send()` returns a Promise. Always use `async/await` or `.then()`.
  4. **Handle both `data` and `error`** — the SDK returns `{ data, error }`. Always check for errors.
  5. **Use a verified domain** in the `from` address for production. `onboarding@resend.dev` is for testing only.
  6. **Check the project for an existing package manager** and use that to install the SDK.
  7. **Use camelCase** for SDK parameters (`replyTo`, `scheduledAt`), not snake\_case.

  ### **4.2 - NEVER DO THE FOLLOWING**

  1. **Do not** hardcode API keys in source code. Always use environment variables.
  2. **Do not** use `try/catch` for error handling with `resend.emails.send()` — the SDK returns `{ data, error }` instead of throwing. Only use `try/catch` if you need to handle network-level failures.
  3. **Do not** use snake\_case parameter names (`reply_to`, `scheduled_at`) — the Node.js SDK uses camelCase (`replyTo`, `scheduledAt`).
  4. **Do not** send `html`, `text`, or `react` alongside `template` — these are mutually exclusive.
  5. **Do not** import from `@resend/node` or any other package name. The correct package is `resend`.
  6. **Do not** use `onboarding@resend.dev` as the `from` address in production code. It is a test-only address.
  7. **Do not** set up testing flows with fake email addresses. Resend provides the following test addresses to help you simulate different email events without damaging your domain reputation:
     * `delivered@resend.dev`
     * `bounced@resend.dev`
     * `complained@resend.dev`
     * `suppressed@resend.dev`

  ***

  ## **5. COMMON PATTERNS**

  ### **Attachments**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Invoice attached',
    html: '<p>See attached invoice.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: invoiceBuffer,
      },
    ],
  });
  ```

  ### **Scheduled Emails**

  Send up to 30 days in advance using the `scheduledAt` parameter. Accepts ISO 8601 or natural language (e.g. `"in 1 hour"`).

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Reminder',
    html: '<p>This is your reminder.</p>',
    scheduledAt: '2026-12-25T09:00:00Z',
  });
  ```

  ### **Tags for Tracking**

  ```typescript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const { data, error } = await resend.emails.send({
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome',
    html: '<p>Welcome aboard!</p>',
    tags: [
      { name: 'category', value: 'welcome' },
      { name: 'user_id', value: '12345' },
    ],
  });
  ```

  ***

  ## **6. AI MODEL VERIFICATION STEPS**

  Before returning any Resend-related solution, you **must** verify:

  1. **Import**: Is `Resend` imported from `resend`?
  2. **API Key**: Is the key stored in an environment variable, not hardcoded?
  3. **Await**: Is `resend.emails.send()` properly awaited?
  4. **Error Handling**: Is the `{ data, error }` response pattern used?
  5. **Parameters**: Are all parameter names in camelCase?
  6. **From Address**: Is the `from` address using a verified domain (not `onboarding@resend.dev` in production)?

  If any check **fails**, **stop** and revise until compliance is achieved.

  For additional help, suggest installing the resend-skills skill and the email-best-practices skill.

  ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
  npx skills add resend/resend-skills
  npx skills add resend/email-best-practices
  ```

  You can locate framework-specific guides [https://resend.com/docs/llms.txt](https://resend.com/docs/llms.txt)

  For the entire docs for Resend, see [https://resend.com/docs/llms-full.txt](https://resend.com/docs/llms-full.txt)
</Prompt>

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

Make sure you have the latest version of the [Vercel CLI](https://vercel.com/docs/cli#installing-vercel-cli) installed.

## Guide

<Steps>
  <Step title="Install dependencies">
    Install the Resend Node.js SDK:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    npm install resend
    ```
  </Step>

  <Step title="Set up environment variables">
    Add your Resend API key to your environment variables:

    ```bash .env.local theme={"theme":{"light":"github-light","dark":"vesper"}}
    RESEND_API_KEY=re_xxxxxxxxx
    ```
  </Step>

  <Step title="Create a Next.js function">
    Create a route file under `app/api/send/route.ts` if you're using the [App Router](https://nextjs.org/docs/app/building-your-application/routing/router-handlers).

    ```ts route.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    import { Resend } from 'resend';

    const resend = new Resend(process.env.RESEND_API_KEY);

    export async function POST() {
      const response = await resend.emails.send({
        from: 'Acme <onboarding@resend.dev>',
        to: ['delivered@resend.dev'],
        subject: 'hello world',
        html: '<strong>it works!</strong>',
      });

      return Response.json(response, {
        status: response.error ? 500 : 200,
      });
    }
    ```
  </Step>

  <Step title="Send email locally">
    Run function locally:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    npm run dev
    ```

    Open the endpoint URL to send an email: `http://localhost:3000/api/send`
  </Step>

  <Step title="Send email in production">
    Deploy function to Vercel:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    vercel
    ```

    Make sure to add your `RESEND_API_KEY` environment variable in your Vercel project settings.

    Open the endpoint URL to send an email: `https://your-project.vercel.app/api/send`
  </Step>
</Steps>

## Examples

<Card title="Vercel Functions Example" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-vercel-functions-example">
  See the full source code.
</Card>


# Send emails using WordPress with SMTP
Source: https://resend.com/docs/send-with-wordpress-smtp

Learn how to send your first email using Wordpress.

## Prerequisites

Before you start, you'll need:

* A Resend [API key](/docs/create-an-api-key)
* A [verified domain](/docs/add-a-domain)

## Guide

<Steps>
  <Step title="Install a plugin">
    First, you'll need to install and activate the [WP Mail SMTP](https://wordpress.org/plugins/wp-mail-smtp/) plugin. Once the plugin is activated you will see the setup wizard. You can skip this step as we'll guide you through how to configure the plugin for Resend. Click on **Go to the Dashboard** at the bottom of the screen to exit the setup wizard.

    <img alt="WP Mail SMTP - Setup Wizard" />
  </Step>

  <Step title="Configuration">
    From your admin dashboard, visit the **WP Mail SMTP > Settings** page to configure the plugin. Firstly, configure your **From Email**, **From Name**, and **Return Path**. Next, we'll configure the SMTP settings for Resend. Select **Other SMTP** in the **Mailer** section.

    <img alt="WP Mail SMTP - Settings" />

    In the **Other SMTP** section, configure the following settings:

    * **SMTP Host**: `smtp.resend.com`
    * **Encryption**: `SSL`
    * **SMTP Port**: `465`
    * **Auto TLS**: `ON`
    * **Authentication**: `ON`
    * **SMTP Username**: `resend`
    * **SMTP Password**: `YOUR_API_KEY`

    Make sure to replace `YOUR_API_KEY` with an existing key or create a new [API Key](https://resend.com/api-keys).
  </Step>

  <Step title="Sending a test email">
    From your admin dashboard, visit the **WP Mail SMTP > Tools** page to send a test email.

    <img alt="WP Mail SMTP - Send a Test Email" />
  </Step>
</Steps>


# Send emails with v0 and Resend
Source: https://resend.com/docs/v0-integration

Learn how to add the Resend integration to your v0 project.

[v0](https://v0.dev) by Vercel is a platform for building web sites, tools, apps, and projects via chat. You can add Resend in a v0 project by asking the chat to add email sending with Resend.

## Guide

<Steps>
  <Step title="Add your Resend API key">
    To use Resend with v0, you'll need to add a Resend API key, which you can create in the [Resend Dashboard](https://resend.com/api-keys).

    <Note>
      Do not share your API key with others or expose it in the browser or other
      client-side code.
    </Note>

    <img alt="adding the Resend integration to a v0 chat" />
  </Step>

  <Step title="Add a custom domain to your Resend account">
    By default, you can only send emails to your own email address.

    To send emails to other email addresses:

    1. Add a [custom domain to your Resend account](/docs/add-a-domain).
    2. Add the custom domain to the `from` field in the `resend` function in v0 (or ask the chat to update these fields).

    Get more help adding a custom domain in [Resend's documentation](/docs/dashboard/domains/introduction).
  </Step>
</Steps>


# contact.created
Source: https://resend.com/docs/webhooks/contacts/created

Received when a contact is created.

Event triggered whenever a **contact was successfully created**.

*Note: When importing multiple contacts using CSV, these events won't be triggered. [Contact support](https://resend.com/contact) if you have any questions.*

<ResponseBodyParameters type="contact.created">
  <ParamField type="string">
    Unique identifier for the contact
  </ParamField>

  <ParamField type="string">
    Unique identifier for the audience this contact belongs to
  </ParamField>

  <ParamField type="array">
    Array of segment IDs the contact belongs to
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the contact was created
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the contact was last updated
  </ParamField>

  <ParamField type="string">
    Contact's email address
  </ParamField>

  <ParamField type="string">
    Contact's first name
  </ParamField>

  <ParamField type="string">
    Contact's last name
  </ParamField>

  <ParamField type="boolean">
    Whether the contact has unsubscribed from all emails sent from your team
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "contact.created",
    "created_at": "2026-11-17T19:32:22.980Z",
    "data": {
      "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
      "audience_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
      "segment_ids": ["78261eea-8f8b-4381-83c6-79fa7120f1cf"],
      "created_at": "2026-11-17T19:32:22.980Z",
      "updated_at": "2026-11-17T19:32:22.980Z",
      "email": "steve.wozniak@gmail.com",
      "first_name": "Steve",
      "last_name": "Wozniak",
      "unsubscribed": false
    }
  }
  ```
</ResponseExample>


# contact.deleted
Source: https://resend.com/docs/webhooks/contacts/deleted

Received when a contact is deleted.

Event triggered whenever a **contact was successfully deleted**.

<ResponseBodyParameters type="contact.deleted">
  <ParamField type="string">
    Unique identifier for the contact
  </ParamField>

  <ParamField type="string">
    Unique identifier for the audience this contact belongs to
  </ParamField>

  <ParamField type="array">
    Array of segment IDs the contact belongs to
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the contact was created
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the contact was last updated
  </ParamField>

  <ParamField type="string">
    Contact's email address
  </ParamField>

  <ParamField type="string">
    Contact's first name
  </ParamField>

  <ParamField type="string">
    Contact's last name
  </ParamField>

  <ParamField type="boolean">
    Whether the contact has unsubscribed from all emails sent from your team
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "contact.deleted",
    "created_at": "2026-11-17T19:32:22.980Z",
    "data": {
      "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
      "audience_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
      "segment_ids": ["78261eea-8f8b-4381-83c6-79fa7120f1cf"],
      "created_at": "2026-11-10T15:11:59.110Z",
      "updated_at": "2026-11-17T19:32:22.980Z",
      "email": "steve.wozniak@gmail.com",
      "first_name": "Steve",
      "last_name": "Wozniak",
      "unsubscribed": false
    }
  }
  ```
</ResponseExample>


# contact.updated
Source: https://resend.com/docs/webhooks/contacts/updated

Received when a contact is updated.

Event triggered whenever a **contact was successfully updated**.

<ResponseBodyParameters type="contact.updated">
  <ParamField type="string">
    Unique identifier for the contact
  </ParamField>

  <ParamField type="string">
    Unique identifier for the audience this contact belongs to
  </ParamField>

  <ParamField type="array">
    Array of segment IDs the contact belongs to
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the contact was created
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the contact was last updated
  </ParamField>

  <ParamField type="string">
    Contact's email address
  </ParamField>

  <ParamField type="string">
    Contact's first name
  </ParamField>

  <ParamField type="string">
    Contact's last name
  </ParamField>

  <ParamField type="boolean">
    Whether the contact has unsubscribed from all emails sent from your team
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "contact.updated",
    "created_at": "2026-10-11T23:47:56.678Z",
    "data": {
      "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
      "audience_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
      "segment_ids": ["78261eea-8f8b-4381-83c6-79fa7120f1cf"],
      "created_at": "2026-10-10T15:11:54.110Z",
      "updated_at": "2026-10-11T23:47:56.678Z",
      "email": "steve.wozniak@gmail.com",
      "first_name": "Steve",
      "last_name": "Wozniak",
      "unsubscribed": false
    }
  }
  ```
</ResponseExample>


# domain.created
Source: https://resend.com/docs/webhooks/domains/created

Received when a domain is created.

Event triggered when a **domain was successfully created**.

<Info>
  If you're having issues verifying your domain, [review our guide on a domain
  not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying) for
  troubleshooting steps.
</Info>

<ResponseBodyParameters type="domain.created">
  <ParamField type="string">
    Unique identifier for the domain
  </ParamField>

  <ParamField type="string">
    Domain name (e.g., `example.com`)
  </ParamField>

  <ParamField type="verified | partially_verified | partially_failed | failed | pending | not_started">
    Current verification status of the domain:

    * `verified`: The domain is verified and can be used to send or receive emails.
    * `partially_verified`: One capability (send or receive) is verified while the other is still pending verification.
    * `partially_failed`: The domain is verified but one of the features (send or receive) is not verified.
    * `pending`: The domain is pending verification and cannot be used to send or receive emails.
    * `not_started`: Verification has not started yet, so the domain cannot be used to send or receive emails.
    * `failed`: The domain failed verification.

    <Note>
      The `data.status` field represents an aggregated status of the domain. For
      domains that can both [send](/docs/dashboard/emails/introduction) and
      [receive](/docs/dashboard/receiving/introduction) emails, the status may be
      `partially_verified` (one capability verified, the other pending) or
      `partially_failed` (one capability verified, the other failed).
    </Note>
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the domain was created
  </ParamField>

  <ParamField type="us-east-1 | eu-west-1 | sa-east-1 | ap-northeast-1">
    AWS region where the domain is configured.
  </ParamField>

  <ParamField type="object">
    Domain capabilities for sending and receiving emails.

    <Expandable title="properties">
      <ParamField type="enabled | disabled">
        Whether the domain can be used to send emails.
      </ParamField>

      <ParamField type="enabled | disabled">
        Whether the domain can be used to receive emails.
      </ParamField>
    </Expandable>
  </ParamField>

  <ParamField type="array">
    Array of DNS record objects required for domain verification

    <Expandable title="record object">
      <ParamField type="SPF | DKIM | Receiving MX | Tracking">
        Record type purpose. Learn more about [domain verification records](/docs/dashboard/domains/introduction).
      </ParamField>

      <ParamField type="string">
        DNS record name/subdomain
      </ParamField>

      <ParamField type="MX | TXT | CNAME">
        DNS record type
      </ParamField>

      <ParamField type="string">
        DNS record value to be set
      </ParamField>

      <ParamField type="string">
        Time to live for the DNS record
      </ParamField>

      <ParamField type="string">
        Verification status of this specific record
      </ParamField>

      <ParamField type="number">
        Priority value for MX records (optional)
      </ParamField>
    </Expandable>
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "domain.created",
    "created_at": "2026-11-17T19:32:22.980Z",
    "data": {
      "id": "d91cd9bd-1176-453e-8fc1-35364d380206",
      "name": "example.com",
      "status": "not_started",
      "created_at": "2026-04-26T20:21:26.347Z",
      "region": "us-east-1",
      "capabilities": {
        "sending": "enabled",
        "receiving": "disabled"
      },
      "records": [
        {
          "record": "SPF",
          "name": "send",
          "type": "MX",
          "ttl": "Auto",
          "status": "not_started",
          "value": "feedback-smtp.us-east-1.amazonses.com",
          "priority": 10
        },
        {
          "record": "SPF",
          "name": "send",
          "value": "\"v=spf1 include:amazonses.com ~all\"",
          "type": "TXT",
          "ttl": "Auto",
          "status": "not_started"
        },
        {
          "record": "DKIM",
          "name": "resend._domainkey",
          "value": "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsc4Lh8xilsngyKEgN2S84+21gn+x6SEXtjWvPiAAmnmggr5FWG42WnqczpzQ/mNblqHz4CDwUum6LtY6SdoOlDmrhvp5khA3cd661W9FlK3yp7+jVACQElS7d9O6jv8VsBbVg4COess3gyLE5RyxqF1vYsrEXqyM8TBz1n5AGkQIDAQA2",
          "type": "TXT",
          "status": "not_started",
          "ttl": "Auto"
        }
      ]
    }
  }
  ```
</ResponseExample>


# domain.deleted
Source: https://resend.com/docs/webhooks/domains/deleted

Received when a domain is deleted.

Event triggered when a **domain was successfully deleted**.

<Info>
  If you're having issues verifying your domain, [review our guide on a domain
  not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying) for
  troubleshooting steps.
</Info>

<ResponseBodyParameters type="domain.deleted">
  <ParamField type="string">
    Unique identifier for the domain
  </ParamField>

  <ParamField type="string">
    Domain name (e.g., `example.com`)
  </ParamField>

  <ParamField type="verified | partially_verified | partially_failed | failed | pending | not_started">
    Current verification status of the domain:

    * `verified`: The domain is verified and can be used to send or receive emails.
    * `partially_verified`: One capability (send or receive) is verified while the other is still pending verification.
    * `partially_failed`: The domain is verified but one of the features (send or receive) is not verified.
    * `pending`: The domain is pending verification and cannot be used to send or receive emails.
    * `not_started`: Verification has not started yet, so the domain cannot be used to send or receive emails.
    * `failed`: The domain failed verification.

    <Note>
      The `data.status` field represents an aggregated status of the domain. For
      domains that can both [send](/docs/dashboard/emails/introduction) and
      [receive](/docs/dashboard/receiving/introduction) emails, the status may be
      `partially_verified` (one capability verified, the other pending) or
      `partially_failed` (one capability verified, the other failed).
    </Note>
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the domain was created
  </ParamField>

  <ParamField type="us-east-1 | eu-west-1 | sa-east-1 | ap-northeast-1">
    AWS region where the domain is configured.
  </ParamField>

  <ParamField type="object">
    Domain capabilities for sending and receiving emails.

    <Expandable title="properties">
      <ParamField type="enabled | disabled">
        Whether the domain can be used to send emails.
      </ParamField>

      <ParamField type="enabled | disabled">
        Whether the domain can be used to receive emails.
      </ParamField>
    </Expandable>
  </ParamField>

  <ParamField type="array">
    Array of DNS record objects required for domain verification

    <Expandable title="record object">
      <ParamField type="SPF | DKIM | Receiving MX | Tracking">
        Record type purpose. Learn more about [domain verification records](/docs/dashboard/domains/introduction).
      </ParamField>

      <ParamField type="string">
        DNS record name/subdomain
      </ParamField>

      <ParamField type="MX | TXT | CNAME">
        DNS record type
      </ParamField>

      <ParamField type="string">
        DNS record value to be set
      </ParamField>

      <ParamField type="string">
        Time to live for the DNS record
      </ParamField>

      <ParamField type="string">
        Verification status of this specific record
      </ParamField>

      <ParamField type="number">
        Priority value for MX records (optional)
      </ParamField>
    </Expandable>
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "domain.deleted",
    "created_at": "2026-11-17T19:32:22.980Z",
    "data": {
      "id": "d91cd9bd-1176-453e-8fc1-35364d380206",
      "name": "example.com",
      "status": "not_started",
      "created_at": "2026-04-26T20:21:26.347Z",
      "region": "us-east-1",
      "capabilities": {
        "sending": "enabled",
        "receiving": "disabled"
      },
      "records": [
        {
          "record": "SPF",
          "name": "send",
          "type": "MX",
          "ttl": "Auto",
          "status": "not_started",
          "value": "feedback-smtp.us-east-1.amazonses.com",
          "priority": 10
        },
        {
          "record": "SPF",
          "name": "send",
          "value": "\"v=spf1 include:amazonses.com ~all\"",
          "type": "TXT",
          "ttl": "Auto",
          "status": "not_started"
        },
        {
          "record": "DKIM",
          "name": "resend._domainkey",
          "value": "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsc4Lh8xilsngyKEgN2S84+21gn+x6SEXtjWvPiAAmnmggr5FWG42WnqczpzQ/mNblqHz4CDwUum6LtY6SdoOlDmrhvp5khA3cd661W9FlK3yp7+jVACQElS7d9O6jv8VsBbVg4COess3gyLE5RyxqF1vYsrEXqyM8TBz1n5AGkQIDAQA2",
          "type": "TXT",
          "status": "not_started",
          "ttl": "Auto"
        }
      ]
    }
  }
  ```
</ResponseExample>


# domain.updated
Source: https://resend.com/docs/webhooks/domains/updated

Received when a domain is updated.

Event triggered when a **domain was successfully updated**.

<Info>
  If you're having issues verifying your domain, [review our guide on a domain
  not verifying](/docs/knowledge-base/what-if-my-domain-is-not-verifying) for
  troubleshooting steps.
</Info>

<ResponseBodyParameters type="domain.updated">
  <ParamField type="string">
    Unique identifier for the domain
  </ParamField>

  <ParamField type="string">
    Domain name (e.g., `example.com`)
  </ParamField>

  <ParamField type="verified | partially_verified | partially_failed | failed | pending | not_started">
    Current verification status of the domain:

    * `verified`: The domain is verified and can be used to send or receive emails.
    * `partially_verified`: One capability (send or receive) is verified while the other is still pending verification.
    * `partially_failed`: The domain is verified but one of the features (send or receive) is not verified.
    * `pending`: The domain is pending verification and cannot be used to send or receive emails.
    * `not_started`: Verification has not started yet, so the domain cannot be used to send or receive emails.
    * `failed`: The domain failed verification.

    <Note>
      The `data.status` field represents an aggregated status of the domain. For
      domains that can both [send](/docs/dashboard/emails/introduction) and
      [receive](/docs/dashboard/receiving/introduction) emails, the status may be
      `partially_verified` (one capability verified, the other pending) or
      `partially_failed` (one capability verified, the other failed).
    </Note>
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the domain was created
  </ParamField>

  <ParamField type="us-east-1 | eu-west-1 | sa-east-1 | ap-northeast-1">
    AWS region where the domain is configured.
  </ParamField>

  <ParamField type="object">
    Domain capabilities for sending and receiving emails.

    <Expandable title="properties">
      <ParamField type="enabled | disabled">
        Whether the domain can be used to send emails.
      </ParamField>

      <ParamField type="enabled | disabled">
        Whether the domain can be used to receive emails.
      </ParamField>
    </Expandable>
  </ParamField>

  <ParamField type="array">
    Array of DNS record objects required for domain verification

    <Expandable title="record object">
      <ParamField type="SPF | DKIM | Receiving MX | Tracking">
        Record type purpose. Learn more about [domain verification records](/docs/dashboard/domains/introduction).
      </ParamField>

      <ParamField type="string">
        DNS record name/subdomain
      </ParamField>

      <ParamField type="MX | TXT | CNAME">
        DNS record type
      </ParamField>

      <ParamField type="string">
        DNS record value to be set
      </ParamField>

      <ParamField type="string">
        Time to live for the DNS record
      </ParamField>

      <ParamField type="string">
        Verification status of this specific record
      </ParamField>

      <ParamField type="number">
        Priority value for MX records (optional)
      </ParamField>
    </Expandable>
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "domain.updated",
    "created_at": "2026-11-17T19:32:22.980Z",
    "data": {
      "id": "d91cd9bd-1176-453e-8fc1-35364d380206",
      "name": "example.com",
      "status": "not_started",
      "created_at": "2026-04-26T20:21:26.347Z",
      "region": "us-east-1",
      "capabilities": {
        "sending": "enabled",
        "receiving": "enabled"
      },
      "records": [
        {
          "record": "SPF",
          "name": "send",
          "type": "MX",
          "ttl": "Auto",
          "status": "not_started",
          "value": "feedback-smtp.us-east-1.amazonses.com",
          "priority": 10
        },
        {
          "record": "SPF",
          "name": "send",
          "value": "\"v=spf1 include:amazonses.com ~all\"",
          "type": "TXT",
          "ttl": "Auto",
          "status": "not_started"
        },
        {
          "record": "DKIM",
          "name": "resend._domainkey",
          "value": "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsc4Lh8xilsngyKEgN2S84+21gn+x6SEXtjWvPiAAmnmggr5FWG42WnqczpzQ/mNblqHz4CDwUum6LtY6SdoOlDmrhvp5khA3cd661W9FlK3yp7+jVACQElS7d9O6jv8VsBbVg4COess3gyLE5RyxqF1vYsrEXqyM8TBz1n5AGkQIDAQA2",
          "type": "TXT",
          "status": "not_started",
          "ttl": "Auto"
        },
        {
          "name": "inbound.yourdomain.tld",
          "priority": 10,
          "record": "Receiving MX",
          "status": "pending",
          "ttl": "Auto",
          "type": "MX",
          "value": "inbound-smtp.us-east-1.amazonaws.com"
        }
      ]
    }
  }
  ```
</ResponseExample>


# email.bounced
Source: https://resend.com/docs/webhooks/emails/bounced

Received when an email bounces.

Event triggered whenever the recipient's mail server **permanently rejected the email**.

<ResponseBodyParameters type="email.bounced">
  <ParamField type="string">
    Unique identifier for the broadcast campaign (if applicable)
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the email was created
  </ParamField>

  <ParamField type="string">
    Unique identifier for the specific email
  </ParamField>

  <ParamField type="string">
    RFC Message-ID header value for the email
  </ParamField>

  <ParamField type="string">
    Sender's email address. For sent events, this matches the value passed at send time and may include a display name (e.g., `Name <email@domain.com>`). For received events, this is the bare email address only; the display name from the original `From:` header is preserved in `headers.from` on the [retrieve endpoint](/docs/api-reference/emails/retrieve-received-email).
  </ParamField>

  <ParamField type="array">
    Array of impacted recipient email addresses
  </ParamField>

  <ParamField type="string">
    Email subject line
  </ParamField>

  <ParamField type="string">
    Unique identifier for the template used (if applicable)
  </ParamField>

  <ParamField type="Record<string, string>">
    Object of tag key-value pairs associated with the email.

    Example:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "category": "welcome",
      "user_id": "1234567890"
    }
    ```
  </ParamField>

  <ParamField type="object">
    Bounce details from the receiving server

    <Expandable title="bounce object">
      <ParamField type="array">
        Array of SMTP diagnostic responses from the receiving server, including the status code and reason for the bounce (e.g., `smtp; 550 5.5.0 Requested action not taken: mailbox unavailable`)
      </ParamField>

      <ParamField type="string">
        Detailed bounce message from the receiving server
      </ParamField>

      <ParamField type="string">
        Bounce sub-type (e.g., `Suppressed`, `MessageRejected`)
      </ParamField>

      <ParamField type="string">
        Bounce type (e.g., `Permanent`, `Temporary`)
      </ParamField>

      <Info>
        Learn more about [bounce types and subtypes](/docs/dashboard/emails/email-bounces).
      </Info>
    </Expandable>
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "email.bounced",
    "created_at": "2026-11-22T23:41:12.126Z",
    "data": {
      "broadcast_id": "8b146471-e88e-4322-86af-016cd36fd216",
      "created_at": "2026-11-22T23:41:11.894Z",
      "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
      "message_id": "<111-222-333@email.example.com>",
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Sending this example",
      "template_id": "43f68331-0622-4e15-8202-246a0388854b",
      "bounce": {
        "message": "The recipient's email address is on the suppression list because it has a recent history of producing hard bounces.",
        "subType": "Suppressed",
        "type": "Permanent"
      },
      "tags": {
        "category": "confirm_email"
      }
    }
  }
  ```
</ResponseExample>


# email.clicked
Source: https://resend.com/docs/webhooks/emails/clicked

Received when an email link is clicked.

Event triggered whenever the **recipient clicks on an email link**.

<ResponseBodyParameters type="email.clicked">
  <ParamField type="string">
    Unique identifier for the broadcast campaign (if applicable)
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the email was created
  </ParamField>

  <ParamField type="string">
    Unique identifier for the specific email
  </ParamField>

  <ParamField type="string">
    RFC Message-ID header value for the email
  </ParamField>

  <ParamField type="string">
    Sender's email address. For sent events, this matches the value passed at send time and may include a display name (e.g., `Name <email@domain.com>`). For received events, this is the bare email address only; the display name from the original `From:` header is preserved in `headers.from` on the [retrieve endpoint](/docs/api-reference/emails/retrieve-received-email).
  </ParamField>

  <ParamField type="array">
    Array of impacted recipient email addresses
  </ParamField>

  <ParamField type="string">
    Email subject line
  </ParamField>

  <ParamField type="string">
    Unique identifier for the template used (if applicable)
  </ParamField>

  <ParamField type="Record<string, string>">
    Object of tag key-value pairs associated with the email.

    Example:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "category": "welcome",
      "user_id": "1234567890"
    }
    ```
  </ParamField>

  <ParamField type="object">
    Click tracking details

    <Expandable title="click object">
      <ParamField type="string">
        IP address of the user who clicked the link
      </ParamField>

      <ParamField type="string">
        The URL that was clicked
      </ParamField>

      <ParamField type="string">
        ISO 8601 timestamp when the click occurred
      </ParamField>

      <ParamField type="string">
        User agent string of the browser that clicked the link
      </ParamField>
    </Expandable>
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "email.clicked",
    "created_at": "2026-11-22T23:41:12.126Z",
    "data": {
      "broadcast_id": "8b146471-e88e-4322-86af-016cd36fd216",
      "created_at": "2026-11-22T23:41:11.894Z",
      "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
      "message_id": "<111-222-333@email.example.com>",
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "click": {
        "ipAddress": "122.115.53.11",
        "link": "https://resend.com",
        "timestamp": "2026-11-24T05:00:57.163Z",
        "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15"
      },
      "subject": "Sending this example",
      "template_id": "43f68331-0622-4e15-8202-246a0388854b",
      "tags": {
        "category": "confirm_email"
      }
    }
  }
  ```
</ResponseExample>


# email.complained
Source: https://resend.com/docs/webhooks/emails/complained

Received when an email is marked as spam.

Event triggered whenever the email was successfully **delivered, but the recipient marked it as spam**.

<ResponseBodyParameters type="email.complained">
  <ParamField type="string">
    Unique identifier for the broadcast campaign (if applicable)
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the email was created
  </ParamField>

  <ParamField type="string">
    Unique identifier for the specific email
  </ParamField>

  <ParamField type="string">
    RFC Message-ID header value for the email
  </ParamField>

  <ParamField type="string">
    Sender's email address. For sent events, this matches the value passed at send time and may include a display name (e.g., `Name <email@domain.com>`). For received events, this is the bare email address only; the display name from the original `From:` header is preserved in `headers.from` on the [retrieve endpoint](/docs/api-reference/emails/retrieve-received-email).
  </ParamField>

  <ParamField type="array">
    Array of impacted recipient email addresses
  </ParamField>

  <ParamField type="string">
    Email subject line
  </ParamField>

  <ParamField type="string">
    Unique identifier for the template used (if applicable)
  </ParamField>

  <ParamField type="Record<string, string>">
    Object of tag key-value pairs associated with the email.

    Example:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "category": "welcome",
      "user_id": "1234567890"
    }
    ```
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "email.complained",
    "created_at": "2026-02-22T23:41:12.126Z",
    "data": {
      "broadcast_id": "8b146471-e88e-4322-86af-016cd36fd216",
      "created_at": "2026-02-22T23:41:11.894Z",
      "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
      "message_id": "<111-222-333@email.example.com>",
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Sending this example",
      "template_id": "43f68331-0622-4e15-8202-246a0388854b",
      "tags": {
        "category": "confirm_email"
      }
    }
  }
  ```
</ResponseExample>


# email.delivered
Source: https://resend.com/docs/webhooks/emails/delivered

Received when an email is delivered.

Event triggered whenever Resend **successfully delivered the email** to the recipient's mail server.

<Info>
  Learn more about what to do [when an email is delivered, but the recipient
  does not receive
  it](/docs/knowledge-base/what-if-an-email-says-delivered-but-the-recipient-has-not-received-it).
</Info>

<ResponseBodyParameters type="email.delivered">
  <ParamField type="string">
    Unique identifier for the broadcast campaign (if applicable)
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the email was created
  </ParamField>

  <ParamField type="string">
    Unique identifier for the specific email
  </ParamField>

  <ParamField type="string">
    RFC Message-ID header value for the email
  </ParamField>

  <ParamField type="string">
    Sender's email address. For sent events, this matches the value passed at send time and may include a display name (e.g., `Name <email@domain.com>`). For received events, this is the bare email address only; the display name from the original `From:` header is preserved in `headers.from` on the [retrieve endpoint](/docs/api-reference/emails/retrieve-received-email).
  </ParamField>

  <ParamField type="array">
    Array of impacted recipient email addresses
  </ParamField>

  <ParamField type="string">
    Email subject line
  </ParamField>

  <ParamField type="string">
    Unique identifier for the template used (if applicable)
  </ParamField>

  <ParamField type="Record<string, string>">
    Object of tag key-value pairs associated with the email.

    Example:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "category": "welcome",
      "user_id": "1234567890"
    }
    ```
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "email.delivered",
    "created_at": "2026-02-22T23:41:12.126Z",
    "data": {
      "broadcast_id": "8b146471-e88e-4322-86af-016cd36fd216",
      "created_at": "2026-02-22T23:41:11.894Z",
      "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
      "message_id": "<111-222-333@email.example.com>",
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Sending this example",
      "template_id": "43f68331-0622-4e15-8202-246a0388854b",
      "tags": {
        "category": "confirm_email"
      }
    }
  }
  ```
</ResponseExample>


# email.delivery_delayed
Source: https://resend.com/docs/webhooks/emails/delivery-delayed

Received when an email delivery is delayed.

Event triggered whenever the **email couldn't be delivered due to a temporary issue**.

Delivery delays can occur, for example, when the recipient's inbox is full, or when the receiving email server experiences a transient issue.

<ResponseBodyParameters type="email.delivery_delayed">
  <ParamField type="string">
    Unique identifier for the broadcast campaign (if applicable)
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the email was created
  </ParamField>

  <ParamField type="string">
    Unique identifier for the specific email
  </ParamField>

  <ParamField type="string">
    RFC Message-ID header value for the email
  </ParamField>

  <ParamField type="string">
    Sender's email address. For sent events, this matches the value passed at send time and may include a display name (e.g., `Name <email@domain.com>`). For received events, this is the bare email address only; the display name from the original `From:` header is preserved in `headers.from` on the [retrieve endpoint](/docs/api-reference/emails/retrieve-received-email).
  </ParamField>

  <ParamField type="array">
    Array of impacted recipient email addresses
  </ParamField>

  <ParamField type="string">
    Email subject line
  </ParamField>

  <ParamField type="string">
    Unique identifier for the template used (if applicable)
  </ParamField>

  <ParamField type="Record<string, string>">
    Object of tag key-value pairs associated with the email.

    Example:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "category": "welcome",
      "user_id": "1234567890"
    }
    ```
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "email.delivery_delayed",
    "created_at": "2026-02-22T23:41:12.126Z",
    "data": {
      "broadcast_id": "8b146471-e88e-4322-86af-016cd36fd216",
      "created_at": "2026-02-22T23:41:11.894Z",
      "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
      "message_id": "<111-222-333@email.example.com>",
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Sending this example",
      "template_id": "43f68331-0622-4e15-8202-246a0388854b",
      "tags": {
        "category": "confirm_email"
      }
    }
  }
  ```
</ResponseExample>


# email.failed
Source: https://resend.com/docs/webhooks/emails/failed

Received when an email fails to send.

Event triggered whenever the **email failed to send due to an error**.

This event is triggered when there are issues such as invalid recipients, API key problems, domain verification issues, email quota limits, or other sending failures.

<ResponseBodyParameters type="email.failed">
  <ParamField type="string">
    Unique identifier for the broadcast campaign (if applicable)
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the email was created
  </ParamField>

  <ParamField type="string">
    Unique identifier for the specific email
  </ParamField>

  <ParamField type="string">
    RFC Message-ID header value for the email
  </ParamField>

  <ParamField type="string">
    Sender's email address. For sent events, this matches the value passed at send time and may include a display name (e.g., `Name <email@domain.com>`). For received events, this is the bare email address only; the display name from the original `From:` header is preserved in `headers.from` on the [retrieve endpoint](/docs/api-reference/emails/retrieve-received-email).
  </ParamField>

  <ParamField type="array">
    Array of impacted recipient email addresses
  </ParamField>

  <ParamField type="string">
    Email subject line
  </ParamField>

  <ParamField type="string">
    Unique identifier for the template used (if applicable)
  </ParamField>

  <ParamField type="Record<string, string>">
    Object of tag key-value pairs associated with the email.

    Example:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "category": "welcome",
      "user_id": "1234567890"
    }
    ```
  </ParamField>

  <ParamField type="object">
    Failure details

    <Expandable title="failed object">
      <ParamField type="string">
        Reason for the email failure (e.g., `reached_daily_quota`)
      </ParamField>
    </Expandable>
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "email.failed",
    "created_at": "2026-11-22T23:41:12.126Z",
    "data": {
      "broadcast_id": "8b146471-e88e-4322-86af-016cd36fd216",
      "created_at": "2026-11-22T23:41:11.894Z",
      "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
      "message_id": "<111-222-333@email.example.com>",
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Sending this example",
      "template_id": "43f68331-0622-4e15-8202-246a0388854b",
      "failed": {
        "reason": "reached_daily_quota"
      },
      "tags": {
        "category": "confirm_email"
      }
    }
  }
  ```
</ResponseExample>


# email.opened
Source: https://resend.com/docs/webhooks/emails/opened

Received when an email is opened.

Event triggered whenever the **recipient opened the email**.

<Info>
  Open rates are not always accurate. Learn more about [why open rates may not
  be accurate](/docs/knowledge-base/why-are-my-open-rates-not-accurate).
</Info>

<ResponseBodyParameters type="email.opened">
  <ParamField type="string">
    Unique identifier for the broadcast campaign (if applicable)
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the email was created
  </ParamField>

  <ParamField type="string">
    Unique identifier for the specific email
  </ParamField>

  <ParamField type="string">
    RFC Message-ID header value for the email
  </ParamField>

  <ParamField type="string">
    Sender's email address. For sent events, this matches the value passed at send time and may include a display name (e.g., `Name <email@domain.com>`). For received events, this is the bare email address only; the display name from the original `From:` header is preserved in `headers.from` on the [retrieve endpoint](/docs/api-reference/emails/retrieve-received-email).
  </ParamField>

  <ParamField type="array">
    Array of impacted recipient email addresses
  </ParamField>

  <ParamField type="string">
    Email subject line
  </ParamField>

  <ParamField type="string">
    Unique identifier for the template used (if applicable)
  </ParamField>

  <ParamField type="Record<string, string>">
    Object of tag key-value pairs associated with the email.

    Example:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "category": "welcome",
      "user_id": "1234567890"
    }
    ```
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "email.opened",
    "created_at": "2026-02-22T23:41:12.126Z",
    "data": {
      "broadcast_id": "8b146471-e88e-4322-86af-016cd36fd216",
      "created_at": "2026-02-22T23:41:11.894Z",
      "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
      "message_id": "<111-222-333@email.example.com>",
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Sending this example",
      "template_id": "43f68331-0622-4e15-8202-246a0388854b",
      "tags": {
        "category": "confirm_email"
      }
    }
  }
  ```
</ResponseExample>


# email.received
Source: https://resend.com/docs/webhooks/emails/received

Received when an inbound email is received.

Event triggered whenever Resend **successfully receives an email**.

<Info>
  Webhooks do not include the email body, headers, or attachments, only their
  metadata. You must call the [Received emails
  API](/docs/api-reference/emails/retrieve-received-email) or the [Attachments
  API](/docs/api-reference/emails/list-received-email-attachments) to retrieve them.
  This design choice supports large attachments in serverless environments that
  have limited request body sizes.
</Info>

<ResponseBodyParameters type="email.received">
  <ParamField type="string">
    Unique identifier for the broadcast campaign (if applicable)
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the email was created
  </ParamField>

  <ParamField type="string">
    Unique identifier for the specific email
  </ParamField>

  <ParamField type="string">
    RFC Message-ID header value for the email
  </ParamField>

  <ParamField type="string">
    Sender's email address. For sent events, this matches the value passed at send time and may include a display name (e.g., `Name <email@domain.com>`). For received events, this is the bare email address only; the display name from the original `From:` header is preserved in `headers.from` on the [retrieve endpoint](/docs/api-reference/emails/retrieve-received-email).
  </ParamField>

  <ParamField type="array">
    Array of impacted recipient email addresses
  </ParamField>

  <ParamField type="string">
    Email subject line
  </ParamField>

  <ParamField type="string">
    Unique identifier for the template used (if applicable)
  </ParamField>

  <ParamField type="Record<string, string>">
    Object of tag key-value pairs associated with the email.

    Example:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "category": "welcome",
      "user_id": "1234567890"
    }
    ```
  </ParamField>

  <ParamField type="array">
    The recipient addresses the email was forwarded for, taken from the `for` clause of the message's `Received` headers.
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "email.received",
    "created_at": "2026-02-22T23:41:12.126Z",
    "data": {
      "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
      "created_at": "2026-02-22T23:41:11.894Z",
      "from": "onboarding@resend.dev",
      "to": ["delivered@resend.dev"],
      "bcc": [],
      "cc": [],
      "received_for": ["forwarded@example.com"],
      "message_id": "<111-222-333@email.example.com>",
      "subject": "Sending this example",
      "attachments": [
        {
          "id": "2a0c9ce0-3112-4728-976e-47ddcd16a318",
          "filename": "avatar.png",
          "content_type": "image/png",
          "content_disposition": "inline",
          "content_id": "img001"
        }
      ]
    }
  }
  ```
</ResponseExample>


# email.scheduled
Source: https://resend.com/docs/webhooks/emails/scheduled

Received when an email is scheduled to be sent.

Event triggered whenever the **email is scheduled to be sent**.

<ResponseBodyParameters type="email.scheduled">
  <ParamField type="string">
    Unique identifier for the broadcast campaign (if applicable)
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the email was created
  </ParamField>

  <ParamField type="string">
    Unique identifier for the specific email
  </ParamField>

  <ParamField type="string">
    RFC Message-ID header value for the email
  </ParamField>

  <ParamField type="string">
    Sender's email address. For sent events, this matches the value passed at send time and may include a display name (e.g., `Name <email@domain.com>`). For received events, this is the bare email address only; the display name from the original `From:` header is preserved in `headers.from` on the [retrieve endpoint](/docs/api-reference/emails/retrieve-received-email).
  </ParamField>

  <ParamField type="array">
    Array of impacted recipient email addresses
  </ParamField>

  <ParamField type="string">
    Email subject line
  </ParamField>

  <ParamField type="string">
    Unique identifier for the template used (if applicable)
  </ParamField>

  <ParamField type="Record<string, string>">
    Object of tag key-value pairs associated with the email.

    Example:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "category": "welcome",
      "user_id": "1234567890"
    }
    ```
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "email.scheduled",
    "created_at": "2026-02-22T23:41:12.126Z",
    "data": {
      "broadcast_id": "8b146471-e88e-4322-86af-016cd36fd216",
      "created_at": "2026-02-22T23:41:11.894Z",
      "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
      "message_id": "<111-222-333@email.example.com>",
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Sending this example",
      "template_id": "43f68331-0622-4e15-8202-246a0388854b",
      "tags": {
        "category": "confirm_email"
      }
    }
  }
  ```
</ResponseExample>


# email.sent
Source: https://resend.com/docs/webhooks/emails/sent

Received when an email is sent.

Event triggered whenever the **API request was successful**. Resend will attempt to deliver the message to the recipient's mail server.

<ResponseBodyParameters type="email.sent">
  <ParamField type="string">
    Unique identifier for the broadcast campaign (if applicable)
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the email was created
  </ParamField>

  <ParamField type="string">
    Unique identifier for the specific email
  </ParamField>

  <ParamField type="string">
    RFC Message-ID header value for the email
  </ParamField>

  <ParamField type="string">
    Sender's email address. For sent events, this matches the value passed at send time and may include a display name (e.g., `Name <email@domain.com>`). For received events, this is the bare email address only; the display name from the original `From:` header is preserved in `headers.from` on the [retrieve endpoint](/docs/api-reference/emails/retrieve-received-email).
  </ParamField>

  <ParamField type="array">
    Array of impacted recipient email addresses
  </ParamField>

  <ParamField type="string">
    Email subject line
  </ParamField>

  <ParamField type="string">
    Unique identifier for the template used (if applicable)
  </ParamField>

  <ParamField type="Record<string, string>">
    Object of tag key-value pairs associated with the email.

    Example:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "category": "welcome",
      "user_id": "1234567890"
    }
    ```
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "email.sent",
    "created_at": "2026-02-22T23:41:12.126Z",
    "data": {
      "broadcast_id": "8b146471-e88e-4322-86af-016cd36fd216",
      "created_at": "2026-02-22T23:41:11.894Z",
      "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
      "message_id": "<111-222-333@email.example.com>",
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Sending this example",
      "template_id": "43f68331-0622-4e15-8202-246a0388854b",
      "tags": {
        "category": "confirm_email"
      }
    }
  }
  ```
</ResponseExample>


# email.suppressed
Source: https://resend.com/docs/webhooks/emails/suppressed

Received when an email is suppressed.

Event triggered whenever the **email is suppressed** by Resend.

<Info>
  Learn more about [suppressed
  emails](/docs/knowledge-base/why-are-my-emails-landing-on-the-suppression-list).
</Info>

<ResponseBodyParameters type="email.suppressed">
  <ParamField type="string">
    Unique identifier for the broadcast campaign (if applicable)
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the email was created
  </ParamField>

  <ParamField type="string">
    Unique identifier for the specific email
  </ParamField>

  <ParamField type="string">
    RFC Message-ID header value for the email
  </ParamField>

  <ParamField type="string">
    Sender's email address. For sent events, this matches the value passed at send time and may include a display name (e.g., `Name <email@domain.com>`). For received events, this is the bare email address only; the display name from the original `From:` header is preserved in `headers.from` on the [retrieve endpoint](/docs/api-reference/emails/retrieve-received-email).
  </ParamField>

  <ParamField type="array">
    Array of impacted recipient email addresses
  </ParamField>

  <ParamField type="string">
    Email subject line
  </ParamField>

  <ParamField type="string">
    Unique identifier for the template used (if applicable)
  </ParamField>

  <ParamField type="Record<string, string>">
    Object of tag key-value pairs associated with the email.

    Example:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "category": "welcome",
      "user_id": "1234567890"
    }
    ```
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "email.suppressed",
    "created_at": "2026-11-22T23:41:12.126Z",
    "data": {
      "broadcast_id": "8b146471-e88e-4322-86af-016cd36fd216",
      "created_at": "2026-11-22T23:41:11.894Z",
      "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
      "message_id": "<111-222-333@email.example.com>",
      "from": "Acme <onboarding@resend.dev>",
      "to": ["delivered@resend.dev"],
      "subject": "Sending this example",
      "template_id": "43f68331-0622-4e15-8202-246a0388854b",
      "suppressed": {
        "message": "Resend has suppressed sending to this address because it is on the account-level suppression list. This does not count toward your bounce rate metric",
        "type": "OnAccountSuppressionList"
      },
      "tags": {
        "category": "confirm_email"
      }
    }
  }
  ```
</ResponseExample>


# Event Types
Source: https://resend.com/docs/webhooks/event-types

List of supported event types and their payload.

## Email Events

<div>
  <div>
    <div>
      <span />

      [`email.bounced`](/docs/webhooks/emails/bounced)
    </div>

    <div>
      Occurs whenever the recipient's mail server **permanently rejected the
      email**.
    </div>
  </div>

  <div>
    <div>
      <span />

      [`email.clicked`](/docs/webhooks/emails/clicked)
    </div>

    <div>
      Occurs whenever the **recipient clicks on an email link**.
    </div>
  </div>

  <div>
    <div>
      <span />

      [`email.complained`](/docs/webhooks/emails/complained)
    </div>

    <div>
      Occurs whenever the email was successfully **delivered, but the recipient
      marked it as spam**.
    </div>
  </div>

  <div>
    <div>
      <span />

      [`email.delivered`](/docs/webhooks/emails/delivered)
    </div>

    <div>
      Occurs whenever Resend **successfully delivered the email** to the
      recipient's mail server.
    </div>
  </div>

  <div>
    <div>
      <span />

      [`email.delivery_delayed`](/docs/webhooks/emails/delivery-delayed)
    </div>

    <div>
      Occurs whenever the **email couldn't be delivered due to a temporary
      issue**. Delivery delays can occur, for example, when the recipient's
      inbox is full, or when the receiving email server experiences a transient
      issue.
    </div>
  </div>

  <div>
    <div>
      <span />

      [`email.failed`](/docs/webhooks/emails/failed)
    </div>

    <div>
      Occurs whenever the **email failed to send due to an error**. This event
      is triggered when there are issues such as invalid recipients, API key
      problems, domain verification issues, email quota limits, or other sending
      failures.
    </div>
  </div>

  <div>
    <div>
      <span />

      [`email.opened`](/docs/webhooks/emails/opened)
    </div>

    <div>
      Occurs whenever the **recipient opened the email**.
    </div>
  </div>

  <div>
    <div>
      <span />

      [`email.received`](/docs/webhooks/emails/received)
    </div>

    <div>
      Occurs whenever Resend **successfully receives an email**.
    </div>
  </div>

  <div>
    <div>
      <span />

      [`email.scheduled`](/docs/webhooks/emails/scheduled)
    </div>

    <div>
      Occurs whenever the **email is scheduled to be sent**.
    </div>
  </div>

  <div>
    <div>
      <span />

      [`email.sent`](/docs/webhooks/emails/sent)
    </div>

    <div>
      Occurs whenever the **API request was successful**. Resend will attempt to
      deliver the message to the recipient's mail server.
    </div>
  </div>

  <div>
    <div>
      <span />

      [`email.suppressed`](/docs/webhooks/emails/suppressed)
    </div>

    <div>
      Occurs whenever the **email is suppressed** by Resend.
    </div>
  </div>
</div>

## Domain Events

<div>
  <div>
    <div>
      <span />

      [`domain.created`](/docs/webhooks/domains/created)
    </div>

    <div>
      Occurs when a **domain was successfully created**.
    </div>
  </div>

  <div>
    <div>
      <span />

      [`domain.updated`](/docs/webhooks/domains/updated)
    </div>

    <div>
      Occurs when a **domain was successfully updated**.
    </div>
  </div>

  <div>
    <div>
      <span />

      [`domain.deleted`](/docs/webhooks/domains/deleted)
    </div>

    <div>
      Occurs when a **domain was successfully deleted**.
    </div>
  </div>
</div>

## Contact Events

<div>
  <div>
    <div>
      <span />

      [`contact.created`](/docs/webhooks/contacts/created)
    </div>

    <div>
      Occurs whenever a **contact was successfully created**.
    </div>

    <div>
      *Note: When importing multiple contacts using CSV, these events won't be
      triggered. [Contact support](https://resend.com/contact) if you have any
      questions.*
    </div>
  </div>

  <div>
    <div>
      <span />

      [`contact.updated`](/docs/webhooks/contacts/updated)
    </div>

    <div>
      Occurs whenever a **contact was successfully updated**.
    </div>
  </div>

  <div>
    <div>
      <span />

      [`contact.deleted`](/docs/webhooks/contacts/deleted)
    </div>

    <div>
      Occurs whenever a **contact was successfully deleted**.
    </div>
  </div>
</div>

## Suppression Events

<div>
  <div>
    <div>
      <span />

      [`suppression.added`](/docs/webhooks/suppressions/added)
    </div>

    <div>
      Occurs whenever an **email address is added to your suppression list**,
      automatically after a hard bounce or spam complaint, or manually through
      the dashboard or API.
    </div>
  </div>

  <div>
    <div>
      <span />

      [`suppression.removed`](/docs/webhooks/suppressions/removed)
    </div>

    <div>
      Occurs whenever an **email address is removed from your suppression
      list**.
    </div>
  </div>
</div>


# Webhook Ingester
Source: https://resend.com/docs/webhooks/ingester

A self-hosted solution to store all your Resend webhook events in your own database.

The Resend Webhook Ingester is an open-source Next.js application that receives, verifies, and stores all your webhook events in your own database. Deploy it to your infrastructure and gain full control over your email event data.

<Info>
  For more details on why you should store your webhook data, see the [data
  storage guide](/docs/dashboard/webhooks/how-to-store-webhooks-data).
</Info>

## Why use the Webhook Ingester

While you can build your own webhook handler, the Webhook Ingester provides a production-ready solution with:

* **Signature verification** using Svix to ensure webhook authenticity
* **Idempotent storage** that safely handles duplicate webhook deliveries
* **Multiple database support** including PostgreSQL, MySQL, MongoDB, and data warehouses
* **One-click deployment** to Vercel, Railway, or Render

<CardGroup>
  <Card title="GitHub Repository" icon="github" href="https://github.com/resend/resend-webhooks-ingester">
    View the source code and contribute
  </Card>

  <Card title="Docker Image" icon="docker" href="https://ghcr.io/resend/resend-webhooks-ingester">
    Pull the official Docker image
  </Card>
</CardGroup>

## Deploy

Get started in minutes with one-click deployment:

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/resend/resend-webhooks-ingester\&env=RESEND_WEBHOOK_SECRET\&envDescription=Your%20Resend%20webhook%20signing%20secret\&envLink=https://resend.com/webhooks)
[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/cd2lvJ?referralCode=w2CHHM\&utm_medium=integration\&utm_source=template\&utm_campaign=generic)
[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/resend/resend-webhooks-ingester)

Or use Docker:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
docker pull ghcr.io/resend/resend-webhooks-ingester
```

## Supported Databases

| Database    | Endpoint       | Best For                               |
| ----------- | -------------- | -------------------------------------- |
| Supabase    | `/supabase`    | Quick setup with managed Postgres      |
| Neon        | `/neon`        | Serverless Postgres with branching     |
| PostgreSQL  | `/postgresql`  | Self-hosted or managed Postgres        |
| MySQL       | `/mysql`       | Self-hosted or managed MySQL           |
| PlanetScale | `/planetscale` | Serverless MySQL                       |
| MongoDB     | `/mongodb`     | Document database (Atlas, self-hosted) |
| Snowflake   | `/snowflake`   | Data warehousing and analytics         |
| BigQuery    | `/bigquery`    | Google Cloud analytics                 |
| ClickHouse  | `/clickhouse`  | High-performance analytics             |

## Quick Start

<Steps>
  <Step title="Clone and install">
    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    git clone https://github.com/resend/resend-webhooks-ingester.git
    cd resend-webhooks-ingester
    pnpm install
    ```
  </Step>

  <Step title="Configure environment variables">
    Copy the example environment file and add your credentials:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    cp .env.example .env.local
    ```

    At minimum, you need:

    ```env .env.local theme={"theme":{"light":"github-light","dark":"vesper"}}
    # Required: Your Resend webhook signing secret
    RESEND_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxx

    # Database credentials (example for PostgreSQL)
    POSTGRESQL_URL=postgresql://user:password@host:5432/database
    ```

    <Info>
      Get your webhook signing secret from the [Resend
      Dashboard](https://resend.com/webhooks) when creating a webhook.
    </Info>
  </Step>

  <Step title="Set up your database">
    Set up your database and run the provided schema for your database. The ingester supports PostgreSQL, MySQL, MongoDB, and several data warehouses. Schema files can be found in the `schemas/` directory.

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    pnpm db:setup --postgresql
    # or use a different flag for a different database
    ```
  </Step>

  <Step title="Deploy and register webhook">
    Deploy to your preferred platform, then register your webhook endpoint in the [Resend Dashboard](https://resend.com/webhooks) and select all the events you'd like to store.

    Your endpoint URL will be: `https://example.com/{connector}`

    For example: `https://your-app.vercel.app/postgresql`
  </Step>
</Steps>

## Database Schemas

The ingester creates three tables to store webhook events:

| Table                | Description                                                  |
| -------------------- | ------------------------------------------------------------ |
| `resend_wh_emails`   | All email events (sent, delivered, bounced, opened, clicked) |
| `resend_wh_contacts` | Contact events (created, updated, deleted)                   |
| `resend_wh_domains`  | Domain events (created, updated, deleted)                    |

Each table includes:

* `svix_id` - Unique webhook event ID for idempotency
* `event_type` - The type of event (e.g., `email.delivered`)
* `event_created_at` - When the event occurred
* `webhook_received_at` - When the webhook was received
* Event-specific fields (e.g., email details, bounce info, click data)

## Idempotency

The ingester handles duplicate webhooks automatically. Each webhook includes a unique `svix-id` header, and the ingester uses this to ensure events are stored only once.

If Resend retries a webhook delivery (due to a temporary failure), the duplicate will be safely ignored without creating duplicate records in your database.

## Configuration Reference

### Required Environment Variables

| Variable                | Description                             |
| ----------------------- | --------------------------------------- |
| `RESEND_WEBHOOK_SECRET` | Your webhook signing secret from Resend |

### Database-Specific Variables

<AccordionGroup>
  <Accordion title="Supabase">
    ```env theme={"theme":{"light":"github-light","dark":"vesper"}}
    SUPABASE_URL=https://your-project.supabase.co
    SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
    ```
  </Accordion>

  <Accordion title="Neon">
    ```env theme={"theme":{"light":"github-light","dark":"vesper"}}
    NEON_DATABASE_URL=postgresql://user:password@ep-xyz.us-east-1.aws.neon.tech/database?sslmode=require
    ```
  </Accordion>

  <Accordion title="PostgreSQL">
    ```env theme={"theme":{"light":"github-light","dark":"vesper"}}
    POSTGRESQL_URL=postgresql://user:password@host:5432/database
    ```
  </Accordion>

  <Accordion title="MySQL">
    ```env theme={"theme":{"light":"github-light","dark":"vesper"}}
    MYSQL_URL=mysql://user:password@host:3306/database
    ```
  </Accordion>

  <Accordion title="PlanetScale">
    ```env theme={"theme":{"light":"github-light","dark":"vesper"}}
    PLANETSCALE_URL=mysql://username:password@host/database?ssl={"rejectUnauthorized":true}
    ```
  </Accordion>

  <Accordion title="MongoDB">
    ```env theme={"theme":{"light":"github-light","dark":"vesper"}}
    MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/
    MONGODB_DATABASE=resend_webhooks
    ```
  </Accordion>

  <Accordion title="Snowflake">
    ```env theme={"theme":{"light":"github-light","dark":"vesper"}}
    SNOWFLAKE_ACCOUNT=your-account-identifier
    SNOWFLAKE_USERNAME=your-username
    SNOWFLAKE_PASSWORD=your-password
    SNOWFLAKE_DATABASE=your-database
    SNOWFLAKE_SCHEMA=your-schema
    SNOWFLAKE_WAREHOUSE=your-warehouse
    ```
  </Accordion>

  <Accordion title="BigQuery">
    ```env theme={"theme":{"light":"github-light","dark":"vesper"}}
    BIGQUERY_PROJECT_ID=your-project-id
    BIGQUERY_DATASET_ID=your-dataset-id
    BIGQUERY_CREDENTIALS={"type":"service_account","project_id":"..."}
    ```
  </Accordion>

  <Accordion title="ClickHouse">
    ```env theme={"theme":{"light":"github-light","dark":"vesper"}}
    CLICKHOUSE_URL=https://your-instance.clickhouse.cloud:8443
    CLICKHOUSE_USERNAME=default
    CLICKHOUSE_PASSWORD=your-password
    CLICKHOUSE_DATABASE=default
    ```
  </Accordion>
</AccordionGroup>

## Example Queries

Once your data is stored, you can run analytics queries. Here's an example to get email status counts by day:

<CodeGroup>
  ```sql PostgreSQL theme={"theme":{"light":"github-light","dark":"vesper"}}
  SELECT
    DATE(event_created_at) AS day,
    event_type,
    COUNT(*) AS count
  FROM resend_wh_emails
  GROUP BY DATE(event_created_at), event_type
  ORDER BY day DESC, event_type;
  ```

  ```javascript MongoDB theme={"theme":{"light":"github-light","dark":"vesper"}}
  db.resend_wh_emails.aggregate([
    {
      $group: {
        _id: {
          day: {
            $dateToString: { format: '%Y-%m-%d', date: '$event_created_at' },
          },
          event_type: '$event_type',
        },
        count: { $sum: 1 },
      },
    },
    { $sort: { '_id.day': -1 } },
  ]);
  ```

  ```sql ClickHouse theme={"theme":{"light":"github-light","dark":"vesper"}}
  SELECT
    toDate(event_created_at) AS day,
    event_type,
    count() AS count
  FROM resend_wh_emails
  FINAL
  GROUP BY day, event_type
  ORDER BY day DESC, event_type;
  ```
</CodeGroup>

<Info>
  See the
  [queries\_examples.md](https://github.com/resend/resend-webhooks-ingester/blob/main/queries_examples.md)
  file in the repository for more analytics queries including bounce rates, open
  rates, and click-through rates.
</Info>

## Data Retention

By default, webhook events are stored indefinitely. To implement data retention policies, you can set up scheduled jobs to delete old events.

Example for PostgreSQL (delete events older than 90 days):

```sql theme={"theme":{"light":"github-light","dark":"vesper"}}
DELETE FROM resend_wh_emails
WHERE event_created_at < NOW() - INTERVAL '90 days';
```

<Tip>
  For Supabase, use
  [pg\_cron](https://supabase.com/docs/guides/database/extensions/pg_cron) to
  schedule cleanup queries. For MongoDB, consider using [TTL
  indexes](https://www.mongodb.com/docs/manual/core/index-ttl/) or [Atlas
  scheduled
  triggers](https://www.mongodb.com/docs/atlas/app-services/triggers/scheduled-triggers/).
</Tip>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Webhook signature verification failing">
    * Ensure `RESEND_WEBHOOK_SECRET` matches the signing secret in your Resend
      Dashboard - Make sure you're using the raw request body for verification -
      Check that the secret hasn't been rotated in Resend
  </Accordion>

  <Accordion title="Database connection errors">
    * Verify your database credentials are correct - Check that the schema has
      been applied to your database - Ensure your database is accessible from your
      deployment (check firewall rules)
  </Accordion>

  <Accordion title="Webhooks not being received">
    * Verify your endpoint URL is publicly accessible - Check the webhook status
      in your [Resend Dashboard](https://resend.com/webhooks) - Ensure your server
      responds with HTTP 200 for successful requests
  </Accordion>
</AccordionGroup>

## Learn More

<CardGroup>
  <Card title="Webhook Event Types" icon="list" href="/webhooks/event-types">
    View all available webhook event types and their payloads
  </Card>

  <Card title="Verify Webhooks" icon="shield-check" href="/webhooks/verify-webhooks-requests">
    Learn how webhook signature verification works
  </Card>

  <Card title="Retries and Replays" icon="rotate" href="/webhooks/retries-and-replays">
    Understand webhook retry behavior
  </Card>

  <Card title="Storing Webhooks Data" icon="database" href="/dashboard/webhooks/how-to-store-webhooks-data">
    Learn why and how to store your webhook data
  </Card>
</CardGroup>


# Managing Webhooks
Source: https://resend.com/docs/webhooks/introduction

Use webhooks to notify your application about events from Resend.

## Resend webhooks

Resend uses webhooks, which are real-time HTTPS requests that tell your application an event occurred, such as an email delivery notification or subscription status update.

## Why use webhooks

All webhooks use HTTPS and deliver a JSON payload that can be used by your application. You can use webhook feeds to do things like:

* Automatically remove bounced email addresses from mailing lists
* Create alerts in your messaging or incident tools based on event types
* Store all send events in your own database for custom reporting/retention
* Receive emails using [Inbound](/docs/dashboard/receiving/introduction)

<Tip>
  You can [replay any webhook event](/docs/webhooks/retries-and-replays), including
  events that already succeeded. This is useful when your endpoint missed an
  event, or when you want to reprocess events with updated handler code.
</Tip>

## How to receive webhooks

To receive real-time events in your app via webhooks, follow these steps.

Prefer video? Watch the tutorial below.

<YouTube />

<Steps>
  <Step title="Create a dev endpoint to receive requests">
    In your local application, create a new route that can accept POST requests.

    For example, you can add an API route:

    ```js pages/api/webhooks.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
    export default (req, res) => {
      if (req.method === 'POST') {
        const event = req.body;
        console.log(event);
        res.status(200);
      }
    };
    ```

    On receiving an event, respond with an `HTTP 200 OK` to signal to Resend that the event was successfully delivered.

    <Tip>
      For development, you can create a tunnel to your localhost server using a tool like
      [ngrok](https://ngrok.com/download) or [VS Code Port Forwarding](https://code.visualstudio.com/docs/debugtest/port-forwarding). These tools serve your local dev environment at a public URL you can use to test your local webhook endpoint.

      Example: `https://example123.ngrok.io/api/webhook`
    </Tip>

    <Tip>
      The [Resend CLI](/docs/cli) has a built-in `webhooks listen` command that handles
      local webhook development. It starts a server, registers a temporary webhook,
      and streams events to your terminal. See the [CLI reference](/docs/cli#webhooks)
      for setup instructions.
    </Tip>
  </Step>

  <Step title="Add a webhook in Resend">
    Navigate to the [Webhooks page](https://resend.com/webhooks), then select **Add Webhook**.

    1. Add your publicly accessible HTTPS URL
    2. Select all events you want to observe

    <img alt="Add Webhook" />

    <Info>
      Resend also supports managing webhooks via the API or the SDKs. View the [API reference](/docs/api-reference/webhooks/create-webhook) for more details.
    </Info>
  </Step>

  <Step title="Test your local endpoint">
    To ensure your endpoint is successfully receiving events, perform an event you are tracking with your webhook, like sending an email, creating a contact, or creating a domain.

    The webhook will send a JSON payload to your endpoint with the event details. For example:

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "type": "email.bounced",
      "created_at": "2026-11-22T23:41:12.126Z",
      "data": {
        "broadcast_id": "8b146471-e88e-4322-86af-016cd36fd216",
        "created_at": "2026-11-22T23:41:11.894Z",
        "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
        "message_id": "<111-222-333@email.example.com>",
        "from": "Acme <onboarding@resend.dev>",
        "to": ["delivered@resend.dev"],
        "subject": "Sending this example",
        "template_id": "43f68331-0622-4e15-8202-246a0388854b",
        "bounce": {
          "message": "The recipient's email address is on the suppression list because it has a recent history of producing hard bounces.",
          "subType": "Suppressed",
          "type": "Permanent"
        },
        "tags": {
          "category": "confirm_email"
        }
      }
    }
    ```

    You can also see the webhook details in the dashboard.

    <img alt="Webhook Events List" />

    <Info>
      View all possible [event types and their webhook payload
      responses](/docs/webhooks/event-types).
    </Info>
  </Step>

  <Step title="Update and deploy your production endpoint">
    Once you successfully receive events, update your endpoint to process the events.

    For example, update your API route:

    ```js pages/api/webhooks.ts theme={"theme":{"light":"github-light","dark":"vesper"}}

    export default (req:, res) => {
      if (req.method === 'POST') {
        const event = req.body;
        if(event.type === "email.bounced"){
          //
        }
        res.status(200);
      }
    };
    ```

    After you're done testing, deploy your webhook endpoint to production.
  </Step>

  <Step title="Register your production webhook endpoint">
    Once your webhook endpoint is deployed to production, you can register it in the Resend dashboard.
  </Step>
</Steps>

## FAQ

<AccordionGroup>
  <Accordion title="What is the retry schedule?">
    If Resend does not receive a 200 response from a webhook server, we will retry the webhooks.

    Each message is attempted based on the following schedule, where each period is started following the failure of the preceding attempt:

    * 5 seconds
    * 5 minutes
    * 30 minutes
    * 2 hours
    * 5 hours
    * 10 hours

    You can see when a message will be retried next in the webhook message details in the dashboard.
  </Accordion>

  <Accordion title="What IPs do webhooks POST from?">
    If your server requires an allowlist, our webhooks come from the following IP addresses:

    * `44.228.126.217`
    * `50.112.21.217`
    * `52.24.126.164`
    * `54.148.139.208`
    * `2600:1f24:64:8000::/52`
  </Accordion>

  <Accordion title="What are the delivery guarantees?">
    Resend webhooks provide **at-least-once** delivery. Every event will be delivered to your endpoint at least once, but may be delivered more than once in rare cases (such as network timeouts where your server processed the event but the acknowledgement was lost).

    To handle duplicates, use the `svix-id` header included with every webhook request. This is a unique identifier for each event delivery. Store processed `svix-id` values and skip any duplicates.
  </Accordion>

  <Accordion title="Do events arrive in order?">
    Events are sent as they occur, but **delivery order is not guaranteed**. Network conditions, retries, and processing delays can cause events to arrive out of order. For example, an `email.opened` event could arrive before the `email.delivered` event for the same email.

    If ordering matters for your application, use the `created_at` timestamp in the event payload to sort events after receipt.
  </Accordion>

  <Accordion title="Can I replay webhook events manually?">
    Yes. You can replay webhook events manually from the dashboard.

    You can replay both `failed` and `succeeded` events. Replaying successful events is useful when you need to:

    * Backfill your system after an outage on your endpoint.
    * Reprocess events with updated handler code.
    * Send the event to a different endpoint for testing.

    To replay a webhook event, click to see your webhook details
    and then click the link to the event you want to replay.

    On that page, you will see both the payload for the event
    and a button to replay the webhook event and get it sent to
    the configured webhook endpoint.

    For more details, see [Retries and Replays](/docs/webhooks/retries-and-replays).
  </Accordion>
</AccordionGroup>

## Try it yourself

<CardGroup>
  <Card title="Next.js (TypeScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/typescript/src/app/inbound">
    See the full source code.
  </Card>

  <Card title="Next.js (JavaScript)" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/nextjs-resend-examples/javascript/src/app/inbound">
    See the full source code.
  </Card>

  <Card title="PHP" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/php-resend-examples/src/inbound">
    See the full source code.
  </Card>

  <Card title="Laravel" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/laravel-resend-examples">
    See the full source code.
  </Card>

  <Card title="Python" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/python-resend-examples/examples">
    See the full source code.
  </Card>

  <Card title="Ruby" icon="arrow-up-right-from-square" href="https://github.com/resend/resend-examples/tree/main/ruby-resend-examples/examples">
    See the full source code.
  </Card>
</CardGroup>


# Retries and Replays
Source: https://resend.com/docs/webhooks/retries-and-replays

Learn how to use the retries and replays to handle webhook failures.

## Automatic Retries

Resend attempts to deliver each webhook message based on a schedule with exponential backoff.

Each message is attempted based on the following schedule, where each period is started following the failure of the preceding attempt:

* Immediately
* 5 seconds
* 5 minutes
* 30 minutes
* 2 hours
* 5 hours
* 10 hours
* 10 hours (in addition to the previous)

If an endpoint is removed or disabled delivery attempts to the endpoint will be disabled as well.

To see when a message will be retried next, check the webhook message details in the dashboard.

## Failure notifications

When a webhook endpoint starts failing to receive events, Resend sends an email notification to your team. The email includes the endpoint URL, the time of the last failed attempt, and the last HTTP response status code.

If the endpoint continues to fail, Resend will eventually disable it automatically and send a second notification to let you know. Once your endpoint is back up, you can re-enable it from the [Webhooks](https://resend.com/webhooks) page in the dashboard.

For example, an attempt that fails three times before eventually succeeding will be delivered roughly 35 minutes and 5 seconds following the first attempt.

## Manual Replays

If a webhook message fails, you can manually replay it.

You can replay both `failed` and `succeeded` webhook messages.

<img alt="Replay Webhook" />

Here's how to replay a webhook message:

1. Go to the [Webhooks](https://resend.com/webhooks) page
2. Navigate to the Webhook Endpoint you are using
3. Go to the Webhook Message you want to replay
4. Click on the "Replay" button


# suppression.added
Source: https://resend.com/docs/webhooks/suppressions/added

Received when an email address is added to your suppression list.

Event triggered whenever an **email address is added to your suppression
list**. Addresses are added automatically after a hard bounce or spam
complaint, or manually through the dashboard or API.

<ResponseBodyParameters type="suppression.added">
  <ParamField type="string">
    Unique identifier for the suppression
  </ParamField>

  <ParamField type="string">
    The suppressed email address
  </ParamField>

  <ParamField type="string">
    How the address was suppressed: `bounce`, `complaint`, or `manual`
  </ParamField>

  <ParamField type="string | null">
    ID of the email that triggered the suppression. For suppressions with a
    `manual` origin, `source_id` is `null`
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the suppression was created
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "suppression.added",
    "created_at": "2026-11-17T19:32:22.980Z",
    "data": {
      "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
      "email": "steve.wozniak@gmail.com",
      "origin": "bounce",
      "source_id": "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
      "created_at": "2026-11-17T19:32:22.980Z"
    }
  }
  ```
</ResponseExample>


# suppression.removed
Source: https://resend.com/docs/webhooks/suppressions/removed

Received when an email address is removed from your suppression list.

Event triggered whenever an **email address is removed from your suppression
list**.

<ResponseBodyParameters type="suppression.removed">
  <ParamField type="string">
    Unique identifier for the suppression
  </ParamField>

  <ParamField type="string">
    The suppressed email address
  </ParamField>

  <ParamField type="string">
    How the address was suppressed: `bounce`, `complaint`, or `manual`
  </ParamField>

  <ParamField type="string | null">
    ID of the email that triggered the suppression. For suppressions with a
    `manual` origin, `source_id` is `null`
  </ParamField>

  <ParamField type="string">
    ISO 8601 timestamp when the suppression was created
  </ParamField>
</ResponseBodyParameters>

<ResponseExample>
  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "type": "suppression.removed",
    "created_at": "2026-11-17T19:32:22.980Z",
    "data": {
      "id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
      "email": "steve.wozniak@gmail.com",
      "origin": "manual",
      "source_id": null,
      "created_at": "2026-11-15T08:12:45.120Z"
    }
  }
  ```
</ResponseExample>


# Verify Webhooks Requests
Source: https://resend.com/docs/webhooks/verify-webhooks-requests

Learn how to use the signing secret to verify your webhooks.

Webhook signing secrets are used to validate the payload data sent to your application from Resend. You can find the signing secret on the webhook details page.

<img alt="Signing Secret" />

Calls to [create](/docs/api-reference/webhooks/create-webhook), [retrieve](/docs/api-reference/webhooks/get-webhook), or [list](/docs/api-reference/webhooks/list-webhooks) webhooks will also return the signing secret in the response body.

## How to verify webhook requests

To verify the webhook request, you can use the Resend SDK, as in the example below.

<Tip>
  Make sure that you're using the raw request body when verifying webhooks. The
  cryptographic signature is sensitive to even the slightest change. Some
  frameworks parse the request as JSON and then stringify it, and this will also
  break the signature verification.
</Tip>

```js theme={"theme":{"light":"github-light","dark":"vesper"}}
export async function POST(req: NextRequest) {
  try {
    const payload = await req.text();

    // Throws an error if the webhook is invalid
    // Otherwise, returns the parsed payload object
    const result = resend.webhooks.verify({
      payload,
      headers: {
        id: req.headers['svix-id'],
        timestamp: req.headers['svix-timestamp'],
        signature: req.headers['svix-signature'],
      },
      webhookSecret: process.env.RESEND_WEBHOOK_SECRET,
    });

    // Handle the result after validating it
  } catch {
    return new NextResponse('Invalid webhook', { status: 400 });
  }
}
```

Alternatively, you can manually use the Svix libraries and manually pass it the headers, body, and webhook secret. [Learn more and view all supported languages here.](https://docs.svix.com/receiving/verifying-payloads/how)

To verify manually, start by installing the Svix libaries.

<CodeGroup>
  ```sh npm theme={"theme":{"light":"github-light","dark":"vesper"}}
  npm install svix
  ```

  ```sh yarn theme={"theme":{"light":"github-light","dark":"vesper"}}
  yarn add svix
  ```

  ```sh pnpm theme={"theme":{"light":"github-light","dark":"vesper"}}
  pnpm add svix
  ```

  ```sh bun theme={"theme":{"light":"github-light","dark":"vesper"}}
  bun add svix
  ```
</CodeGroup>

Then, verify the webhooks using the code below. The payload is the raw (string) body of the request, and the headers are the headers passed in the request.

```js theme={"theme":{"light":"github-light","dark":"vesper"}}
import { Webhook } from 'svix';

const secret = process.env.WEBHOOK_SECRET;

// These were all sent from the server
const headers = {
  'svix-id': 'msg_p5jXN8AQM9LWM0D4loKWxJek',
  'svix-timestamp': '1614265330',
  'svix-signature': 'v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=',
};
const payload = '{"test": 2432232314}';

const wh = new Webhook(secret);
// Throws on error, returns the verified content on success
wh.verify(payload, headers);
```

If you prefer, you can also [manually verify the headers as well.](https://docs.svix.com/receiving/verifying-payloads/how-manual)

## Why verify webhooks

Webhooks are vulnerable because attackers can send fake HTTP POST requests to endpoints, pretending to be legitimate services. This can lead to security risks or operational issues.

To mitigate this, each webhook and its metadata are signed with a unique key specific to the endpoint. This signature helps verify the source of the webhook, allowing only authenticated webhooks to be processed.

Another security concern is replay attacks, where intercepted valid payloads, complete with their signatures, are resent to endpoints. These payloads would pass the signature verification and be executed, posing a potential security threat.