← BACK TO GUIDES

AbuseGraph + Clerk

Score Clerk signups and logins with the hosted AbuseGraph check API.

Keys

KeyEnvUse
SecretABUSEGRAPH_SECRET_KEY (sk_…)Server /api/v1/check
PublishableNEXT_PUBLIC_ABUSEGRAPH_PUBLISHABLE_KEY (pk_…)Browser SDK
SiteABUSEGRAPH_SITELicensed domain

Env

ABUSEGRAPH_SITE=acme.com
ABUSEGRAPH_CHECK_URL=https://your-app.vercel.app/api/v1/check
ABUSEGRAPH_SECRET_KEY=sk_live_…
ABUSEGRAPH_SECRET_KEY_TEST=sk_test_…

Signup — user.created webhook

export async function POST(req: Request) {
  const evt = await req.json()
  if (evt.type !== "user.created") return new Response("ok")

  const email = evt.data.email_addresses?.[0]?.email_address
  const site = process.env.ABUSEGRAPH_SITE!
  const res = await fetch(process.env.ABUSEGRAPH_CHECK_URL!, {
    method: "POST",
    headers: {
      "content-type": "application/json",
      "x-api-key": process.env.ABUSEGRAPH_SECRET_KEY!,
      "x-abusegraph-site": site,
    },
    body: JSON.stringify({
      email,
      ip: req.headers.get("x-forwarded-for") ?? undefined,
      event: "signup",
      site,
    }),
  })

  if (res.status === 402) {
    return new Response("credits_exhausted", { status: 402 })
  }

  const result = await res.json()
  if (result.verdict === "block") {
    // Ban or delete the Clerk user
  }

  return Response.json(result)
}

Login

Pass event: "login" on session create. Use sk_test_… locally.

Browser SDK (optional)

import { init } from "@palisade/sdk"

const sdk = init({
  publicKey: process.env.NEXT_PUBLIC_ABUSEGRAPH_PUBLISHABLE_KEY!,
  edgeUrl: process.env.NEXT_PUBLIC_ABUSEGRAPH_EDGE_URL!,
})

await sdk.check()