Policy
The local acceptance rules the gate evaluates — caps, rate limits, reputation floor, mandate requirement, intent, and review routing — plus the STRICT / BALANCED / OPEN presets.
Your acceptance policy is a plain object the gate evaluates locally on every settle. Every field is optional; safe defaults fill the rest. Start from a preset, then tune.
The presets
Adopt a posture wholesale, then override individual fields. The presets are functions so each call yields a fresh, isolated copy.
The recommended default. Small spends clear on reputation alone; larger spends need a mandate; generous-but-bounded caps and rates; only the weakest tier is sent to review.
{
requireMandateOverUsd: 20,
minReputationTier: 'standard',
maxPerTransactionUsd: 500,
maxPerAgentPerDayUsd: 2000,
ratePerAgentPerHour: 60,
ratePerAgentPerDay: 300,
holdForReviewBelowTier: 'cautious',
}High-value / sensitive merchants. Always wants a mandate, a trusted reputation, modest caps, tight velocity, and routes anything not clearly trusted to human review.
{
requireMandateOverUsd: 0, // a mandate is required for ANY spend
minReputationTier: 'trusted',
maxPerTransactionUsd: 100,
maxPerAgentPerDayUsd: 250,
ratePerAgentPerHour: 10,
ratePerAgentPerDay: 50,
holdForReviewBelowTier: 'trusted',
}Maximum reach, minimum friction — e.g. cheap digital goods or content APIs where the paid-up-front rail is the guarantee and a bad sale costs almost nothing.
{
requireMandateOverUsd: Infinity, // effectively never require a mandate
minReputationTier: 'risky', // accept the lowest tier
maxPerTransactionUsd: 10000,
holdForReviewBelowTier: 'cautious', // nothing is below cautious → never holds
}Adopt and tweak
import { createCheckout, BALANCED } from '@veto-protocol/checkout';
const checkout = createCheckout({
merchant: { id: 'acme', name: 'Acme', domain: 'shop.acme.example' },
catalog: [/* … */],
receiving: { x402: { chain: 'base', address: '0x…', asset: 'USDC' } },
policy: {
...BALANCED(),
maxPerTransactionUsd: 250,
blockedAgents: ['00000000-0000-0000-0000-000000000000'],
forbiddenIntentKeywords: ['gift card', 'crypto'],
},
});The fields
| Field | Effect | Fires |
|---|---|---|
requireMandateOverUsd | Above this total, a valid mandate is required. | MANDATE_REQUIRED |
minReputationTier | Reputation floor (risky…elite). | REPUTATION_TOO_LOW |
maxPerTransactionUsd | Hard per-transaction cap. | OVER_PER_TX_CAP |
maxPerAgentPerDayUsd | Rolling 24h spend cap per agent. | OVER_DAILY_CAP |
ratePerAgentPerHour | Max transactions / agent / hour. | RATE_LIMITED_HOURLY |
ratePerAgentPerDay | Max transactions / agent / day. | RATE_LIMITED_DAILY |
blockedAgents | Explicit blocklist of agent ids. | AGENT_BLOCKED |
allowedRails | Restrict which rails may settle. | RAIL_NOT_ALLOWED |
forbiddenIntentKeywords | Reject if intent text contains a term. | INTENT_FORBIDDEN_KEYWORD |
requiredIntentMatch | Require intent↔cart match (needs an intentMatcher). | INTENT_MISMATCH |
holdForReviewBelowTier | Route below-tier requests to human review. | HOLD_FOR_REVIEW |
requiredIntentMatch: true holds every transaction unless you also wire an
intentMatcher into your config — otherwise there is no score to compare. The presets
deliberately leave it off for this reason.
See the full policy fields reference and the complete reason-code vocabulary.
Trust tiers
How a verified mandate and hosted reputation resolve to a trust tier — premium, trusted, standard, cautious — that your policy gates on.
Rails
The pluggable settlement interface — x402 (HTTP-402 + stablecoin), mock (offline tests), and the card stub. Bring your own receiving destination per rail; Veto never holds funds.