ブログ • AI / Agent Payments
Agent Payments Protocol(AP2)とは?2026 AI Agent 自動支払い・JSON API・スマート取引の解説
When you wire an AI shopping or procurement agent, the docs mention A2A, MCP, and a payments protocol called AP2. The first two cover conversation and tools; AP2 covers what authorizes the agent to spend.
Agent Payments Protocol (AP2) is an open protocol Google announced in September 2025 with 60+ payments and technology companies. It adds verifiable authorization, authentic intent, and after-the-fact accountability when an agent pays for a user. The 2026 implementation draft (v0.2) splits a transaction into two verifiable credentials—Checkout Mandate and Payment Mandate—with JSON payloads, typically wrapped as SD-JWT.
This article covers:
- The three problems AP2 solves: authorization, authenticity, accountability
- What each of the five roles verifies
- What Checkout / Payment Mandate JSON looks like
- How human-present pay differs from autonomous pay
- How to validate with JSON Schema and debug locally in JSONNote
Keep this in mind: AP2 is not another checkout UI, and it is not a Stripe replacement. It is the trust layer for agent payments: a cryptographically signed Mandate proves the user allowed this transaction. Below we walk through why it is needed → roles → Mandate JSON → two modes → schema validation → how it stacks with A2A/MCP.
What AP2 is
Google Cloud announcement defines AP2 as a payment-agnostic open protocol: users, merchants, and payment institutions share one language for agent-initiated transactions. It can serve as a payments extension of Agent2Agent (A2A) and Model Context Protocol (MCP), without replacing either.
The 2026 public spec is AP2 Specification v0.2; reference implementations live in google-agentic-commerce/AP2.
The core object is not an “order form.” It is a Mandate: a tamper-evident, verifiable digital contract proving the user gave the agent permission for a purchase or a class of constrained purchases. The spec wraps Mandates in SD-JWT verifiable digital credentials—not a bare JSON POST.
The launch narrative used three credentials—Intent, Cart, and Payment Mandates. The current v0.2 draft converges on two, and distinguishes open vs closed:
| Concept | v0.2 equivalent | What it proves |
|---|---|---|
| Intent / open constraints | Open Checkout / Open Payment Mandate | User-preapproved budget, merchant scope, and expiry |
| Cart / closed checkout | Closed Checkout Mandate | This cart’s items, prices, and merchant-signed Checkout JWT |
| Payment | Closed Payment Mandate | Amount, payee, and instrument for this Checkout |
Don’t get stuck on three vocabularies in older posts: product language is intent → cart → pay; the implementation is open constraints plus closed Checkout/Payment.
Why agent payments need a new protocol
Classic ecommerce assumes a human clicks Buy on a trusted page. Once an agent can place the order, that assumption breaks. AP2 answers three questions:
- Authorization: Did the user explicitly allow this charge, or charges inside this constraint set?
- Authenticity: How does the merchant know the cart the agent submitted is the one the user agreed to—not a hallucinated SKU?
- Accountability: After fraud or a mistake, Mandates and Receipts form a non-repudiable evidence chain.
A prompt like “buy me tickets” has no cryptographic boundary. The model can change quantity, swap merchants, or resubmit. AP2 binds user-signed constraints to the agent-assembled closed order. Verification must run in deterministic code—not another LLM judgment.
The rails stay cards, bank transfers, or stablecoins. AP2 does not clear funds; it only answers whether this agent transaction was authorized. For crypto, the A2A x402 extension is built with Coinbase, the Ethereum Foundation, MetaMask, and others.
Five roles: who signs, who verifies, who gets paid
The spec defines five roles. One entity may play several, but verification rules stack per role:
| Role | English | What it does | May be agentic? |
|---|---|---|---|
| Shopping Agent | Shopping Agent | Discover products, assemble checkout, execute the purchase | Expected to be agentic |
| Credential Provider | Credential Provider | Issues payment credentials and confirms the agent may use them | Optional |
| Merchant | Merchant | Provides and completes Checkout; checks inventory and price | Optional |
| Merchant Payment Processor | Merchant Payment Processor | Processes payment; confirms the credential is bound to this Checkout | Optional |
| Trusted Surface | Trusted Surface | Shows intent to the user and collects the signature | Must not be agentic |
Hard rule: the Trusted Surface must be a non-agentic, deterministic UI. User signatures must not be “paraphrased” by another LLM. The Shopping Agent may be non-deterministic, so its output is untrusted by default—Mandate signatures and hashes pin it down.
Mandates: Checkout and Payment
v0.2 defines only two Mandate types. After the shopping agent assembles the task, it obtains signatures via the Trusted Surface and hands them to the merchant and the payment path.
Checkout Mandate
Shown to the merchant: the Shopping Agent is authorized to buy this assembled Checkout. The merchant must first issue a merchant-signed Checkout JWT. The closed Checkout Mandate binds to that JWT’s cryptographic hash (checkout_hash) so the agent cannot change the price and reuse an old authorization.
After accept or reject, the merchant must return a Checkout Receipt.
Payment Mandate
Shown to the credential provider, network, and processor: the Shopping Agent is authorized to pay for this Checkout. Binding is the cryptographic hash of the Checkout JWT. The spec requires a non-deterministic signature such as ECDSA—not Ed25519—to avoid rainbow-table attacks.
After accept or reject, the processor must return a signed Payment Receipt to the agent, the credential provider, and optionally the network. In a dispute, Checkout and Payment Mandates plus Receipts are the evidence pack.
Two modes: human present vs autonomous
Verifiers always receive closed Checkout and Payment Mandates. The difference is who signed the closed credentials and how open constraints are checked.
-
1
Human Present (direct)
The user sees the closed cart on a trusted surface and signs it. Verifiers check a user credential or a user signature from a trusted Agent Provider list.
-
2
Human Not Present (autonomous)
The user first signs an open Mandate: amount range, allowed merchants, expiry, plus the agent public key (cnf). When conditions match, the agent signs the closed Mandate with its key. Verifiers must confirm the closed Mandate satisfies the open constraints.
Autonomous mode has two hard rules: the same open Mandate must not authorize another closed checkout until the previous one is rejected; when presenting an open Mandate, disclose only the fields needed to evaluate the closed one—protect user privacy.
Typical cases: buying tickets the instant they go on sale, restocking a missing SKU, booking a flight and hotel inside a trip budget. Constraints are signed first; the closed Mandate is filled in at execution—not an unlimited agent credit card.
JSON APIs: fields, vct, and schema
Day to day, AP2 is JSON. The official SDK keeps protocol objects in code/sdk/python/ap2/schemas/ and generates Pydantic models. Debug them as ordinary JSON objects first, then worry about the SD-JWT wrapper.
Each Mandate declares type and version with vct, for example mandate.payment.1 and mandate.checkout.open.1. Implementations must match the exact string, including the numeric suffix; an incompatible revision becomes .2.
Here is the business payload shape of a closed Payment Mandate from the spec (units depend on the implementation; the sample uses minor currency units):
{
"vct": "mandate.payment.1",
"transaction_id": "NivWhuqfzcvZNapvIEJ2-3tsdQLkiuIcye2g46WVgX8",
"payee": {
"id": "merchant_1",
"name": "Demo Merchant",
"website": "https://demo-merchant.example"
},
"payment_amount": {
"amount": 19900,
"currency": "USD"
},
"payment_instrument": {
"id": "stub",
"type": "card",
"description": "Card ••••4242"
}
}
An open Payment Mandate does not freeze one charge; it writes constraints:
{
"vct": "mandate.payment.open.1",
"cnf": {
"jwk": {
"kty": "EC",
"crv": "P-256",
"x": "QpSyxPQHy38xckypDr54gZ3T42zj9iLtV4koyb5U27c",
"y": "37HLd7JJinxjJIn8J7HijssoeclbfhdW-gUL7feI9lw"
}
},
"exp": 1781203600,
"constraints": [
{
"type": "mandate.payment.allowed_payees",
"allowed": [{ "id": "merchant_1" }]
},
{
"type": "mandate.payment.amount_range",
"currency": "USD",
"min": 10000,
"max": 40000
}
]
}
On the wire they are not bare JSON—they are SD-JWTs: selective disclosure plus key binding. When debugging at the business layer, reconstruct the JSON above from disclosures, then validate fields and constraints.
A JSON Schema should at least lock vct, transaction_id, payee, payment_amount, and the instrument type, so the model cannot drop fields or emit amounts as strings:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://jsonnote.com/schemas/ap2-payment-mandate-debug.json",
"title": "AP2 Closed Payment Mandate (debug)",
"type": "object",
"additionalProperties": false,
"required": ["vct", "transaction_id", "payee", "payment_amount", "payment_instrument"],
"properties": {
"vct": {
"type": "string",
"const": "mandate.payment.1"
},
"transaction_id": {
"type": "string",
"minLength": 16
},
"payee": {
"type": "object",
"required": ["id", "name"],
"properties": {
"id": { "type": "string", "minLength": 1 },
"name": { "type": "string", "minLength": 1 },
"website": { "type": "string", "format": "uri" }
}
},
"payment_amount": {
"type": "object",
"required": ["amount", "currency"],
"properties": {
"amount": { "type": "integer", "minimum": 1 },
"currency": { "type": "string", "pattern": "^[A-Z]{3}$" }
}
},
"payment_instrument": {
"type": "object",
"required": ["id", "type"],
"properties": {
"id": { "type": "string" },
"type": {
"type": "string",
"enum": ["card", "bank_transfer", "stablecoin"]
},
"description": { "type": "string" }
}
}
}
}
In production, follow the canonical schemas in the official repo. The subset above is for local JSONNote checks—it does not replace full spec fields or selective-disclosure annotations.
Worked example: validate a Payment Mandate
Agent-side failures are often broken JSON, not failed signatures:
- The model writes
vctasmandate.payment, dropping the version suffix.1 - Amount is emitted as the string
"19.90"while the schema requires an integer in minor units transaction_iddoes not match the Checkout JWT hash—the binding is broken
The business layer should parse, then schema-validate, and only then verify the SD-JWT and evaluate constraints:
import json
from jsonschema import validate, ValidationError
PAYMENT_MANDATE_SCHEMA = {
"type": "object",
"required": ["vct", "transaction_id", "payee", "payment_amount"],
"properties": {
"vct": {"type": "string", "const": "mandate.payment.1"},
"transaction_id": {"type": "string", "minLength": 16},
"payee": {
"type": "object",
"required": ["id", "name"],
"properties": {
"id": {"type": "string"},
"name": {"type": "string"},
},
},
"payment_amount": {
"type": "object",
"required": ["amount", "currency"],
"properties": {
"amount": {"type": "integer", "minimum": 1},
"currency": {"type": "string", "pattern": "^[A-Z]{3}$"},
},
},
},
"additionalProperties": True,
}
def parse_payment_mandate(raw: str) -> dict:
try:
data = json.loads(raw)
except json.JSONDecodeError as e:
raise ValueError(f"invalid mandate JSON: {e}") from e
try:
validate(instance=data, schema=PAYMENT_MANDATE_SCHEMA)
except ValidationError as e:
raise ValueError(f"mandate schema failed: {e.message}") from e
return data
# 用法:先过结构,再拿 transaction_id 去对 Checkout JWT 的哈希
mandate = parse_payment_mandate(disclosed_payload)
assert mandate["transaction_id"] == checkout_hash
This is the same discipline as validating tool_calls[].function.arguments: first valid JSON, then contract conformance, then side effects. See AI Agents and JSON Schema.
The smart-commerce path looks like this:
-
1
User signs constraints or a closed Mandate in person
The Trusted Surface issues the Mandate. The agent must not “backfill” user intent.
-
2
Merchant issues a Checkout JWT
Price, inventory, and discounts are whatever the merchant signed. The agent cannot edit them and pretend it is the same checkout.
-
3
Closed Mandate binds checkout_hash
Payment Mandate transaction_id must equal that hash.
-
4
Parties verify and return Receipts
Failures return a Receipt JWT with an error. Only success proceeds to capture or a push of funds.
AP2 vs traditional payments / A2A / MCP
| Layer | What it solves | Typical objects | Relation to AP2 |
|---|---|---|---|
| Traditional payment APIs | Charge, refund, tokenized cards | PaymentIntent, capture | AP2 does not replace clearing; a Payment Mandate proves you may call those APIs |
| A2A | Agent-to-agent interoperability | Tasks, messages, capability discovery | AP2 can extend A2A for payments; x402 covers crypto |
| MCP | Agents calling external tools | inputSchema / outputSchema | The tool contract describes parameters; paying still needs an AP2 Mandate |
| UCP and other commerce protocols | Catalog, price changes, checkout session | Checkout object | AP2 is explicitly compatible; it does not browse products |
| JSON Schema | Structural contract | type / required / enum | Mandates and tool parameters both use it; structure first, then signatures |
In one line: MCP lets agents use tools, A2A lets agents collaborate, AP2 lets agents pay inside allowed bounds. Together they are the 2026 smart-commerce stack. How to write MCP tool contracts: AI Agents and JSON Schema; how models emit stable JSON: 2026 Structured Output.
Debug AP2 JSON with JSONNote
The slow part of AP2 is rarely cryptography—it is reconciling payloads. Mandates, Checkout JWT claims, Receipts, and constraint arrays are all JSON. JSONNote runs in the browser; raw transaction data never uploads:
-
1
Check the structure first
Paste the reconstructed Mandate into JSON Formatter to catch missing commas, trailing commas, or a truncated JWT.
-
2
Pin fields with a schema
Put the debug schema and instance into JSON Schema to see missing fields, wrong types, and enum violations immediately.
-
3
Compare two transactions
Open constraints vs a closed Mandate, or two agent assemblies—use JSON Diff to see which fields changed.
-
4
Share a local debug sample
Never put real card numbers or private keys in a link. Use Hash sharing for redacted sample JSON only. Data stays in the URL fragment and is not uploaded.
よくある質問
How does AP2 relate to A2A and MCP?
A2A covers how agents talk to each other; MCP covers how agents call external tools. AP2 only answers who authorized this payment, on what grounds, and how to prove it later. It can extend A2A / MCP; it does not replace them.
Does AP2 only support credit cards?
No. AP2 is payment-instrument agnostic: cards, bank transfers, and stablecoins all work, distinguished by Payment Instrument type. Crypto flows also have the A2A x402 extension.
Does autonomous pay mean the agent can spend freely?
No. In autonomous mode the user first signs an open Mandate on a trusted surface—amount cap, merchant scope, expiry, and the agent public key. The agent may only sign closed Mandates that satisfy those constraints; verifiers must check them.
Why still validate JSON Schema when building AP2?
On the wire a Mandate is an SD-JWT; at the business layer you still see a JSON object. Wrong field names, amount units, or vct versions fail before signature checks even start. Block structural errors with JSON Schema, then do crypto verification.
Do Intent / Cart Mandates from the announcement still count?
The product story is still intent → cart → pay. Implement against the current Checkout / Payment Mandates (open and closed) and official schemas. Do not invent a third set of field names.
まとめ
If agents are going to pay automatically in 2026, what is missing is not another checkout button—it is verifiable authorization.
AP2 pins user intent to a signed JSON contract: Checkout pins what is bought, Payment pins how much and to whom.
Human present: sign the closed Mandate. Human not present: sign constraints first, then let the agent fill the closed Mandate. Validate structure with JSON Schema, then verify the SD-JWT. Debug payloads in JSONNote locally—keep keys and real payment credentials on your machine.