AbuseZero

Outcomes

Report whether an allowed claim was granted, and read the outcome of every claim.

Every allowed claim has an outcome: the record of whether the user actually received the benefit. The outcomes you report become the history that later evaluations are checked against.

EndpointScope
POST /v1/evaluations/{id}/outcomeoutcomes:write
GET /v1/outcomesoutcomes:read
GET /v1/outcomes/{id}outcomes:read

How outcomes start depends on the benefit's outcome_tracking setting. See Benefits.

The outcome object

FieldTypeDescription
objectstringAlways outcome.
idstringThe outcome's ID, starting with out_.
evaluationstring or nullThe evaluation that allowed the claim. null for an imported outcome. See Evaluations.
statestringThe outcome's state. See Outcome states.
sourcestringevaluation when an evaluation created it, or import when it came from an import.
occurred_atstringWhen the claim was allowed, or when an imported benefit was granted.
due_atstring or nullWhen the outcome report is due, for benefits that use report_outcome. Otherwise null.

Outcome states

StateMeaningCounts toward eligibility
assumed_grantedThe benefit uses assume_granted, so the allowed claim counts as granted at once.Yes
awaiting_outcomeThe benefit uses report_outcome. AbuseZero is waiting for your report by due_at.Yes
grantedYou reported or imported that the user received the benefit.Yes
not_grantedYou reported that the user didn't receive the benefit. The user can claim it again.No
outcome_unknownNo report arrived by due_at. The benefit's missing_outcome_behavior decides whether it counts.hold_eligibility: yes. release_eligibility: no.
reversedYou reported that a granted benefit was taken back. The claim still counts.Yes

New states can be added within v1.

Report an outcome

POST /v1/evaluations/{id}/outcome · Scope outcomes:write · Requires Idempotency-Key

Also available as abusezero outcomes report in the AbuseZero CLI, abusezero_report_outcome on the AbuseZero MCP server and outcome() in the AbuseZero Node.js SDK.

Reports what happened to an allowed claim. {id} is the ID of the evaluation that allowed it.

Report granted when you deliver the benefit and not_granted when you don't. Report reversed when you take a granted benefit back. For a benefit that uses report_outcome, report by the due_at the evaluation returned.

Request body

FieldTypeRequiredDescription
outcomestringYesgranted, not_granted or reversed.
reasonstringWith not_granted or reversedWhy the outcome changed, 3 to 500 characters. Required when you report not_granted or reversed and the outcome is in a different state.
external_outcome_idstringNoYour own ID for the grant, such as a subscription or order ID. 1 to 128 printable characters with no spaces.

Allowed changes

You reportAllowed when the outcome is
grantedassumed_granted, awaiting_outcome or outcome_unknown
not_grantedassumed_granted, awaiting_outcome or outcome_unknown
reversedgranted or assumed_granted

Reporting the state the outcome already has changes nothing, and is a safe way to attach an external_outcome_id. Every change is recorded in your audit log.

Example

import { randomUUID } from "node:crypto";

const report = await abusezero.outcome(
  "eval_3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a0c4e93",
  { outcome: "granted", external_outcome_id: "sub_20481" },
  randomUUID(),
);

Response

Returns 200.

{
  "object": "outcome_report",
  "evaluation": "eval_3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a0c4e93",
  "state": "granted",
  "conflicts": []
}
FieldTypeDescription
objectstringAlways outcome_report.
evaluationstringThe evaluation the outcome belongs to.
statestringThe outcome's state after the report.
conflictsarrayOutcome IDs that now overlap with this claim. See below.

Conflicts

For a benefit that uses release_eligibility, a claim stops counting when its report is overdue. If you then report it granted, other claims with the same identifiers may have been allowed in the meantime. conflicts lists their outcome IDs so you can reconcile them in your application. It's empty in every other case.

Errors

StatusCodeWhen
422IDEMPOTENCY_KEY_REQUIREDThe Idempotency-Key header is missing or invalid.
422INVALID_FIELDoutcome is missing, a field is invalid, or the ID doesn't start with eval_.
422UNSUPPORTED_FIELDThe body has a field this endpoint doesn't define.
422REASON_REQUIREDA not_granted or reversed report that changes the outcome has no reason.
404EVALUATION_NOT_FOUNDNo evaluation with this ID exists in the workspace.
409OUTCOME_CONFLICTThe evaluation was denied, a newer evaluation replaced it for this claim, the change isn't allowed from the current state, or the external_outcome_id belongs to another outcome. Read the evaluation's current outcome before reporting again.
409IDEMPOTENCY_CONFLICTThe key was already used with a different body.
429RATE_LIMITEDThe workspace is over a traffic limit. Wait for Retry-After.

List outcomes

GET /v1/outcomes · Scope outcomes:read

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

Lists outcomes, 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.outcomes({ limit: 50 });

Response

{
  "object": "list",
  "data": [
    {
      "object": "outcome",
      "id": "out_9e7c5a31-2d4b-4f86-b0a9-6c1e8d3f5a72",
      "evaluation": "eval_3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a0c4e93",
      "state": "assumed_granted",
      "source": "evaluation",
      "occurred_at": "2026-10-29T14:02:47.000Z",
      "due_at": null
    },
    {
      "object": "outcome",
      "id": "out_1f3a5c7e-9b2d-4e6f-8a0c-3d5e7f9a1b24",
      "evaluation": null,
      "state": "granted",
      "source": "import",
      "occurred_at": "2026-09-14T08:30:00.000Z",
      "due_at": null
    }
  ],
  "next_cursor": "kZ3x9QvB7mT2pLr8Wn4cYh6dFs1aJe5u"
}

Errors

StatusCodeWhen
422CURSOR_INVALIDThe cursor was changed or belongs to another list.
422INVALID_FIELDA query parameter is invalid.

Retrieve an outcome

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

Also available as abusezero outcomes get in the AbuseZero CLI, abusezero_get_outcome on the AbuseZero MCP server and getOutcome() in the AbuseZero Node.js SDK.

Returns one outcome object.

Example

const outcome = await abusezero.getOutcome("out_9e7c5a31-2d4b-4f86-b0a9-6c1e8d3f5a72");

Response

{
  "object": "outcome",
  "id": "out_9e7c5a31-2d4b-4f86-b0a9-6c1e8d3f5a72",
  "evaluation": "eval_3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a0c4e93",
  "state": "granted",
  "source": "evaluation",
  "occurred_at": "2026-10-29T14:02:47.000Z",
  "due_at": null
}

Errors

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

Next steps

How is this guide?

Last updated on

On this page