Resend

Email adapter for Chat SDK powered by Resend. Receive inbound emails via webhooks, send rich HTML replies, and proactively start email threads with `openDM`.

Vendor-official adapter maintained by Resend, not Vercel or Chat SDK contributors. For feature requests, bug reports, and support, file an issue on the adapter's repo.

Install

pnpm add @resend/chat-sdk-adapter chat @chat-adapter/shared

Quick start

lib/bot.ts
import { Chat } from "chat";
import { MemoryStateAdapter } from "@chat-adapter/state-memory";
import { createResendAdapter } from "@resend/chat-sdk-adapter";

const resend = createResendAdapter({
  fromAddress: "bot@yourdomain.com",
  fromName: "My Bot", // optional
  // apiKey: "re_...",            // or set RESEND_API_KEY
  // webhookSecret: "whsec_...",  // or set RESEND_WEBHOOK_SECRET
});

const chat = new Chat({
  userName: "email-bot",
  adapters: { resend },
  state: new MemoryStateAdapter(),
});

// New inbound email starts a 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 Resend webhooks to your server's webhook endpoint — the adapter verifies signatures and routes events into the Chat SDK handler pipeline. See the examples/basic folder in the adapter repo for a full working server.

Configuration

Prop

Type

Environment variables

VariableDescription
RESEND_API_KEYResend API key. Overridden by config.apiKey.
RESEND_WEBHOOK_SECRETWebhook signing secret. Overridden by config.webhookSecret.
FROM_ADDRESSUsed by example apps only.

Email threading

Threads are resolved using the standard Message-ID, In-Reply-To, and References email headers. Reply chains are automatically grouped into Chat SDK threads — your handlers receive each follow-up as a onSubscribedMessage event on the same thread.

Sending email proactively

Use openDM to start a new email thread to any address — useful for notifications, alerts, or scheduled reports:

const threadId = await chat.adapters.resend.openDM("user@example.com");
const thread = await chat.thread("resend", threadId);
await thread.post("Hello from the bot!");

Rich card emails

Post a Chat SDK card and the adapter renders it to HTML email through @react-email/components:

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",
});

Attachments

Inbound email attachments are exposed on message.raw.attachments as objects with filename, content_type, and url fields — your handler can fetch the URL or hand it off to downstream processing.

Limitations

Email is inherently one-shot. The following operations throw NotImplementedError:

  • editMessage / deleteMessage
  • addReaction / removeReaction
  • startTyping

There are no native concepts for typing indicators, reactions, or message edits in email — use cards or new replies instead.

Examples

ExampleDescription
basicEcho bot — replies to every email
welcome-cardsSends a styled card email on first contact
notificationsProactive emails via openDM() + HTTP POST
support-botMulti-turn support with subscribe/unsubscribe
attachmentsDetects attachments and replies with a summary

Official docs are available at resend.com/docs/chat-sdk.

Feature support

Messaging

FeatureSupported
Post message
Edit message
Delete message
File uploadsInbound only
Streaming
Scheduled messages

Rich content

FeatureSupported
Card formatHTML email via react-email
Buttons
Link buttons
Select menus
Tables
Fields
Images in cards
Modals

Conversations

FeatureSupported
Slash commands
Mentions
Add reactions
Remove reactions
Typing indicator
DMs
Ephemeral messages
User lookup
Parent subject
Native client
Custom API endpoint

Message history

FeatureSupported
Fetch messages
Fetch single message
Fetch thread info
Fetch channel messages
List threads
Fetch channel info
Post channel message

On this page