DOCS / THE EXPENSE ACCOUNT

The expense account

A spend grant is policy, not custody: an allowlist of hosts plus USD caps, enforced in-process beforeany payment is signed. It's the guardrail against runaway loops, bugs, and prompt-injected tool calls — one grant authorizes many endpoints.

The grant

grant: {
  id: 'cmq…',                // optional: a yeetful.com grant this mirrors (enables ledger sync)
  allow: ['tripadvisor.x402.paysponge.com'], // exact hostnames this agent may pay
  perCallUsd: 0.05,          // max for any single call
  perDayUsd: 2,              // rolling UTC-day budget
  totalUsd: 25,              // optional lifetime cap for this client instance
  expiresAt: '2026-12-31',   // Date, ISO string, or unix ms — omit for no expiry
  status: 'active',          // 'revoked' refuses everything
}

Checks run in order — status, expiry, allowlist before any network I/O; the price caps when the 402 challenge reveals what the call costs — and the first violation throws a typed GrantError:

GrantError.codeMeaning
NOT_ALLOWEDHost isn't on the allowlist (denied before any network I/O)
OVER_PER_CALLThe challenge priced this single call above perCallUsd
BUDGET_EXCEEDEDToday's (or the lifetime) budget would be passed
EXPIREDThe grant's expiresAt is in the past
REVOKEDstatus: 'revoked'

Receipts — the audit trail

Every decision emits a Receipt, refusals included. That's deliberate: an audit trail that only shows successes isn't one.

onReceipt: (r) => {
  // { host, amountUsd, ok, txHash?, note, ts }
  // note: 'settled' on success, or the GrantViolation code on a denial
}

Settlement transaction hashes come from the x402 settle header and are verifiable on Basescan. Live totals are always available on the client: pay.spentTodayUsd(), pay.remainingTodayUsd(), pay.spentTotalUsd().

Local vs. hard enforcement

The SDK enforces the grant in-process — instant, free, and ideal for governing your own agents. It is not an adversarial guarantee: code that bypasses pay() bypasses the grant. For hard guarantees, back the grant with an on-chain Coinbase Spend Permission so the wallet contract caps spend no matter what the process does. The yeetful.com dashboard is the control plane for both: approvals derive the allowlist, caps are EIP-712-signable, and every receipt lands in the hosted ledger.