Next.js email verification

Validate signup emails in Next.js

Call Verifly from a server route before creating trial accounts, saving lead forms, or passing contacts into downstream automations.

Route handler snippetAPI
const response = await fetch(`https://verifly.email/api/v1/verify?email=${email}`, {
  headers: { Authorization: `Bearer ${process.env.VERIFLY_API_KEY}` }
})
const result = await response.json()

Real-time SMTP mailbox checks

Single, batch, and async bulk verification

Disposable, role account, and catch-all detection

Pay-as-you-go credits with no subscription lock-in

Search fit

Built for Next.js email verification searches

Use Verifly when you need a simple API, predictable pricing, and clean JSON results before emails hit your product, CRM, or campaign tool.

Verify trial signup emails before account creation
Block disposable addresses from lead magnets
Check contact forms before CRM sync
Keep API keys server-side in route handlers

Verify on the server, never in the browser

The most important rule for calling any keyed API from Next.js is that the call belongs on the server. Your Verifly key is a secret; if it ships in a client component or a NEXT_PUBLIC_ variable, it is visible in the browser bundle and anyone can spend your credits. Next.js gives you the right home for it: a Route Handler (app/api/.../route.ts) or a Server Action, where process.env.VERIFLY_API_KEY stays on the server.

The typical shape is a signup or lead form that POSTs to your own /api/verify-email route. That route reads the address, calls Verifly with the secret key, and returns only a safe verdict to the client — deliverable, undeliverable, or risky — never the key and never the raw upstream response if you would rather not expose the flags.

Because the check happens before you create the user row, disposable and invalid addresses are rejected at the door instead of polluting your database and your lifecycle emails. A single GET is fast enough to run inline in the request without a noticeable delay for the user.

A Route Handler that gates signups

  1. Add VERIFLY_API_KEY to .env.local (no NEXT_PUBLIC_ prefix) so it stays server-only.
  2. Create app/api/verify-email/route.ts that reads the posted email.
  3. Call GET /api/v1/verify from the handler with the key from process.env.
  4. Return a small JSON verdict to the client; reject undeliverable (and optionally risky/disposable) before creating the account.
  5. On the client, POST the form to this route and only proceed when the verdict is acceptable.
app/api/verify-email/route.ts
import { NextResponse } from 'next/server'

export async function POST(req: Request) {
  const { email } = await req.json()
  const r = await fetch(
    `https://verifly.email/api/v1/verify?email=${encodeURIComponent(email)}`,
    { headers: { Authorization: `Bearer ${process.env.VERIFLY_API_KEY}` } }
  )
  const { result, disposable } = await r.json()
  const allowed = result === 'deliverable' && !disposable
  return NextResponse.json({ allowed, result }, { status: allowed ? 200 : 422 })
}

FAQ

Frequently asked questions

Can I call Verifly from a client component?

No — that would expose your API key in the browser bundle. Call it from a Route Handler or Server Action where process.env.VERIFLY_API_KEY stays on the server, and return only a verdict to the client.

Route Handler or Server Action?

Either works. A Route Handler (app/api/.../route.ts) is convenient when the form fetches an endpoint; a Server Action is convenient with progressive-enhancement forms. Both keep the key server-side.

Is one verification fast enough for signup?

Yes. A single GET /verify runs in a request without a noticeable delay, so you can gate account creation inline rather than deferring to a background job.

Should I block risky and disposable too, or just undeliverable?

Always block undeliverable. For a paid product, also block disposable to stop throwaway trials; whether you block risky depends on how strict you want signup to be.

Where do I put the key locally and in production?

In .env.local for development and your host's environment variables in production — without the NEXT_PUBLIC_ prefix so it is never inlined into the client bundle.

How do I verify many addresses at once server-side?

For imports rather than single signups, call POST /verify/batch from a Route Handler, or the async bulk endpoint for very large lists.