Resend: Sending and Receiving Email From Your App
What it does
Resend sends email for your app: a morning list of COIs about to expire, a schedule change to a flooring sub, a change order summary to yourself. It can also receive email, so when a sub replies, the reply lands in that job's history.
What it costs
- Free: $0 a month for 3,000 emails, with a limit of 100 a day. 3 domains. Receiving email is included, and each email you receive counts toward the monthly total.
- Pro: $20 a month for 50,000 emails, no daily limit, 10 domains. If you turn on overages, extra emails are $0.90 per 1,000.
- Scale: from $90 a month.
- You start paying past 100 emails in a day or 3,000 in a month. Most single-shop tools stay free a long time.
A 10-minute setup (plus DNS time)
Where your keys go. Every service here gives you secret keys. Keep them in exactly two places: your password manager, and your app's settings.
- If an AI agent with its own cloud computer builds for you (like Grok Bot): paste each key into the agent's secret card or Secrets section, never into the chat. Saved values can't be read back, so keep your own copy.
- If you build in a folder on your own computer: put keys in a
.env.localfile, and make sure.gitignorelists.env*before your first save.- On Vercel: add the same keys under Settings, Environment Variables, then redeploy.
Never put a key in a screenshot, an email, or browser code. Anything starting with
NEXT_PUBLIC_is readable by anyone.
- Sign up at resend.com.
- Create an API key and save it in your settings as
RESEND_API_KEY. - Domains, Add Domain. Use a subdomain like
updates.yourcompany.com, so app mail doesn't touch your main email. - Add the DNS records Resend shows you at your domain host (GoDaddy, Namecheap, Cloudflare, and so on), exactly as shown.
- Click Verify. Often about 15 minutes, but DNS can take up to 72 hours.
- Meanwhile, send a test from
onboarding@resend.devto your own email.
Common mistakes and gotchas
- The test address only sends to you. Anyone else gets a 403 error. You need a verified domain to email subs or adjusters.
- Don't add Resend's receiving record to your main domain if your office email runs on it. Use a subdomain, or your normal email can break.
- 100 a day is the free limit. A big batch of reminders can hit it.
- Check that incoming email really came from Resend (signature check with your webhook signing secret).
- Why not SendGrid? SendGrid ended its free plan starting May 27, 2025. It now offers a 60-day trial, then plans from $19.95 a month.
Where it fits in your build
Add your sending subdomain early, because DNS can take up to 72 hours. Send alerts to yourself first (like a morning list of expiring COIs). Add receiving and the email.received webhook only after the app is live.
Sources
- Resend pricing (Free 3,000 emails a month, 100 a day, 3 domains, receiving included; Pro $20 for 50,000 or $35 for 100,000, 10 domains, $0.90 per extra 1,000 when overages are turned on; Scale from $90; received emails count toward the quota): https://resend.com/pricing (checked October 7, 2026)
- Adding a domain (often verifies within 15 minutes, DNS can take up to 72 hours): https://resend.com/docs/add-a-domain (checked October 7, 2026)
- Domains overview (subdomain recommended): https://resend.com/docs/dashboard/domains/introduction (checked October 7, 2026)
- resend.dev only sends to you: https://resend.com/docs/knowledge-base/403-error-resend-dev-domain (checked October 2, 2026)
- Sending with Node.js: https://resend.com/docs/send-with-nodejs (checked October 2, 2026)
- Receiving emails (
.resend.appaddress,email.receivedwebhook, body fetched separately): https://resend.com/docs/dashboard/receiving/introduction (checked October 2, 2026) - Custom receiving domains (MX record, use a subdomain if you already have mail): https://resend.com/docs/dashboard/receiving/custom-domains (checked October 2, 2026)
- Verifying webhooks (signing secret, raw body): https://resend.com/docs/dashboard/webhooks/verify-webhooks-requests (checked October 2, 2026)
- API key permissions (Full access, Sending access): https://resend.com/changelog/new-api-key-permissions (via search summary, October 2, 2026)
- SendGrid free plan retirement (starting May 27, 2025): https://www.twilio.com/en-us/changelog/sendgrid-free-plan (checked October 7, 2026)
- SendGrid pricing (60-day trial at 100 emails a day; Essentials from $19.95 a month): https://www.twilio.com/en-us/products/email-api/pricing (checked October 7, 2026)
Last checked: October 7, 2026
Full article
What email does for a restoration or remodeling app
Texts are for quick back-and-forth. Email is for the things you want on record:
- Alerts to yourself: "3 subcontractor COIs expire in the next 30 days."
- Schedule and scope notes to subs: "Cabinet install at the Garcia rebuild moved to the 14th. Revised layout attached."
- Summaries: a weekly list of jobs still in drying, or change orders waiting on approval.
- Replies coming back in: when a sub answers, the reply gets filed under the right job.
What it costs, in more detail
- Free, $0: 3,000 emails a month, 100 a day, 3 domains, 30 days of email history, receiving included. Each received email counts toward the 3,000.
- Pro, $20 a month: 50,000 emails, no daily cap, 10 domains. $35 a month for 100,000. Over your plan, $0.90 per 1,000 if you turn on overages in your team settings.
- Scale: from $90 a month for high volume.
- SendGrid, for comparison: its free plan was retired starting May 27, 2025. New accounts get a 60-day trial at 100 emails a day, then Essentials from $19.95 a month.
The full setup, step by step
Sending:
- Sign up at resend.com.
- Create an API key. API Keys, Create. Resend offers Full access and Sending access keys. If your app only sends, Sending access is the safer pick. If your app also reads incoming replies, it needs to fetch the reply's body from Resend, which a send-only key may not allow. Ask your AI coding assistant which permission it needs and why. Copy the key right away into your settings as
RESEND_API_KEY. - Add your domain. Domains, Add Domain. Resend recommends a subdomain like
updates.yourcompany.com. - Add the DNS records. Resend shows a few records (for DKIM and SPF). Log in to your domain host in another tab and add each one. Copy and paste; don't retype. Some hosts add your domain name to the end automatically, so if the record name already includes it, you can end up with it doubled. Compare carefully.
- Verify. Click Verify in Resend. Often within about 15 minutes, up to 72 hours.
- Set your from address in your settings, on the verified domain:
RESEND_FROM_EMAIL=alerts@updates.yourcompany.com - Test. Send to
delivered@resend.dev(a test address that accepts mail) and to your own inbox. Check your spam folder the first time.
Receiving replies:
- Pick a receiving address. Two options: the
.resend.appaddress Resend gives your account (Emails, Receiving tab, three-dot menu, Receiving address), or a subdomain of your own, such asreplies.yourcompany.com, with the MX record Resend shows you. - Set your app's reply-to to that address, so when a sub hits Reply, the answer goes to Resend instead of a personal inbox.
- Add a webhook (after your app is live). Webhooks, Add Webhook, enter your app's incoming email address, choose
email.received. Copy the signing secret into your settings asRESEND_WEBHOOK_SECRET. - Test it: reply to one of your app's emails from your phone and confirm it shows up in the job's history.
More gotchas worth knowing
- The MX record trap. Your MX records decide where a domain's email goes. If your office email runs on
yourcompany.comand you add Resend's receiving record there too, either Resend gets nothing or your office email gets disrupted. Resend's docs say to use a subdomain. Do that. - The webhook only carries the outline. Resend's incoming email webhook includes who sent it and the subject, not the body or attachments. Your app has to ask Resend for the rest. That's normal; your assistant will handle it.
- Check the signature on every incoming email. Anyone who finds that address could post a fake "reply." Resend signs each request; your app should verify it with Resend's library and the signing secret, using the raw request body. Reject anything that fails.
- The
onboarding@resend.devaddress only sends to your account email. It's for your first test, not for real use. - Made-up test addresses bounce. Use
delivered@resend.devandbounced@resend.devinstead. - Keep the API key on the server. Never in browser code, never in a screenshot, never in chat.
Settings names to use
Keep the names consistent so your assistant and your hosting settings match:
RESEND_API_KEYRESEND_FROM_EMAILRESEND_REPLY_TO_EMAILRESEND_WEBHOOK_SECRET
