ByeBuy.ai
BUILD YOUR ESCAPE ROUTE · ✦ CURSOR · HOST IT · ◫ SUPABASE · CONNECT IT · ↯ RELAY · BUILD YOUR ESCAPE ROUTE · ✦ CURSOR · HOST IT · ◫ SUPABASE · CONNECT IT · ↯ RELAY ·
CURRICULUM
← BYEBUY NOTES

September 12, 2026

APPENDIX: SEND YOUR FIRST TRANSACTIONAL EMAIL WITH RESEND

Appendix: Send Your First Transactional Email With Resend

You have already sent a model request. Now send something a product actually needs: one email. The mechanics are the same — endpoint, authorization header, JSON body, response — but the consequence is different. An email leaves your system and lands in a person's inbox. That makes this a perfect first lesson in a real-world API boundary.

Three email jobs — do not mix them up

Transactional email is caused by a person or product event: a sign-in link, password reset, receipt, booking confirmation, failed-payment notice, or "your report is ready." It is one message to one person because the product needs to tell them something.

Lifecycle email is a planned series tied to a relationship: a welcome sequence, onboarding reminder, or reactivation note. Class 78 will teach the content and timing.

Newsletter or broadcast email is a message to an opted-in audience. It needs a clear promise, a consistent cadence, and an easy way for readers to leave. It is not a disguised receipt.

Resend can be the delivery layer beneath all three. This appendix focuses on the first and clearest job: send one transactional email from your application. The later lessons decide *who* should receive a message, *why*, and *what the message says*.

The email providers you will run into

Resend is not the only way to send email from a product. These are the names worth recognizing:

ProviderBest known for
ResendA clean developer API that can handle transactional email, audiences, broadcasts, templates, webhooks, and inbound email in one modern system.
PostmarkFocused transactional delivery for receipts, magic links, password resets, and other critical one-to-one product email.
SendGridA large, mature platform spanning transactional and marketing email, often used by bigger teams with broader operational needs.
MailgunFlexible engineering infrastructure for sending, inbound email, validation, logs, and deliverability operations.
Customer.ioBehavioral lifecycle messaging: segments, campaigns, onboarding, and product-driven journeys.
Amazon SESAWS-native sending infrastructure; useful at large scale when a team is comfortable operating AWS configuration and its pricing model.
CourierNotification infrastructure for sending one product event through email, SMS, Slack, push, and other channels.

For this course, we prefer Resend. It gives a new builder one clean place to learn the API path, product notifications, newsletters, audience broadcasts, and the webhook events that connect email back to the rest of an application. That is enough surface area to learn the system without creating a contact-sync problem across several providers.

Choose another provider when its specialty is genuinely your project's main job: Postmark for a product that lives or dies on focused transactional delivery, Customer.io for a mature behavior-driven lifecycle program, SES for AWS-heavy scale, or Courier when one event must coordinate several notification channels. The email mechanics in this lesson still apply: verified domain, server-held key, clear event, durable record, safe retry.

The delivery path

your product event
  → your server or worker decides an email is needed
  → Resend API receives sender + recipient + subject + content
  → recipient mail server accepts or rejects delivery
  → Resend returns an email ID and can send delivery/bounce events back by webhook

The API does not know whether your email is useful. Your product makes that decision. Resend's job is to deliver the message you intentionally asked it to send.

Setup: domain first, key second

1. Create an account at Resend, add a domain you control, and use a sending subdomain such as updates.example.com when that suits your project. 2. In the Resend dashboard, copy the required DNS records into the place that manages your DNS — often Cloudflare, Vercel, or your domain registrar. Resend uses SPF and DKIM records to prove it is allowed to send for your domain. Add the exact records Resend gives you; do not guess or combine them with old records. Resend's domain guide explains the verification screen and the purpose of each record. 3. Wait until the domain is marked verified. Once verified, you can send from an address at that domain, such as hello@updates.example.com. Use an address that can receive replies when you invite a reply. 4. Create a restricted-purpose API key and place it in your local .env file:

RESEND_API_KEY=re_...

Put .env in .gitignore. Never paste this key into a browser client, a public repository, a screenshot, or a prompt. Your backend, server route, or worker uses it; the visitor's browser does not.

Send one test message

Load your local variables using your shell's normal method, then replace the two email addresses below with your verified sender and an inbox you control.

