The chargeback was load-bearing. For twenty-five years, "I didn't authorize this" was the escape hatch that made handing your card to a stranger's website feel safe — the merchant ate the fraud risk, and everyone shopped anyway. The moment an autonomous agent initiates the purchase, that hatch narrows. Did the user authorize this buy, this category, this ceiling? The answer now lives in your logs, and if you can't reconstruct it, you lose the dispute by default. This is the how-to for the log that keeps you out of that hole — and the good news is you don't have to design the schema, because AP2 already did.
The schema is three signed records#
Google's Agent Payments Protocol (AP2) — contributed to the FIDO Alliance in May 2026, backed by Stripe, Visa, Mastercard, PayPal, and 60+ partners — defines exactly what to keep. It carries three Mandates as W3C Verifiable Credentials: cryptographically signed, independently checkable records.
- Intent Mandate — what the user authorized: scope, spend caps, expiry. Signed at delegation.
- Cart Mandate — what the agent selected: exact items, prices, merchant. Signed when the cart is built.
- Payment Mandate — what was charged: amount, method, rail, receipt. Signed at settlement.
Log all three, stitched by one correlation id. That triple answers the three questions every dispute opens with: was this authorized, did the agent buy what I meant, and what actually hit my account?
The fields AP2 forgets#
Here is the non-obvious part. The mandates prove authorization; they say nothing about the agent's reasoning. When the complaint is "the agent bought the wrong thing," a valid Payment Mandate confirms the charge was in-scope and still loses you the argument. You have to capture the decision context yourself:
{
"correlation_id": "agtxn_9f3k2c",
"intent_mandate": { "...": "AP2 VC, user-signed" },
"cart_mandate": { "...": "AP2 VC, agent-signed" },
"payment_mandate": { "...": "AP2 VC, settled, PAN tokenized" },
"decision": {
"model": "claude-opus-x",
"prompt_version": "checkout-v7",
"tool_calls": [ { "name": "search_catalog", "result_hash": "…" } ],
"spend_cap_state": { "remaining_daily": 4200, "cap": 20000 },
"human_approval": { "required": true, "approver": "jane@co", "at": "…" }
},
"retention_class": "payment-authorization"
}
Snapshot the spend-cap state at decision time — don't recompute it later, because "was it in budget then" is the question, and the balance has moved since. Record the model and prompt version, so a bad buy traceable to a prompt regression is a bug you can find, not a mystery. And above a threshold you set, require and store a human-approval record; that one field is the difference between "a person signed off on the $5,000 purchase" and a shrug.
AP2 is the envelope that proves authority moved from user to agent. Your decision log is the letter inside that proves the agent used it sanely. You need both.
Keep it for years, redact the card#
Two rules people get backwards. Retention: payment-authorization logs are not application logs. You might rotate app traces at 30 or 90 days; these live on chargeback, tax, and regulatory clocks measured in years. Set a distinct retention class so a default TTL never silently deletes your only defense. Redaction: never store the raw PAN — the mandates reference tokenized methods precisely so you don't have to. Keep the intent, the cart, the charge, and the reasoning; drop the card number.
The pattern underneath is the one that governs every agent with real-world reach: you cannot trust the agent's own account of what it did, so you build an external record it can't edit. When the thing the agent can do is spend, that record isn't telemetry. It's the escape hatch the chargeback used to be.



