Quickstart
BurnGuard checks each signup in one API call and returns allow, limit, review or block, with readable reasons. New projects start in monitor mode, so nothing changes for your users until you decide.
1. Create a project and get your keys
Create a free account, confirm your email, and create a project. You get two keys:
| Key | Looks like | Where it goes |
|---|---|---|
| Publishable | bg_pk_… |
In the browser, on the snippet tag. Safe to expose. |
| Secret | bg_sk_… |
On your server only. Shown once, so copy it into an env var. |
BURNGUARD_SECRET_KEY=bg_sk_your_secret_key
2. Add the snippet to your signup page
<script src="https://YOUR-BURNGUARD-HOST/sdk.js" data-key="bg_pk_your_publishable_key" defer></script>
<form method="post" action="/signup" data-burnguard>
<input type="email" name="email" required>
<input type="password" name="password" required>
<button>Create account</button>
</form>
The snippet adds a hidden bg_device field to every form marked data-burnguard. It holds an opaque device token: a hash of a few stable browser properties. No cookies, no cross-site tracking. For single-page apps, call await BurnGuard.token() and send the value with your signup request. See SDK.
3. Call /v1/check from your backend
async function burnguardCheck({ email, ip, deviceToken, userAgent, userId }) {
try {
const res = await fetch("https://YOUR-BURNGUARD-HOST/v1/check", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BURNGUARD_SECRET_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
event: "signup",
email,
ip,
device_token: deviceToken,
user_agent: userAgent,
external_id: userId, // optional, lets you report usage later
}),
signal: AbortSignal.timeout(1500),
});
if (!res.ok) return { decision: "allow" }; // fail open
return await res.json();
} catch {
return { decision: "allow" }; // timeout or network error: fail open
}
}
Always fail open: if BurnGuard is slow or unreachable, treat the signup as allow. Your signups should never depend on us being up.
4. Act on the decision
const check = await burnguardCheck({ email, ip: req.ip, deviceToken: req.body.bg_device, userAgent: req.get("user-agent") });
switch (check.decision) {
case "block":
return res.status(403).send("We couldn't create this account. Contact support if this is a mistake.");
case "review":
await createUser({ email, credits: 0, needsVerification: true }); // e.g. require a card or phone
break;
case "limit":
await createUser({ email, credits: Math.floor(FREE_CREDITS * (check.recommended_credit_fraction ?? 0.1)) });
break;
default:
await createUser({ email, credits: FREE_CREDITS });
}
limit is credit gating: let the account in, but grant a fraction of the free credits until it verifies or ages. See Decisions and credit gating.
5. Watch, then enforce
In monitor mode, decision is always allow and would_decision tells you what BurnGuard would have done. After about a week, open the dashboard, look at the flagged signups and their reasons, and switch the project to enforce in Settings. Mark mistakes as legit with /v1/feedback or one click in the dashboard.
Next
- API reference
- Recipes: Next.js · Express · Supabase Auth · Better Auth · Clerk