AbuseZero

Previews, simulations and replays

Try a request or a policy change against the real evaluation engine before it reaches your users.

A preview runs the same evaluation as live traffic without recording a claim. Simulations and replays reuse the evidence your past evaluations retained and apply a policy to it, so a changed result comes from your policy change. Use them to see how AbuseZero will decide before anything changes for a real user.

EndpointScopeWhat it doesUses credits
POST /v1/evaluation-previewssimulations:runRuns one full evaluation and records nothing.Yes
POST /v1/simulationssimulations:runRuns a benefit's recent claims, in sequence, under a policy you choose.No
POST /v1/replayssimulations:runRe-decides a benefit's recent evaluations under a policy you choose, and shows which results would change.No

Preview an evaluation

POST /v1/evaluation-previews · Scope simulations:run · Requires Idempotency-Key

Also available as abusezero evaluations preview in the AbuseZero CLI, abusezero_preview_evaluation on the AbuseZero MCP server and previewEvaluation() in the AbuseZero Node.js SDK.

Runs a complete evaluation and returns the result without recording anything. The preview creates no evaluation, claim or outcome, and never affects a later evaluation.

A preview is a real evaluation and uses workspace credits, like POST /v1/evaluations. Previews and Test console runs also have their own rate limit, separate from evaluations. Over it, a preview returns 429 RATE_LIMITED with a Retry-After header.

Request body

The same body as Create an evaluation.

Example

import { randomUUID } from "node:crypto";

const preview = await abusezero.previewEvaluation(
  {
    benefit: "pro_trial",
    claim_id: "preview_user_4821",
    subject: { external_id: "user_4821", email: "jordan@example.com" },
    context: { ip: "203.0.113.42" },
  },
  randomUUID(),
);

Replace the example IP address with the user's public address. 203.0.113.42 comes from a range reserved for documentation, and AbuseZero rejects documentation, private and other non-routable addresses with IP_NOT_ROUTABLE.

Response

Returns 201.

{
  "object": "evaluation_preview",
  "preview": true,
  "result": "deny",
  "risk": { "score": null, "band": "not_assessed" },
  "reason": {
    "code": "prior_claim_user",
    "message": "This user already received this benefit."
  },
  "inputs": {
    "email": "received",
    "ip": "received",
    "user_id": "received",
    "phone": "missing",
    "payment": "missing",
    "device": "missing",
    "browser": "missing"
  }
}
FieldTypeDescription
objectstringAlways evaluation_preview.
previewbooleanAlways true.
resultstringallow or deny: the result a real evaluation would return now.
riskobjectThe AbuseZero Risk Score. See Evaluations.
reasonobject or nullWhy the result was reached. See Reason codes.
inputsobjectWhich inputs the preview received.

A preview can also return { "object": "evaluation_preview", "status": "skipped", "reason": … } when the workspace can't run it. See Skipped evaluations.

Errors

StatusCodeWhen
422IDEMPOTENCY_KEY_REQUIREDThe Idempotency-Key header is missing or invalid.
422INVALID_FIELDA field is missing, invalid or not defined for this endpoint. error.field names it.
422INVALID_EMAILsubject.email isn't in a supported form.
422INVALID_IPcontext.ip isn't a valid IPv4 or IPv6 address.
422IP_NOT_ROUTABLEcontext.ip is a private, loopback, documentation or other non-routable address. Send the user's public address, or leave it out.
422UNSUPPORTED_FIELDA custom identifier and key version aren't registered.
422DEVICE_TOKEN_INVALIDidentifiers.device_token isn't a value the browser SDK returned.
422DEVICE_TOKEN_SCOPEThe device token was collected for a different claim ID.
422BROWSER_SDK_UPGRADE_REQUIREDThe device token came from an outdated browser SDK.
422BOT_EVIDENCE_REQUIREDThe benefit requires a bot check and the preview has none that can be used.
422AGENT_EVIDENCE_SCOPEagent_evidence was produced for a different claim.
422AGENT_EVIDENCE_OUTDATEDagent_evidence came from a Node.js SDK before 0.11.0. Update the SDK.
404BENEFIT_NOT_FOUNDNo benefit has this key.
409IDEMPOTENCY_CONFLICTThe key was already used with a different body.
409EVALUATION_PENDINGA preview with this key is still running. Retry with the same key.
409CLAIM_CONFLICTThe claim ID belongs to a different user.
409DEVICE_TOKEN_USEDThe device token was already used for another claim.
409DELETION_IN_PROGRESSThe user's history or the workspace is being deleted.
409POLICY_UNAVAILABLEThe benefit's policy isn't available.
413PAYLOAD_TOO_LARGEThe body is over 256 KiB.
429RATE_LIMITEDThe workspace is over a traffic limit. Wait for Retry-After.
503BOT_EVIDENCE_UNAVAILABLEThe bot check couldn't be completed. Collect new browser data and retry.
504DEADLINE_EXCEEDEDThe preview reached its time limit. Retry with the same key.

