Resend OTP

PreviousNext

Step-by-step guide to configuring Resend for email OTP and password reset in the Convex Auth starter — the account, domain verification, the API key, and the from address you have to change.

Two flows in the starter send mail through Resend: the email OTP tab, and the password-reset code.

Before you start

  • A Resend account. The free tier is enough to test with.
  • A domain you own, with access to its DNS records. You can create an API key and send to your own address without one, but you cannot send to anyone else until a domain is verified.

Set it up

Create a Resend account

Sign up at resend.com and confirm your email address. The onboarding checklist that greets you covers exactly two things — adding an API key and sending a test email — and you will do both below.

Resend onboarding checklist: add an API key and send your first emailResend onboarding checklist with both steps completed

Add your domain

  1. Click Domains in the left sidebar.
  2. Click Add Domain.
  3. Enter the domain or subdomain you want to send from, pick the region closest to your users, and click Add Domain.

A subdomain like mail.yourdomain.com is worth considering: it keeps the sending reputation of your transactional mail separate from whatever else uses the root domain.

Empty Resend Domains page with the Add Domain button highlightedAdd Domain form with a domain name and region selected

Add the DNS records

Resend generates the records for you — an MX and two TXT records for DKIM and SPF, marked Required, plus an optional TXT record for DMARC. Copy each one into your DNS provider exactly as shown; do not retype the values.

Then click I've added the records. Verification usually lands in a few minutes, but DNS propagation can take up to 24 hours.

Resend DNS Records panel showing the required DKIM/SPF records and the optional DMARC record

Create an API key

  1. Click API Keys in the left sidebar.
  2. Click Create API Key.
  3. Name it something you'll recognise later, leave Permission on Full access, and scope it to your domain if you want to restrict it.
  4. Click Add.
  5. Copy the key. Resend shows it once and never again.
Resend API Keys page with the Create API Key button highlightedAdd API Key dialog with a name, Full access permission and domain scopeView API Key dialog warning that the key is only shown once

Set it on your Convex deployment

pnpm dlx convex env set AUTH_RESEND_KEY re_your_key_here

Or add AUTH_RESEND_KEY in the Convex dashboard under Settings → Environment Variables.

Use separate keys for dev and prod

npx convex env set writes to your development deployment. Production is a separate deployment with its own environment, so set it there too:

pnpm dlx convex env set AUTH_RESEND_KEY re_prod_key_here --prod

Separate keys mean you can revoke one without taking the other down, and the Resend logs tell you which environment a send came from.

Test it

pnpm dlx convex dev

Try the OTP tab and the forgot-password flow. Without AUTH_RESEND_KEY set, both fail — the sign-up and sign-in flows in the password tab work regardless, since they don't send mail.

Then open Logs in the Resend dashboard. Every send shows up there, whether it was delivered, bounced or rejected, along with the API error if there was one.

No local mail catcher

Supabase's local stack ships Inbucket, which catches every message instead of delivering it. There is no Convex equivalent — testing email here always sends through Resend, dev key or not. Resend's dashboard Logs is the closest thing to it: every send, delivered or not, shows up there.

When it does not work

What you seeUsually
Email never arrives, no errorAUTH_RESEND_KEY unset, or set on the wrong deployment (dev vs. prod)
Arrives in spamDomain has no SPF/DKIM, or the from address isn't on that domain
Could not send email thrownCheck the Resend dashboard's Logs for the actual API error
Works in dev, not after deployingAUTH_RESEND_KEY was never set with --prod
Domain stuck on "Pending"DNS hasn't propagated yet, or a record was retyped instead of pasted

Next