Policy fields
Every MerchantPolicy field, its type, default, and the reason code it fires. All fields are optional; safe defaults fill the rest.
MerchantPolicy is the acceptance policy the gate evaluates locally. Every field is
optional; normalizePolicy() fills the gaps with safe defaults. Caps and rates you don't
set stay undefined on purpose — "no cap" is a distinct, legitimate posture from
"default cap".
interface MerchantPolicy {
requireMandateOverUsd?: number;
minReputationTier?: 'risky' | 'standard' | 'trusted' | 'elite';
maxPerTransactionUsd?: number;
maxPerAgentPerDayUsd?: number;
ratePerAgentPerHour?: number;
ratePerAgentPerDay?: number;
blockedAgents?: string[];
allowedRails?: ('x402' | 'card' | 'mock')[];
forbiddenIntentKeywords?: string[];
requiredIntentMatch?: boolean;
holdForReviewBelowTier?: 'cautious' | 'standard' | 'trusted' | 'premium';
}Fields
| Field | Default | Fires |
|---|---|---|
requireMandateOverUsd | 20 | MANDATE_REQUIRED |
minReputationTier | standard | REPUTATION_TOO_LOW |
maxPerTransactionUsd | 500 | OVER_PER_TX_CAP |
maxPerAgentPerDayUsd | (none) | OVER_DAILY_CAP |
ratePerAgentPerHour | (none) | RATE_LIMITED_HOURLY |
ratePerAgentPerDay | (none) | RATE_LIMITED_DAILY |
blockedAgents | [] | AGENT_BLOCKED |
allowedRails | (all rails) | RAIL_NOT_ALLOWED |
forbiddenIntentKeywords | [] | INTENT_FORBIDDEN_KEYWORD |
requiredIntentMatch | false | INTENT_MISMATCH |
holdForReviewBelowTier | cautious | HOLD_FOR_REVIEW |
Preset values
| Field | STRICT() | BALANCED() | OPEN() |
|---|---|---|---|
requireMandateOverUsd | 0 | 20 | Infinity |
minReputationTier | trusted | standard | risky |
maxPerTransactionUsd | 100 | 500 | 10000 |
maxPerAgentPerDayUsd | 250 | 2000 | (none) |
ratePerAgentPerHour | 10 | 60 | (none) |
ratePerAgentPerDay | 50 | 300 | (none) |
holdForReviewBelowTier | trusted | cautious | cautious |
requiredIntentMatch: true holds every transaction unless you also wire an
intentMatcher into your CheckoutConfig — without a matcher there is no score to compare.
The presets deliberately leave it off.
Reason codes
The complete, stable rejection vocabulary. Every rejection (and several accepts) carries one or more of these SCREAMING_SNAKE_CASE codes — a stable API surface an agent keys off.
Type contract
The shared TypeScript interfaces the whole protocol agrees on — money, catalog, mandates, verdicts, sessions, and the merchant receipt.