CheckDisposable Emailcheckdisposable.email
← All guidesClerk guide · TypeScript

Block disposable email signups in Clerk

Use Clerk's `restrictions` API or a webhook on `user.created` to reject disposable signups before they become full Clerk users. Two patterns depending on whether you want to block at the form or at the API.

The code

// app/api/webhooks/clerk/route.ts — runs on user.created
// Configure in Clerk dashboard: Webhooks → +endpoint → user.created
import { Webhook } from 'svix';
import { clerkClient } from '@clerk/nextjs/server';

async function isDisposable(email: string) {
  const r = await fetch(
    `https://api.checkdisposable.email/v1/check?email=${encodeURIComponent(email)}`,
    { headers: { Authorization: `Bearer ${process.env.CDE_KEY!}` } }
  );
  if (!r.ok) return false;
  return (await r.json()).is_disposable === true;
}

export async function POST(req: Request) {
  const payload = await req.text();
  const wh = new Webhook(process.env.CLERK_WEBHOOK_SECRET!);
  const evt = wh.verify(payload, Object.fromEntries(req.headers)) as any;

  if (evt.type === 'user.created') {
    const email = evt.data.email_addresses[0]?.email_address;
    if (email && (await isDisposable(email))) {
      // Roll the user back — Clerk's only async option after creation.
      const client = await clerkClient();
      await client.users.deleteUser(evt.data.id);
    }
  }
  return new Response('ok');
}

Notes

Pre-signup block (cleaner)
For stricter UX, validate the email in your sign-up form before calling `signUp.create()` and refuse there. The webhook is a safety net for OAuth-based signups (Google, Apple) where you can't intercept the address.
Webhook secret
Copy the signing secret from the Clerk dashboard into `CLERK_WEBHOOK_SECRET`. Without it, Svix verification fails and your endpoint accepts spoofed requests.
Why delete instead of block
Clerk does not expose a "reject during creation" hook. Deletion happens within seconds of the user being created and before they can sign in — they never see a session.

Get a free API key

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

Sign up free →