CheckDisposable Emailcheckdisposable.email
← All guidesSupabase guide · TypeScript (Deno)

Block disposable email signups on Supabase

Use a Supabase Edge Function as an Auth Hook. Calls CheckDisposable Email before Supabase creates the user — rejects the signup at the auth layer so no row is ever written to `auth.users`.

The code

// supabase/functions/before-user-created/index.ts
// Deploy with: supabase functions deploy before-user-created
// Wire as: Database → Webhooks → "Send before user is created" → this function

Deno.serve(async (req) => {
  const body = await req.json();
  const email = body.user_metadata?.email ?? body.email;

  const cdeKey = Deno.env.get('CDE_KEY');
  if (!email || !cdeKey) {
    return new Response(JSON.stringify({ decision: 'continue' }), {
      headers: { 'content-type': 'application/json' },
    });
  }

  try {
    const r = await fetch(
      `https://api.checkdisposable.email/v1/check?email=${encodeURIComponent(email)}`,
      { headers: { Authorization: `Bearer ${cdeKey}` } }
    );
    if (r.ok) {
      const data = await r.json();
      if (data.is_disposable) {
        return new Response(
          JSON.stringify({
            decision: 'reject',
            message: 'Please use a real email address.',
          }),
          { headers: { 'content-type': 'application/json' } }
        );
      }
    }
  } catch {
    // fail open: let Supabase continue with the signup
  }

  return new Response(JSON.stringify({ decision: 'continue' }), {
    headers: { 'content-type': 'application/json' },
  });
});

Notes

Set the API key as a secret
Run `supabase secrets set CDE_KEY=cde_live_xxx` so the Edge Function has access to your key without committing it to git.
Auth hook wiring
In the Supabase dashboard: Authentication → Hooks → enable "Send before user is created (Custom Access Token / Pre-signup)" and point it at this Edge Function. The hook contract is: return `decision: "continue"` to proceed, `decision: "reject"` to block with a message.
No row created on reject
Because we hook BEFORE user creation, rejected signups never write a row to `auth.users`. No cleanup job needed.

Get a free API key

500 checks/month, no credit card. No credit card. 30 seconds.

Sign up free →