AbuseZero

Add a bot check

Run AbuseZero's bot check when a person submits a claim, and decide how each benefit treats automation.

The bot check gives AbuseZero Automation Defense a verification taken at the moment the person submits a claim. It runs in the browser, and AbuseZero verifies it inside the evaluation that follows. You then decide, benefit by benefit, how detected automation is treated. For the bigger picture, see Bots and AI agents.

Before you begin

  • Browser protection is set up, and your server sends identifiers.device_token with every evaluation.
  • A server key with the scopes benefits:read, benefits:write, policies:read, evaluations:create and evaluations:read.

Run the bot check on submit

Call prepareBotObservation instead of observe in your submit handler. It takes the same options and returns the same deviceToken. Wait for it to finish before you send the form.

app/trial-form.ts
import { prepareBotObservation } from "abusezero/browser";

export async function submitTrial(claimId: string, email: string) {
  const { deviceToken } = await prepareBotObservation({ key: "pk_…", claimId });

  await fetch("/api/trial", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ claimId, email, deviceToken }),
  });
}

Call it on submit, not when the page loads. The result is tied to this claim and this moment.

Evaluate within 2 minutes

Send the deviceToken to AbuseZero as identifiers.device_token within 2 minutes, in evaluate() or POST /v1/evaluations. Your server code doesn't change.

  • A token sent later than that can't be verified. When the benefit requires a bot check, the evaluation returns BOT_EVIDENCE_REQUIRED. Run the bot check again and resubmit.
  • Each token belongs to one claim. Reusing it for another claim returns DEVICE_TOKEN_USED (conflict).

Choose how the benefit treats automation

Two benefit settings control automation. Change them on the Benefits page of the dashboard, with PATCH /v1/benefits/{id} in the AbuseZero REST API, with abusezero benefits update in the AbuseZero CLI, or with abusezero_update_benefit on the AbuseZero MCP server. Both are described in the Automation settings reference.

SettingValueEffect
automationassess (default)Detected automation counts toward the AbuseZero Risk Score.
denyDetected automation is denied, with the reason automation.
allowDetected automation doesn't count against the claim.
bot_evidenceoptional (default)Evaluations run with or without a bot check.
requiredAn evaluation without a usable bot check returns an error instead of a result.

Recognized AI agents that you allow on the benefit are exempt from both settings. See Verify AI agents.

A benefit update sends the benefit's full settings with its current revision. This helper reads the benefit and its policy with the SDK's additional methods, applies your changes and saves it:

lib/update-benefit-config.ts
import { abusezero } from "./abusezero";

type Benefit = {
  name: string;
  policy: string;
  mode: "protect" | "observe";
  revision: number;
  config: Record<string, unknown>;
};

export async function updateBenefitConfig(benefitId: string, changes: Record<string, unknown>) {
  const benefit = await abusezero.getBenefit(benefitId) as Benefit;
  const policy = await abusezero.getPolicy(benefit.policy) as { key: string };
  const config = Object.fromEntries(Object.entries(benefit.config).filter(([, value]) => value !== null));

  return abusezero.updateBenefit(benefitId, {
    name: benefit.name,
    policy_key: policy.key,
    protection_mode: benefit.mode,
    config: { ...config, ...changes },
    revision: benefit.revision,
  }, `benefit:${benefitId}:revision:${benefit.revision}`);
}
await updateBenefitConfig("ben_6f1d2c3b-4a5e-4f60-8b7c-9d0e1f2a3b4c", {
  automation: "deny",
  bot_evidence: "required",
});

If someone else saved the benefit since you read it, the update returns BENEFIT_CONFLICT (conflict). Read it again and retry.

Handle bot check errors

When bot_evidence is required, two errors mean the evaluation didn't run:

CodeStatusWhat to do
BOT_EVIDENCE_REQUIRED422The claim had no usable bot check. Run prepareBotObservation again and resubmit with the new token.
BOT_EVIDENCE_UNAVAILABLE503The bot check couldn't be verified this time. The error is retryable: collect fresh evidence and retry shortly. See unavailable errors.

The AbuseZero Node.js SDK always throws these errors, even when outage is "allow" or "deny". A missing bot check never becomes a local decision.

lib/evaluate-with-bot-check.ts
import { AbuseZeroError, type EvaluationRequest } from "abusezero/server";
import { abusezero } from "./abusezero";

export async function evaluateWithBotCheck(input: EvaluationRequest, attempt: number) {
  try {
    return await abusezero.evaluate(input, `evaluate:${input.claim_id}:${attempt}`);
  } catch (error) {
    if (error instanceof AbuseZeroError && error.code.startsWith("BOT_EVIDENCE_")) {
      return { status: "run_bot_check_again" as const };
    }
    throw error;
  }
}

The resubmitted claim keeps its claim_id but carries a new token, so it needs a new Idempotency-Key. Here the key includes an attempt number.

Verify your integration

Submit a claim from your page, then open its evaluation with GET /v1/evaluations/{id}.

curl https://api.abusezero.com/v1/evaluations/eval_3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a0c4e93 \
  -H "Authorization: Bearer $ABUSEZERO_SECRET_KEY"
  • browser_data is collected.
  • In the evaluation's evidence or the dashboard, the automation family has an assessment other than unavailable.

With automation set to deny, a claim submitted by automation is denied with the reason automation.

How is this guide?

Last updated on

On this page