AbuseGraph + Cloudflare Workers
Browser SDK on Pages — Worker proxies toCheckBody to abusegraph.com with sk_ secrets.
Install the browser SDK
npm install @palisade/sdk
Init early on app load. Call check({ email }) at signup or login — not on every page view.
Quick path
- Init the browser SDK with
pk_test_…on your site. - Store
ABUSEGRAPH_SECRET_KEYandABUSEGRAPH_SITEas Worker secrets. - Worker receives
toCheckBodyfrom the client and POSTs tohttps://abusegraph.com/api/v1/check.
Keys
| Key | Env | Use |
|---|---|---|
| Secret | ABUSEGRAPH_SECRET_KEY (sk_test_… / sk_live_…) | Server /api/v1/check |
| Publishable | NEXT_PUBLIC_ABUSEGRAPH_PUBLISHABLE_KEY (pk_test_…) | Browser SDK |
| Site | ABUSEGRAPH_SITE | DNS-verified domain |
Free includes 1,000 live API checks / month after DNS verify. Test keys never bill.
Env
Worker secrets (set via your Workers secrets UI or CLI):
bash
ABUSEGRAPH_SITE=yourdomain.com
ABUSEGRAPH_CHECK_URL=https://abusegraph.com/api/v1/check
ABUSEGRAPH_SECRET_KEY=sk_test_…
NEXT_PUBLIC_ABUSEGRAPH_PUBLISHABLE_KEY=pk_test_…Use sk_live_… / pk_live_… in production after DNS verify.
Server check
Workers use fetch — POST to https://abusegraph.com/api/v1/check. Events: signup | login | password_reset | email_change. Optional sessionId.
Browser signals (recommended)
init + collect + evaluate + toCheckBody — NEVER bare sdk.check() alone as the authoritative decision.
typescript
import { init } from "@palisade/sdk"
const sdk = init({
publicKey: import.meta.env.VITE_ABUSEGRAPH_PUBLISHABLE_KEY!, // pk_test_…
})
export async function collectForAuth(
email: string,
event: "signup" | "login" | "password_reset" | "email_change",
) {
const collected = await sdk.collect()
const edge = await sdk.evaluate(collected, { email })
return sdk.toCheckBody(collected, {
email,
event,
verdictToken: edge.verdictToken.token,
})
}Cloudflare Worker proxy
typescript
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (request.method !== "POST") {
return new Response("Method not allowed", { status: 405 })
}
const body = await request.json()
const res = await fetch(
env.ABUSEGRAPH_CHECK_URL ?? "https://abusegraph.com/api/v1/check",
{
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": env.ABUSEGRAPH_SECRET_KEY, // sk_test_…
"x-abusegraph-site": env.ABUSEGRAPH_SITE,
},
body: JSON.stringify({
...body,
site: env.ABUSEGRAPH_SITE,
event: body.event ?? "signup",
}),
},
)
if (res.status === 402) {
return new Response("credits_exhausted", { status: 402 })
}
const result = await res.json()
if (result.verdict === "block") {
return Response.json(result, { status: 403 })
}
return Response.json(result)
},
}Client:
typescript
const browserFields = await collectForAuth(email, "signup")
await fetch("/api/abusegraph-check", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ email, event: "signup", ...browserFields }),
})Lifecycle events
- login — POST with
event: "login"before session create. - password_reset — proxy with
event: "password_reset". - email_change — proxy with
event: "email_change".
Platform
Lists, rules, and linked accounts apply on every check — configure in the console. Optional session: POST /api/v1/session. Native apps: iOS, Android, React Native.
Verify
Deploy with sk_test_…, submit signup, confirm the Worker returns a verdict and Activity shows the check.