How to receive emails with Resend

Resend added inbound email in 2025. This guide walks through the MX record, the email.received webhook, fetching the body with the Receiving API, replying in the same thread, and what the 30-day retention means for you.

How Resend receiving works

Receiving in Resend is domain-wide and webhook-driven:

  • You enable Receiving on a verified domain and publish one MX record. Any address on the domain (hello@, support@, anything@) is accepted. There are no per-address routes.
  • Each incoming message creates an email.received webhook event with metadata: email_id, from, to, subject, message_id, and attachment info.
  • Your code calls the Receiving API (GET /emails/receiving/{id}) for the HTML, plain text, and headers, and downloads attachments through temporary signed URLs.
  • Received messages are also listed read-only under Emails → Receiving in the dashboard.

Set up receiving on your domain

  1. Verify the domain for sending first (SPF and DKIM records). Receiving is enabled per domain after verification.
  2. Open Domains → your domain in the Resend dashboard and switch on Receiving.
  3. Add the MX record Resend shows at your DNS provider. The value is specific to your domain and region, so copy it from the dashboard rather than from a tutorial.
  4. Give it the lowest priority value on the domain. If the domain already has MX records for Google Workspace or Microsoft 365, use a subdomain such as mail.yourdomain.com instead of the root.
  5. Click “I've added the record” and send a test email to any address on the domain.
Testing without DNS? Every Resend account can receive on a managed <id>.resend.app address immediately.

Handle the email.received webhook

  1. Create a webhook (dashboard or POST /webhooks) subscribed to email.received. Store the signing_secret it returns.
  2. Verify every request with the svix-id, svix-timestamp, and svix-signature headers against the raw body. Retries reuse the same svix-id, so de-duplicate on it.
  3. Fetch the content with GET /emails/receiving/{email_id}, then save html, text, headers, and message_id.
  4. For each attachment, call the attachments endpoint to get a download URL and store the file yourself. The URLs expire.
// Minimal handler (Node)
const event = resend.webhooks.verify({ payload: rawBody, headers, webhookSecret });
if (event.type === 'email.received') {
  const { data } = await resend.emails.receiving.get(event.data.email_id);
  // data.html, data.text, data.headers, data.message_id, data.attachments[]
}

Reply to a received email in the same thread

There is no reply button in the dashboard. To reply, send a new email through the API from an address on your domain and set the threading headers:

  • In-Reply-To: the message_id of the received email
  • References: all earlier message ids in the conversation, space separated
  • Subject prefixed with Re: so mail clients group the thread

Keep the original message_id per conversation in your database, or follow-up replies will break out of the thread.

Retention, quotas, and limits

ItemResend
Data retention30 days on Free, Pro, and Scale; flexible on Enterprise
Inbound pricingIncluded on all plans; each received email counts toward the plan quota
Free plan quota3,000 emails per month, 100 per day (sent + received)
Address matchingDomain catch-all; filter by recipient in your code
Body in webhookNo; fetch via Receiving API

Compare this with Mailgun, where stored messages last only 3 days and inbound is driven by routes: can Mailgun receive emails?

A simpler way: give the domain an inbox

If the goal is for a person to read and answer mail on hello@ or support@, you do not need to build any of the above. Inboxes connects to your Resend account with an API key, creates the webhook, stores every received message with threads and attachments, and lets you reply from your domain with the threading headers set correctly. The only manual step left is enabling Receiving and adding the MX record in Resend. See Resend webmail: where do received emails go?

Frequently asked questions

Yes. Verify your domain, turn on Receiving for it in the Resend dashboard, and add the MX record Resend shows. From then on, every address on that domain is received and each message fires an email.received webhook. You can also receive without DNS changes on a Resend-managed *.resend.app address.

Read your Mailgun or Resend email in a real inbox

Connect your provider API key and get a Gmail-like inbox for every mailbox. $5/month.

Get started

Related guides