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.code | Meaning |
|---|---|
NOT_ALLOWED | Host isn't on the allowlist (denied before any network I/O) |
OVER_PER_CALL | The challenge priced this single call above perCallUsd |
BUDGET_EXCEEDED | Today's (or the lifetime) budget would be passed |
EXPIRED | The grant's expiresAt is in the past |
REVOKED | status: '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.