Run a simulation

POST /v1/simulations · Scope simulations:run

Also available as abusezero simulations run in the AbuseZero CLI, abusezero_simulate_sequence on the AbuseZero MCP server and simulate() in the AbuseZero Node.js SDK.

Runs a benefit's most recent evaluations again, one after another, under the policy you choose, as if that policy had been active at the time. The sequence starts from an empty history, and each step sees the claims the simulation allowed before it, so a simulation shows how a policy handles repeat claims across a sequence.

Simulations use evaluations whose request details are still retained. They apply the chosen policy and the benefit's current settings, not your allow and block list entries. They use no credits and change nothing.

Request body

FieldTypeRequiredDescription
benefit_idstringYesThe benefit's ID, starting with ben_.
policy_keystringYesThe key of the policy to simulate: a protection level (lenient, balanced or strict) or one of your custom policies. Up to 64 characters.

Example

const simulation = await abusezero.simulate({
  benefit_id: "ben_5b2e9c41-7d3a-4f68-a1c0-9e8d7b6a5f24",
  policy_key: "strict",
});

Response

Returns 201.

{
  "object": "simulation",
  "data": [
    {
      "step": 1,
      "evaluation": "eval_3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a0c4e93",
      "result": "allow",
      "reason": {
        "code": "default_allow",
        "message": "No rule matched, so the policy's default allowed this claim."
      }
    },
    {
      "step": 2,
      "evaluation": "eval_8a1d4f20-6c3b-4e57-b9d2-0f7e6a5c3b18",
      "result": "deny",
      "reason": {
        "code": "prior_claim_email",
        "message": "An earlier claim used this email address."
      }
    }
  ]
}
FieldTypeDescription
objectstringAlways simulation.
data[].stepintegerThe step's position in the sequence, starting at 1.
data[].evaluationstringThe original evaluation the step re-ran.
data[].resultstringallow or deny under the simulated policy.
data[].reasonobject or nullWhy the simulated policy reached that result.

The benefit's current protection mode applies. In observe mode, every result is allow.

Errors

StatusCodeWhen
404POLICY_NOT_FOUNDThe benefit or the policy doesn't exist in this workspace.
422INVALID_FIELDbenefit_id or policy_key is missing or invalid.

Run a replay

POST /v1/replays · Scope simulations:run

Also available as abusezero simulations replay in the AbuseZero CLI, abusezero_replay_evaluations on the AbuseZero MCP server and replay() in the AbuseZero Node.js SDK.

Re-decides a benefit's most recent evaluations under the policy you choose, using what each evaluation recorded, and shows every result that would change. Save a change as a draft policy and replay it before you assign it to a benefit.

Replays make no new lookups. They apply the chosen policy and the benefit's current settings to each evaluation's retained record, not your allow and block list entries. They use no credits and change nothing.

Request body

FieldTypeRequiredDescription
benefit_idstringYesThe benefit's ID, starting with ben_.
policy_keystringYesThe key of the policy to replay: a protection level (lenient, balanced or strict) or one of your custom policies. Up to 64 characters.

Example

const replay = await abusezero.replay({
  benefit_id: "ben_5b2e9c41-7d3a-4f68-a1c0-9e8d7b6a5f24",
  policy_key: "trial_protection",
});

const rows = replay.data as { evaluation: string; changed: boolean }[];
const changed = rows.filter((row) => row.changed);

Response

Returns 201.

{
  "object": "replay",
  "limit": 500,
  "data": [
    {
      "evaluation": "eval_3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a0c4e93",
      "original": "allow",
      "replayed": "allow",
      "changed": false
    },
    {
      "evaluation": "eval_d2b7f9a4-5e1c-4a38-9f6d-7c3e1b8a0d52",
      "original": "allow",
      "replayed": "deny",
      "changed": true
    }
  ]
}
FieldTypeDescription
objectstringAlways replay.
limitintegerThe most evaluations one replay covers. The newest evaluations are replayed first.
data[].evaluationstringThe evaluation that was replayed.
data[].originalstringThe result it received.
data[].replayedstringThe result under the chosen policy.
data[].changedbooleantrue when the two results differ.

The benefit's current protection mode applies. In observe mode, every replayed result is allow.

Errors

StatusCodeWhen
404POLICY_NOT_FOUNDThe benefit or the policy doesn't exist in this workspace.
422INVALID_FIELDbenefit_id or policy_key is missing or invalid.

Next steps

How is this guide?

Last updated on

On this page