AbuseGraph + Clerk
Score Clerk signups and logins with the hosted AbuseGraph check API.
Keys
| Key | Env | Use |
|---|---|---|
| Secret | ABUSEGRAPH_SECRET_KEY (sk_…) | Server /api/v1/check |
| Publishable | NEXT_PUBLIC_ABUSEGRAPH_PUBLISHABLE_KEY (pk_…) | Browser SDK |
| Site | ABUSEGRAPH_SITE | Licensed 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()