Supabase email verification

Validate emails before Supabase inserts

Add Verifly to Supabase-backed apps when signups, leads, or imports need an email quality check before records are stored or acted on.

Edge Function checkAPI
const res = await fetch(`https://verifly.email/api/v1/verify?email=${email}`, {
  headers: { Authorization: `Bearer ${Deno.env.get("VERIFLY_API_KEY")}` }
})
const verification = await res.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 Supabase email verification workflows

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

Check signup emails in an Edge Function
Reject disposable addresses before creating lead records
Store verification status alongside user metadata
Use batch checks before importing CSV data into Supabase

Guard the insert, not just the form

Supabase makes it trivial to write a row, which is exactly why bad email data ends up in the table. Client-side validation only checks the shape of an address; it cannot tell you whether the mailbox exists. If you want your users and leads tables to hold real, reachable addresses, the check has to sit on the server side of the insert.

A Supabase Edge Function is the natural place for it. It runs on Deno, reads secrets from Deno.env, and can call Verifly before it ever touches the database. The pattern is: the client posts the email to the function, the function verifies it, and only on a deliverable verdict does it perform the insert with the service-role client. Disposable and invalid addresses are turned away before a row exists.

Store the verdict alongside the record — a verification_status column, or a JSON field in user metadata — so downstream jobs can trust the data without re-checking. Set the Verifly key as a function secret with supabase secrets set; it never belongs in client code or the database.

An Edge Function that verifies then inserts

  1. Set the secret: supabase secrets set VERIFLY_API_KEY=vf_your_api_key (get the key at verifly.email/api/v1/autonomous/register).
  2. In the Edge Function, read the posted email and call GET /verify with the key from Deno.env.
  3. If the verdict is not deliverable (or the address is disposable), return a 4xx and do not insert.
  4. On a clean verdict, insert the row with the service-role client and persist verification_status.
  5. For CSV imports, call POST /verify/batch from the function instead of one request per address.
supabase/functions/signup/index.ts
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'

Deno.serve(async (req) => {
  const { email } = await req.json()
  const v = await fetch(
    `https://verifly.email/api/v1/verify?email=${encodeURIComponent(email)}`,
    { headers: { Authorization: `Bearer ${Deno.env.get('VERIFLY_API_KEY')}` } }
  ).then(r => r.json())

  if (v.result !== 'deliverable' || v.disposable) {
    return new Response(JSON.stringify({ error: 'invalid email' }), { status: 422 })
  }

  const db = createClient(Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!)
  await db.from('leads').insert({ email, verification_status: v.result })
  return new Response(JSON.stringify({ ok: true }))
})

FAQ

Frequently asked questions

Why verify in an Edge Function instead of the client?

The client can only check an address's format. An Edge Function runs server-side, keeps the API key in Deno.env, and can confirm the mailbox actually exists with a live SMTP check before the insert.

How do I store the Verifly key for a function?

Use supabase secrets set VERIFLY_API_KEY=... and read it with Deno.env.get('VERIFLY_API_KEY'). It never goes in client code or the database.

Should I store the verdict in the row?

Yes. Persisting verification_status (or a metadata field) lets downstream jobs trust the address without re-verifying, and gives you an audit trail of why a lead was accepted.

Can I verify addresses on bulk import into Supabase?

Call POST /verify/batch from the function for a list, or the async bulk endpoint (up to 1,000,000 addresses) for large CSV imports, then insert only the deliverable rows.

Does this work with Supabase Auth signups?

Route the signup through a function that verifies first and only then calls the admin create-user API, so disposable and invalid addresses never create an auth user.

What does each check cost?

One credit per address, pay-as-you-go from $2 to $0.60 per 1,000, credits never expire — cheap enough to guard every insert.