AbuseZero

Benefits

Create and manage the benefits AbuseZero protects, and how each one is evaluated.

A benefit is something you give users a limited number of times: a trial, a free plan, sign-up credits, a promotion. Each benefit has a key you send with every evaluation, a policy that decides its claims, and settings for eligibility, outcomes, automation and agents.

EndpointScope
POST /v1/benefitsbenefits:write
GET /v1/benefitsbenefits:read
GET /v1/benefits/{id}benefits:read
PATCH /v1/benefits/{id}benefits:write
DELETE /v1/benefits/{id}benefits:write

With an OAuth access token, benefits:write also needs the member's Publish policies and benefits permission.

The benefit object

FieldTypeDescription
objectstringAlways benefit.
idstringThe benefit's ID, starting with ben_.
keystringThe key you send as benefit in evaluations. Unique in the workspace and fixed after creation.
namestringThe benefit's display name.
policystringThe ID of the policy that decides its claims, starting with pol_. See Policies and rules.
modestringprotect or observe. See Protection mode.
configobjectThe benefit's settings. See Benefit configuration.
revisionintegerIncreases with every update. Send it back when you update the benefit.
created_atstringWhen the benefit was created.

Protection mode

ModeBehavior
protectEvaluations return the result your policy reaches.
observeEvaluations always return allow. Each evaluation records the result your policy would have reached as observed_result, so you can measure a policy on real traffic before it affects anyone.

Benefit configuration

Every field is optional when you create a benefit. A field you leave out takes its default.

FieldTypeDefaultDescription
eligibilityobject{ "kind": "once" }How often one user may receive the benefit. Fixed after creation. See Eligibility.
outcome_trackingstringassume_grantedassume_granted: an allowed claim counts as granted at once. report_outcome: you report the outcome of each allowed claim by its due_at.
missing_outcome_behaviorstringhold_eligibilityFor report_outcome benefits. What happens when no report arrives by due_at. hold_eligibility: the claim keeps counting. release_eligibility: the claim stops counting, and the user can claim again.
automationstringassessHow automated activity is treated. See Automation.
bot_evidencestringoptionaloptional or required. With required, every evaluation must carry a bot check from the browser SDK, or it returns BOT_EVIDENCE_REQUIRED. Allowed recognized agents are exempt.
allowed_agentsarray of strings[]The recognized AI agents allowed to claim this benefit. Use IDs from GET /v1/agents. At most 1 item.
valuationobject{ "currency": "USD", "face_value": 0, "delivery_cost": 0 }What one award is worth and costs you. See Valuation.

Eligibility

ValueMeaning
{ "kind": "once" }One award per user, ever.
{ "kind": "calendar", "period": "day", "timezone": "Europe/Berlin" }One award per calendar day, week or month, in the IANA time zone you set (up to 80 characters). Weeks start on Monday.
{ "kind": "rolling", "days": 30 }One award per rolling window of 1 to 365 days.

To change a benefit's eligibility, create a new benefit. The existing benefit keeps its protection and history.

Automation

ValueBehavior
assessAbuseZero Automation Defense's assessment counts toward the AbuseZero Risk Score.
denyDetected automation denies the claim, with the reason automation.
allowDetected automation doesn't count against the claim.

Recognized agents in allowed_agents are never treated as unwanted automation for this benefit. See Bots and AI agents.

Valuation

FieldTypeDescription
currencystringA three-letter ISO 4217 code in capitals, such as USD.
face_valuenumberWhat one award is worth to the user, from 0 to 10,000,000,000, with up to two decimals.
delivery_costnumberWhat one award costs you to deliver, in the same range.

Each outcome keeps the valuation in force when it was recorded.

Create a benefit

POST /v1/benefits · Scope benefits:write · Requires Idempotency-Key

Also available as abusezero benefits create in the AbuseZero CLI, abusezero_create_benefit on the AbuseZero MCP server and createBenefit() in the AbuseZero Node.js SDK.

Request body

FieldTypeRequiredDescription
namestringYesDisplay name, 1 to 80 characters.
keystringYesThe key you'll send in evaluations. Lowercase letters, numbers and underscores, starting with a letter; up to 64 characters. Unique in the workspace: a key that's already used returns BENEFIT_KEY_TAKEN.
policy_keystringYesThe policy that decides claims: a protection level (lenient, balanced or strict) or one of your custom policies.
protection_modestringYesprotect or observe.
configobjectYesThe benefit configuration. Send {} to use every default.

Example

import { randomUUID } from "node:crypto";

const benefit = await abusezero.createBenefit(
  {
    name: "Pro trial",
    key: "pro_trial",
    policy_key: "balanced",
    protection_mode: "protect",
    config: {
      eligibility: { kind: "once" },
      outcome_tracking: "report_outcome",
      missing_outcome_behavior: "hold_eligibility",
      valuation: { currency: "USD", face_value: 49, delivery_cost: 6.5 },
    },
  },
  randomUUID(),
);

Response

Returns 201.

{
  "object": "benefit",
  "id": "ben_5b2e9c41-7d3a-4f68-a1c0-9e8d7b6a5f24",
  "revision": 1
}

Errors

StatusCodeWhen
422IDEMPOTENCY_KEY_REQUIREDThe Idempotency-Key header is missing or invalid.
422INVALID_FIELDA field is missing or invalid. error.field names it.
422POLICY_NOT_FOUNDNo policy has this policy_key.
422INVALID_TIMEZONEThe calendar eligibility's timezone isn't a recognized IANA time zone. field is config.eligibility.timezone.
409BENEFIT_KEY_TAKENAnother benefit already uses this key. field is key.
409IDEMPOTENCY_CONFLICTThe key was already used with a different body.

