Add a trial and credit abuse check to your signup flow
Step-by-step guide to adding a free trial and signup credit abuse check to your signup flow with the AbuseZero Node.js SDK or REST API. One call returns allow or deny.
The best place for a free trial abuse check is the exact moment your application is about to grant the benefit. Not after the trial has started, and not in a nightly report. This guide shows where the check goes in your signup flow, how to add it with the AbuseZero Node.js SDK or REST API, and how to roll it out without affecting a single real user on day one.
You keep your signup flow. You add one server-side call. AbuseZero returns allow or deny.
Without a check at that moment, the first sign of abuse is usually the bill: a spend alert at 3 a.m., a queue backed up with accounts that will never pay, or a free tier that's suddenly slow for everyone.
From our early beta
A team whose cloud bill normally ran $200 to $300 a month woke up to a $12,000 bill. Automated registrations had triggered thousands of expensive serverless functions, database operations and background jobs overnight.
Evaluate before you grant
The principle is simple: evaluate the claim, then grant the benefit. A benefit can be a trial, signup credits, a free plan or a promotion. Whatever it is, the check belongs at the point where your server is about to hand it out.
Checking at the claim, rather than only at account creation, protects each benefit on its own terms. A user might sign up today and claim credits next week, or claim a second benefit later. For why this matters to the economics, see the real cost of free trial abuse.
What you need
- An AbuseZero workspace. Start with Builder and pay as you go.
- A secret key from Developers → API keys, stored on your server as
ABUSEZERO_SECRET_KEY. - Node.js 22 or later for the SDK examples. Any other language can call the AbuseZero REST API directly.
Add the check, step by step
Install the AbuseZero package
npm install abusezeroOne package covers your server (abusezero/server) and your pages (abusezero/browser), with separate entry points so server code never loads in the browser.
Create the benefit in observe mode
A benefit is what you protect. Start it in observe mode: every claim is allowed while AbuseZero records what it would have decided.
const benefit = await abusezero.createBenefit({
name: "Pro trial",
key: "pro_trial",
policy_key: "balanced",
protection_mode: "observe",
config: {
eligibility: { kind: "once" },
},
}, "create-benefit-pro-trial");You can also create benefits in the dashboard, or with abusezero benefits create in the AbuseZero CLI.
Collect a device token on your page
The AbuseZero browser SDK connects the claim to AbuseZero's device and automation intelligence. Use the same claim ID in the browser and on your server.
import { init, observe } from "abusezero/browser";
init({ key: "pk_…" }); // once, when your app starts
const { deviceToken } = await observe({ key: "pk_…", claimId: trialId });
// Send deviceToken to your server with the claim.Evaluate the claim on your server
Call AbuseZero before you grant the benefit. The idempotency key makes the call safe to retry.
import { AbuseZero } from "abusezero/server";
const abusezero = new AbuseZero({
key: process.env.ABUSEZERO_SECRET_KEY!,
outage: "throw",
});
export async function startTrial(
user: { id: string; email: string; emailVerified: boolean },
trialId: string,
ip: string,
deviceToken: string,
) {
const evaluation = await abusezero.evaluate(
{
benefit: "pro_trial",
claim_id: trialId,
subject: { external_id: user.id, email: user.email, email_verified: user.emailVerified },
context: { ip },
identifiers: { device_token: deviceToken },
},
`evaluate-${trialId}`,
);
if ("status" in evaluation) {
// Skipped: no allow or deny was decided.
return { started: false };
}
if (evaluation.result === "deny") {
return { started: false };
}
// Grant the trial in your application here.
return { started: true };
}The response is one final result:
{
"object": "evaluation",
"id": "eval_3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a0c4e93",
"result": "allow",
"risk": { "score": 10, "band": "low" },
"reason": { "code": "default_allow", "message": "No rule matched, so the policy's default allowed this claim." },
"outcome": { "state": "assumed_granted", "due_at": null }
}Act on the result
Branch on result and keep the reason for your team. For credits, a denial can lead to a paid starter pack, as the AI credits playbook shows. Show denied users a neutral message with a way to reach you, and never explain what was detected. We cover the wording in multi-accounting detection without blocking real users.
A skipped evaluation, for example when a workspace has no credits left, is its own branch: no allow or deny was decided. See skipped evaluations.
Switch to protect
When the observe-mode results look right, set the benefit's mode to protect. Your code doesn't change. Before you do, you can replay a policy change against your recent traffic. See test changes safely. The full rollout is in shadow mode for abuse rules.
Ship the check today
The integration is one package and one server call. Start with Builder and protect your first benefit, or see pricing for Pro and Scale.
Grant now, evaluate in the background
For a benefit you can take back in full, you can let the user continue at once and evaluate in a background job. On deny, you take the benefit back. See zero-wait free trials.
| Benefit | Pattern |
|---|---|
| Trial days, plan access, a feature | Grant now, evaluate in the background. Take it back on deny. |
| AI or API credits, payouts, referral cash, promotional codes | Evaluate before you grant. These can be used up at once. |
The job can act on the response itself, or on the evaluation.completed webhook event. See evaluate in the background. To pick the right pattern for each offer, see how to prevent free trial abuse. More in AbuseZero webhooks.
Decide what happens if AbuseZero can't be reached
Every evaluation returns one final result within the evaluation's time limit, and evidence that is slow or unavailable doesn't hold it up. For the rare case where your server can't reach AbuseZero at all, choose your behavior up front with the SDK's outage option:
Reuse the same idempotency key on every retry, so a retry never creates a second evaluation. See handle outages and retries. To choose per benefit, see fail open or fail closed?
Use the tool your team prefers
Every action is available through the AbuseZero REST API, the AbuseZero Node.js SDK, the AbuseZero CLI and the AbuseZero MCP server, with the same inputs and the same results. Connect the AbuseZero MCP server to your AI coding agent and it can create benefits, run previews and read evaluations for you while you build. See AbuseZero MCP server and CLI.
Before launch, run through the go-live checklist.
Frequently asked questions
Should I check for trial abuse at signup or when the trial starts?
Check when the benefit is granted. If your trial starts at signup, that's the same moment. If users can sign up first and claim later, evaluate at the claim, so each benefit is protected on its own terms.
Will an abuse check slow down my signup flow?
The evaluation is one server-side call that returns within its time limit, with everything AbuseZero gathered in that window. For benefits you can take back, you can also grant at once and evaluate in the background.
Which languages does AbuseZero support?
Any language that can make an HTTPS request can use the AbuseZero REST API. The AbuseZero Node.js SDK adds typed methods, retries and outage handling for JavaScript and TypeScript servers.
Do I need the browser SDK?
The browser SDK is optional, and it gives every evaluation more evidence to work with. AbuseZero works from your server alone, and adding browser protection on the pages where claims start strengthens every check.
Can I set up AbuseZero from an AI coding agent?
Yes. The AbuseZero MCP server works with standards-compliant MCP clients, so your agent can manage benefits and run previews through the same actions as the API.
Add your first abuse check
Start with Builder
Pay as you go. One package, one server call.
Read the quickstart
Evaluate your first claim in minutes.
See pricing
Builder, Pro, Scale and Enterprise.
Keep reading
- How to prevent free trial abuse, starting with the offer itself
- Multi-accounting detection without blocking real users
- The real cost of free trial abuse for SaaS and AI apps
- AbuseZero MCP server and CLI: protect benefits from your agent
- AI agents are claiming your free trials. Let the right ones in.
- Why we built AbuseZero: an abuse prevention API for SaaS
- Zero-wait free trials: run your abuse check in the background
- AbuseZero webhooks: every evaluation in your own systems
- Fail open or fail closed? What your abuse check should do when it can't answer