CheckDisposable Emailcheckdisposable.email
← All guidesWorkOS guide · TypeScript

Block disposable email signups in WorkOS AuthKit

Hook the `user.created` webhook from WorkOS. Verify the disposable status, then delete the user if needed. AuthKit doesn't expose a synchronous pre-creation hook, so this is the supported pattern.

The code

// app/api/webhooks/workos/route.ts
import { WorkOS } from '@workos-inc/node';

const workos = new WorkOS(process.env.WORKOS_API_KEY!);

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 sigHeader = req.headers.get('workos-signature') ?? '';
  const payload = await req.text();
  const event = await workos.webhooks.constructEvent({
    payload: JSON.parse(payload),
    sigHeader,
    secret: process.env.WORKOS_WEBHOOK_SECRET!,
  });

  if (event.event === 'user.created') {
    const email = (event.data as any).email;
    if (email && (await isDisposable(email))) {
      await workos.userManagement.deleteUser((event.data as any).id);
    }
  }
  return new Response('ok');
}

Notes

Configure webhook
WorkOS Dashboard → Webhooks → +endpoint → subscribe to `user.created`. Copy the signing secret into `WORKOS_WEBHOOK_SECRET`.
Pair with client-side check
For better UX, also call CheckDisposable Email client-side before showing the AuthKit signup form. The webhook is the backstop; the client check stops most signups before WorkOS even sees them.
Enterprise SSO
For SSO via SAML/OIDC, the user.created webhook fires the same way. Same code handles both AuthKit-direct and SSO-federated signups.

Get a free API key

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

Sign up free →