curl -X POST "https://api.resend.com/emails" \
  -H "Authorization: Bearer $RESEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "ByeBuy Test <hello@updates.example.com>",
    "to": ["you@example.com"],
    "subject": "Your first API email worked",
    "html": "<p>You sent this from an API. That is the whole point.</p>"
  }'

A successful response contains an ID like this:

{
  "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794"
}

Save that ID in your test notes. It proves the API accepted the request. It does not mean the message has necessarily reached the inbox yet; delivery is a separate event. Resend can tell your product about email.delivered, email.bounced, email.failed, and other outcomes through webhooks. Class 31 and Class 88 explain how to receive and safely operate those events.

Make retries safe before you need them

The dangerous moment is not the happy-path curl. It is a timeout. Your server may lose the response after Resend accepted the email, then retry and send the person the same message twice.

Give each intended message a durable identity before you send it:

welcome/user_481
receipt/order_9917
report-ready/report_302

Send that same identity in the Idempotency-Key header whenever you retry the *same* message:

curl -X POST "https://api.resend.com/emails" \
  -H "Authorization: Bearer $RESEND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: report-ready/report_302" \
  -d '{
    "from": "ByeBuy Reports <hello@updates.example.com>",
    "to": ["you@example.com"],
    "subject": "Your research report is ready",
    "html": "<p>Your report is ready.</p>"
  }'

Resend keeps an idempotency key for 24 hours, so repeating that same request returns the original result instead of creating a second email. Read the idempotency-key documentation, then carry this pattern into background workers in Lesson 26.4. Your own database should still record the product event, recipient, message type, key, Resend email ID, and final delivery state. That record is your long-term memory; an API response is not.

Where this sits in a real product

Product momentWho decidesWhat sends itWhat you record
User asks for a sign-in linkManaged auth providerIts configured email delivery pathuser + request time + single-use token state
User purchases somethingYour payment/product backendServer or worker → Resendorder ID + receipt/order_9917 + email ID
New reader opts inYour audience/workflow logicEmail platform or Resend broadcast/delivery workflowconsent + segment + sequence step
Report finishes overnightBackground workerWorker → Resendreport ID + idempotency key + delivery event

Notice the split: the email API is a powerful *delivery tool*; it is not the product's brain. Do not let an agent with a broad key decide which real customers receive messages. Let it draft, test against a test inbox, and propose a send. A narrowly scoped server tool plus a human approval gate is the right path for consequential outbound email.

Exercise: create one delivery proof

Create EMAIL-DELIVERY-NOTES.md in a private project notes folder:

# EMAIL-DELIVERY-NOTES.md
- Verified sending domain: ___
- Test sender: ___
- Test recipient I control: ___
- Message purpose: ___
- Idempotency key: ___
- Resend email ID: ___
- Inbox result: received / spam / not received
- Next action: ___

Finish line: one accepted test email, its returned ID, and the filled note. Then run the exact same request one time with the same Idempotency-Key; confirm you did not receive a second copy.

Common failure mode: putting RESEND_API_KEY in a frontend file because the browser is where the button lives. The button calls *your* server; your server calls Resend. The API key stays on the server side of that line.

Check your understanding

1. What is the difference between a transactional email, a welcome sequence, and a newsletter? 2. Why must the sender domain be verified before you treat email delivery as part of your product? 3. What does the returned email ID prove, and what does it not prove? 4. What stable key would you use for a receipt for order 9917, and why should a retry reuse it?

Next

You now know the full small loop: verified domain → server-held key → request → returned ID → delivery event → recorded outcome. Read Lesson 26.4 for retries and durable jobs, Lesson 31.3 for agent approval boundaries, Lesson 47.2 for sign-in email, Lesson 78.2 for a welcome sequence, and Lesson 88.4 for operating failures when this becomes a real system.

ARTICLE DISCUSSION

JOIN THE
CONVERSATION.

0 COMMENTS

BYEBUY ACCOUNT ACCESS

Sign in

Use your account to save routes and make the catalogue yours.

Enter your email and we’ll send a secure sign-in link and code.

NEW ROUTES ADDED WEEKLY · 9,235 CATALOGUE ENTRIES · BUILD · DEPLOY · QUERY · STACK · SAY BYE TO BUY · NEW ROUTES ADDED WEEKLY · 9,235 CATALOGUE ENTRIES · BUILD · DEPLOY · QUERY · STACK · SAY BYE TO BUY ·