Decision codes

Reference table of every verdict Saifuro returns and what happens next.

Every spend request ends in one of these codes. A code always carries a reason and a record.

Spend requestIs there an applicable mandate?deny_no_mandateIs the mandate still in date?deny_expiredHas it been revoked?deny_revokedIs the category allowed?deny_categoryIs the amount within the limit?deny_limitDo the velocity rules clear?deny_velocityIs it above the review threshold?reviewallowevery outcome is signed, metered and logged
CodeWhen it occursWhat happens next
allowRequest is within the mandate and policiesSettlement proceeds through the provider
reviewPolicy requires confirmation: soft limit, new category, unusual recipientOperation waits for the mandate owner
deny_limitAmount limit exceededDenied, agent receives the reason
deny_velocityA frequency rule triggeredDenied, the spike is recorded
deny_categoryCategory outside the mandateDenied before the provider is contacted
deny_expiredMandate has expiredDenied, a new mandate is required
deny_revokedMandate was revokedDenied, effective on the next request
deny_no_mandateNo applicable mandate foundDenied, spending without authority is not possible

Six denial codes instead of one generic failure exist for triage. deny_limit is a finance conversation, deny_category usually means the allowed list is out of date, and deny_no_mandate is almost always a misconfigured agent.

Both the agent and the mandate owner can see which rule fired and under which policy version, without opening a support ticket.

What a decision looks like

A 720 dollar purchase against the procurement mandate from core concepts, which caps single transactions at 500:

{
  "decision": "dec_91c4",
  "request": {
    "agent": "agt_procurement_01",
    "amount": 720.00,
    "recipient": "vendor:acme_saas",
    "category": "saas"
  },
  "verdict": "deny_limit",
  "reason": "amount 720.00 exceeds per_transaction limit 500.00",
  "mandate": "mnd_7f3a",
  "policy_version": "pol_2026-08-12.3",
  "nonce": "n_4c81ba97",
  "mode": "enforce",
  "issued_at": "2026-09-03T08:43:11Z",
  "verdict_token": "eyJhbGciOiJFUzI1NiIs..."
}

The policy version is what makes the verdict reconstructable later. The same request under a different rule set may resolve differently, and the log says which one applied.

Every verdict is signed over the fields above. An allow also carries a short expiry, after which it can no longer be presented for settlement. An approval therefore cannot be replayed for a second purchase or reused at a larger amount, and a counterparty can verify one against the public key without access to Saifuro. See the threat model.

The field names above are canonical — the decision object in the API reference returns exactly these.

On this page