List benefits

GET /v1/benefits · Scope benefits:read

Also available as abusezero benefits list in the AbuseZero CLI, abusezero_list_benefits on the AbuseZero MCP server and benefits() in the AbuseZero Node.js SDK.

Lists benefits, newest first.

Query parameters

ParameterTypeRequiredDescription
limitintegerNoItems per page, 1 to 100. Defaults to 50.
cursorstringNoThe next_cursor from the previous page.

Example

const page = await abusezero.benefits({ limit: 50 });

Response

A list of benefit objects.

Errors

StatusCodeWhen
422CURSOR_INVALIDThe cursor was changed or belongs to another list.

Retrieve a benefit

GET /v1/benefits/{id} · Scope benefits:read

Also available as abusezero benefits get in the AbuseZero CLI, abusezero_get_benefit on the AbuseZero MCP server and getBenefit() in the AbuseZero Node.js SDK.

Example

const benefit = await abusezero.getBenefit("ben_5b2e9c41-7d3a-4f68-a1c0-9e8d7b6a5f24");

Response

{
  "object": "benefit",
  "id": "ben_5b2e9c41-7d3a-4f68-a1c0-9e8d7b6a5f24",
  "key": "pro_trial",
  "name": "Pro trial",
  "policy": "pol_7a1e3c95-4d2b-4e68-9f0a-5c8d2b6e4a17",
  "mode": "protect",
  "config": {
    "eligibility": { "kind": "once" },
    "outcome_tracking": "report_outcome",
    "missing_outcome_behavior": "hold_eligibility",
    "automation": "assess",
    "bot_evidence": "optional",
    "allowed_agents": [],
    "valuation": { "currency": "USD", "face_value": 49, "delivery_cost": 6.5 }
  },
  "revision": 1,
  "created_at": "2026-10-29T13:40:00.000Z"
}

Errors

StatusCodeWhen
404RESOURCE_NOT_FOUNDNo benefit with this ID exists in the workspace.
422INVALID_FIELDThe ID doesn't start with ben_.

Update a benefit

PATCH /v1/benefits/{id} · Scope benefits:write · Requires Idempotency-Key

Also available as abusezero benefits update in the AbuseZero CLI, abusezero_update_benefit on the AbuseZero MCP server and updateBenefit() in the AbuseZero Node.js SDK.

Replaces the benefit's name, policy, protection mode and configuration. Send every field, including the configuration fields you aren't changing: a configuration field you leave out returns to its default. The key and eligibility can't change.

The benefit object gives its policy as an ID. To keep the current policy, retrieve the policy and send its key as policy_key.

Changes apply to evaluations from the moment the update succeeds. Earlier evaluations keep the settings they ran under.

Request body

FieldTypeRequiredDescription
namestringYesDisplay name, 1 to 80 characters.
policy_keystringYesThe policy that decides claims.
protection_modestringYesprotect or observe.
configobjectYesThe complete benefit configuration. eligibility must match the current value.
revisionintegerYesThe benefit's current revision.

Example

import { randomUUID } from "node:crypto";

const current = await abusezero.getBenefit("ben_5b2e9c41-7d3a-4f68-a1c0-9e8d7b6a5f24");

await abusezero.updateBenefit(
  "ben_5b2e9c41-7d3a-4f68-a1c0-9e8d7b6a5f24",
  {
    name: current.name,
    policy_key: "strict",
    protection_mode: "observe",
    config: current.config,
    revision: current.revision,
  },
  randomUUID(),
);

Response

Returns 200.

{
  "object": "benefit",
  "id": "ben_5b2e9c41-7d3a-4f68-a1c0-9e8d7b6a5f24",
  "revision": 2
}

Errors

StatusCodeWhen
404BENEFIT_NOT_FOUNDNo benefit with this ID exists in the workspace.
409BENEFIT_CONFLICTrevision isn't the current revision. Read the benefit again.
409BENEFIT_SCOPE_FIXEDThe update changes eligibility. Create a new benefit instead.
409IDEMPOTENCY_CONFLICTThe key was already used with a different body.
422POLICY_NOT_FOUNDNo policy has this policy_key.
422INVALID_TIMEZONEThe calendar eligibility's timezone isn't a recognized IANA time zone. field is config.eligibility.timezone.
422INVALID_FIELDA field is missing or invalid. error.field names it.
422IDEMPOTENCY_KEY_REQUIREDThe Idempotency-Key header is missing or invalid.

Delete a benefit

DELETE /v1/benefits/{id} · Scope benefits:write · Requires Idempotency-Key

Also available as abusezero benefits delete in the AbuseZero CLI, abusezero_delete_benefit on the AbuseZero MCP server and deleteBenefit() in the AbuseZero Node.js SDK.

Deleting a benefit is permanent. It also deletes the allow and block list entries that apply only to this benefit. Evaluations that send its key fail with BENEFIT_NOT_FOUND from then on.

Example

import { randomUUID } from "node:crypto";

await abusezero.deleteBenefit("ben_5b2e9c41-7d3a-4f68-a1c0-9e8d7b6a5f24", randomUUID());

Response

Returns 200.

{
  "object": "deleted",
  "id": "ben_5b2e9c41-7d3a-4f68-a1c0-9e8d7b6a5f24",
  "deleted": true
}

Errors

StatusCodeWhen
404BENEFIT_NOT_FOUNDNo benefit with this ID exists in the workspace.
422IDEMPOTENCY_KEY_REQUIREDThe Idempotency-Key header is missing or invalid.

How is this guide?

Last updated on

On this page