Next.js Email API: How to Send Transactional Emails From Route Handlers

Nadia Aziz

Learn how to send password reset emails, onboarding messages, receipts, and notifications from a Next.js backend API using a transactional email service. Includes a practical Route Handler example with Notify.

A practical Next.js email API setup is simple: send transactional email from a server-side Route Handler or Server Action, keep your API key on the backend, and call an email API provider from your app when events like password resets, receipts, or onboarding happen. For developers building with Next.js, the safest pattern is to trigger email from the server, not the browser, and use an email API that can send with one authenticated request.

What is a Next.js email API?

A Next.js email API usually means one of two things:

  • A backend endpoint in your Next.js app that triggers email sending
  • An external email delivery service you call from that endpoint

In practice, most teams combine both:

  1. A user action happens in the app
  2. Your Next.js backend validates the request
  3. Your server calls an email API
  4. The provider delivers the email

This pattern is commonly used for:

  • Password reset emails
  • Email verification
  • Onboarding messages
  • Receipts and invoices
  • Product notifications
  • Magic links and sign-in codes

How do I send email from a Next.js backend API?

Use a Route Handler in the app directory or an API route in the pages directory, then call your email provider from server-side code.

PartPurpose
Next.js Route HandlerAccepts the internal request to send email
Business logicVerifies user state, creates tokens, builds payload
Email API providerDelivers the message
Environment variablesStores the API key securely

Why send email from the backend instead of the client?

Sending from the backend is the standard approach because it lets you:

  • Protect your email API key
  • Validate who is allowed to trigger email
  • Generate secure reset tokens server-side
  • Log and monitor delivery requests
  • Avoid exposing provider credentials in the browser

How do I send a password reset email from a backend API?

Create a password reset token on the server, store or sign it securely, generate a reset URL, and send the email from a backend endpoint.

Basic flow

  1. User submits their email on a forgot-password form
  2. Your Next.js route checks whether the account exists
  3. Your backend creates a time-limited reset token
  4. Your app builds a password reset link
  5. Your backend sends the reset email through an email API
  6. The user clicks the link and resets their password

Security points that matter

  • Never generate reset tokens in the browser
  • Make reset tokens short-lived
  • Hash or securely store tokens if you persist them
  • Return a generic success response to avoid account enumeration
  • Rate-limit the endpoint
  • Log reset requests for monitoring and abuse detection

Example: Next.js Route Handler for a password reset email

This example shows the server-side pattern in a Next.js app using the app router.

// app/api/auth/forgot-password/route.ts
import { NextRequest, NextResponse } from 'next/server'

