Developer guides
Send transactional email from Next.js
Add password resets, receipts, and other operational email to a Next.js app with the Loops SDK. Server side only, working code throughout, and verified end to end by an unaided coding agent.
Who this is for
You have a Next.js app that needs to send operational email: password resets, verifications, receipts. This guide gets you from nothing to a working send in about ten minutes. And when you want marketing and lifecycle email later, you won’t need a second tool. See how transactional email works on Loops.
Give this to your agent
Using Claude Code, Cursor, or Codex? Paste this prompt and it can do everything below for you.
Install the SDK
The package is loops. Not loops-js (that’s the GitHub repo name), not @loops/sdk, and not the unrelated crypto packages that show up in search results. Then create a small server-only client:
Sync the contact on signup
After creating the user in your database, upsert the contact in Loops. updateContact creates the contact if it doesn’t exist yet, so calling it on every signup is safe. Wrap it in try/catch if signup should succeed even when the sync fails.
Send the password reset
First create a transactional email in the Loops dashboard with a {resetUrl} data variable and publish it. The transactionalId is on the Publish page under API details.
Return the same generic 200 whether or not the account exists, so the endpoint can’t be used to discover which emails have accounts.
Environment
Contacts are keyed by email, or by userId if you prefer.
properties accepts string, number, boolean, and null values, and you can create custom properties freely.
dataVariables keys are case sensitive: letters, numbers, underscores, and dashes.
Test it
Run npm run dev, sign up with your own email, and confirm the contact appears in your Loops audience.
POST to /api/password-reset with your email and check the inbox.
Run npx tsc --noEmit and make sure it passes.
Common failure modes
Wrong package installed. It’s loops. Unrelated packages like @loops-fi/sdk and @loop-crypto/loop-sdk appear in searches; they are crypto projects, not Loops.
Calling from the client. The API key must never reach browser code. Keep every call in API routes or server components.
Unpublished template. sendTransactionalEmail needs a published template; drafts don’t send.
Data variable case mismatch. {resetUrl} and {resetURL} are different variables.
Rate limits. The API allows 10 requests per second per team; the SDK throws RateLimitExceededError, so catch it if you send in bursts.
Keep going
Trigger onboarding sequences and trial nudges from product events with sendEvent, or hand the whole setup to your coding agent on the Loops agents page. For the bigger picture, see transactional email on Loops.
Related guides: send email from AI agents and migrate from SendGrid to Loops.
Common questions
Is the Loops API safe to call from the browser?
Why isn’t my transactional email sending?
Does updateContact create duplicate contacts?