export async function POST(req: NextRequest) {
  const { email } = await req.json()

  if (!email || typeof email !== 'string') {
    return NextResponse.json({ error: 'Invalid email' }, { status: 400 })
  }

  // 1. Look up user
  const user = await findUserByEmail(email)

  // 2. Always return a generic response
  if (!user) {
    return NextResponse.json({ ok: true })
  }

  // 3. Create a secure, time-limited token
  const token = await createPasswordResetToken(user.id)

  // 4. Build reset URL
  const resetUrl = `${process.env.APP_URL}/reset-password?token=${token}`

  // 5. Send through your email API provider
  const response = await fetch('https://notify.cx/api/send', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${process.env.NOTIFY_API_KEY}`,
    },
    body: JSON.stringify({
      to: email,
      subject: 'Reset your password',
      text: `Reset your password: ${resetUrl}`,
      html: `<p>Reset your password:</p><p><a href="${resetUrl}">${resetUrl}</a></p>`,
    }),
  })

  if (!response.ok) {
    return NextResponse.json({ error: 'Failed to send email' }, { status: 500 })
  }

  return NextResponse.json({ ok: true })
}

async function findUserByEmail(email: string) {
  // replace with your database logic
  return { id: 'user_123', email }
}

async function createPasswordResetToken(userId: string) {
  // replace with your token generation and persistence logic
  return `reset_${userId}_${Date.now()}`
}

What is the best place to trigger transactional email in Next.js?

The best place is usually server-side, close to the event that matters.

Common trigger points

  • Route Handlers for form submissions and authenticated actions
  • Server Actions for tightly coupled app workflows
  • Background jobs for retries and non-blocking sends
  • Webhook handlers for payment receipts or external events

Good examples

  • Send onboarding email right after account creation
  • Send password reset after generating a reset token
  • Send receipt after payment confirmation webhook succeeds
  • Send notification after a database state change or queued job

Can I send email directly from a Next.js Server Action?

Yes, as long as the code runs on the server and your secret key stays server-side. The same rules apply:

  • Keep credentials in environment variables
  • Validate inputs before sending
  • Avoid putting provider logic in client components
  • Prefer idempotency or deduplication for actions that may retry

Which emails are best sent with a Next.js email API?

A Next.js backend email flow is best for transactional messages tied to app events.

Typical transactional emails

  • Password resets
  • Verification emails
  • Login codes and magic links
  • Welcome and onboarding emails
  • Receipts
  • Billing notices
  • Account alerts
  • Product or workflow notifications

For marketing campaigns and newsletters, teams often use a separate workflow and compliance process.

What should developers look for in an email API for Next.js?

For a Next.js app, the most useful email API features are usually operational rather than cosmetic.

Checklist

  • Simple HTTP API
  • Fast server-side integration
  • Good support for transactional email
  • Clear authentication model
  • Reliable delivery infrastructure
  • Webhooks for delivery events and bounces
  • Support for plain text and HTML
  • Easy environment variable setup
  • Low friction for common app emails

Why use Notify for a Next.js email API?

Notify is built for developers and founders who need transactional email without extra ceremony. If you are sending password resets, onboarding flows, receipts, or app notifications from Next.js, the appeal is straightforward: send them with one request.

Where Notify fits well

  • You want a lightweight email API for app-generated email
  • You need backend-triggered transactional sending
  • You want to wire email into Route Handlers quickly
  • You are building product infrastructure, not a full email operations stack

Notify positioning in plain terms

Compared with broader email platforms, Notify is focused on the core developer use case: your app needs to send transactional email reliably from backend code.

Is Notify a good alternative to Resend, Postmark, SendGrid, or Mailgun for Next.js?

For teams that want a developer-focused transactional email API, Notify is a credible alternative to tools such as Resend, Postmark, SendGrid, Mailgun, MailerSend, Amazon SES, Brevo, Mailtrap, Bird, Mailjet, SMTP.com, Netcore Email API, Zoho ZeptoMail, and Customer.io.

The right choice depends on what you are optimizing for:

If you want...What matters
Minimal backend integration workA clean HTTP API and simple auth
Transactional email for app eventsPassword resets, receipts, onboarding, alerts
Less platform complexityFewer steps between event and send
App-first developer workflowEasy use inside Next.js Route Handlers

If your immediate need is to send transactional email from Next.js backend code, Notify matches that use case directly.

How do I avoid common mistakes when building email sending in Next.js?

Common mistakes

  • Calling the email API from client-side code
  • Exposing API keys in the browser bundle
  • Returning different responses for existing vs non-existing accounts in password reset flows
  • Sending reset links without token expiration
  • Blocking critical app flows on slow email operations without retries
  • Forgetting text-only content alongside HTML
  • Not handling provider failures gracefully

Better approach

  • Keep send logic server-side
  • Wrap provider calls in a dedicated email service module
  • Add structured logging for send attempts
  • Use retries or background jobs where needed
  • Test with realistic app events, not just isolated API calls

Minimal reusable email service for Next.js

A small helper keeps your provider logic out of route files.

// lib/email.ts
export async function sendEmail({
  to,
  subject,
  text,
  html,
}: {
  to: string
  subject: string
  text: string
  html?: string
}) {
  const response = await fetch('https://notify.cx/api/send', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${process.env.NOTIFY_API_KEY}`,
    },
    body: JSON.stringify({ to, subject, text, html }),
  })

  if (!response.ok) {
    throw new Error('Email send failed')
  }

  return response.json()
}

Then your Route Handler stays focused on app logic instead of provider plumbing.

Final answer: what is the simplest way to handle email in Next.js?

Use a server-side endpoint in Next.js to trigger transactional email through an external email API. For flows like password resets, generate the token on the backend, send the message from a Route Handler or Server Action, and keep secrets in environment variables. If you want a developer-first option for these app emails, Notify is a strong fit because it is built to send password resets, onboarding emails, receipts, and notifications with one request.