The Agent Payments Protocol (AP2) is an open protocol, first published by Google on 16 September 2025, that lets an AI agent prove a person authorised a specific purchase. It does this with signed mandates: tamper evident credentials that bind the user's approval to an exact checkout and payment, so merchants, card networks and processors can verify intent instead of trusting the agent.
Version 0.2, released on 28 April 2026 alongside Google's donation of AP2 to the FIDO Alliance, reshaped the vocabulary. The original "Intent Mandate" and "Cart Mandate" became open and closed forms of a Checkout Mandate and a Payment Mandate, secured as SD-JWTs. This post goes one level deeper than our posts on x402 and agent payments, A2A versus MCP on the wire, A2A for security teams and sandboxing computer-use agents. Those cover how agents talk; this one covers how they are allowed to spend.
Key takeaways
- What it is. A security and evidence layer for agent commerce, not a payment rail. It works over cards today and has samples for the x402 crypto payment scheme.
- Who publishes it. Google announced AP2 on 16 September 2025. Version 0.2 shipped on 28 April 2026, when the FIDO Alliance took on agent commerce standards starting from AP2 and a Mastercard contribution.
- Two mandates, two states. A Checkout Mandate covers the merchant's exact checkout; a Payment Mandate covers the payment. Each is open (constraints) or closed (bound to one transaction).
- The trust anchor is a Trusted Surface, a deterministic interface, never an LLM, where the user approves mandate content.
- Human present or not changes who signs the closed mandate: the user, or an agent key the user's open mandate named in a
cnfclaim. - The spec assumes prompt injection cannot be prevented, so it caps damage with deterministic checks of hashes, signatures and constraints.
- Real risks remain: wide open mandates, double spend, weak agent key custody, constraint bugs, units mismatches, and liability left to payment networks.
What AP2 is, who published it and what problem it solves
Online payments assume a human clicked "buy" on a page they trust; fraud tools, 3-D Secure and chargeback rules all lean on that. When an agent pays, the AP2 documentation says three questions lack answers:
- Authorisation. What proves the user gave this agent authority for this purchase?
- Authenticity. How can a merchant know the request reflects the user's real intent, not an agent error or hallucination?
- Accountability. If it goes wrong, who answers: user, agent developer, merchant, issuer or processor?
AP2's answer is "verifiable intent, not inferred action": each party gets a signed statement of what the user approved and checks the transaction against it in deterministic code.
Dated timeline
| Date | Event | Source |
|---|---|---|
| 15 May 2025 | W3C Verifiable Credentials Data Model 2.0 becomes a W3C Recommendation | W3C |
| 9 July 2025 | OpenID for Verifiable Presentations 1.0 published as a final specification (used by AP2 v0.2 for user credential delegation) | OpenID Foundation |
| 16 September 2025 | Google Cloud announces AP2 and publishes v0.1.0 on GitHub. The post lists more than 60 collaborating organisations and an A2A x402 extension for crypto payments | Google Cloud blog; GitHub release v0.1.0 |
| 16 September 2025 | v0.1 specification defines three verifiable credentials: Intent Mandate, Cart Mandate and Payment Mandate | AP2 v0.1.0 docs/specification.md |
| November 2025 | SD-JWT published as RFC 9901 (the format AP2 v0.2 uses for mandates) | RFC Editor |
| 28 April 2026 | AP2 v0.2.0 released; Google donates AP2 to the FIDO Alliance; FIDO announces an Agentic Authentication Technical Working Group and agent commerce work in its Payments Technical Working Group | GitHub release v0.2.0; Google blog; FIDO Alliance |
| 23 October 2026 | Current documentation at ap2-protocol.org describes "Agentic Payment Protocol (v0.2)" | ap2-protocol.org |
The repository is licensed under Apache 2.0, and standardisation now continues in FIDO's working groups.
What AP2 is not
AP2 does not move money. The v0.2 specification says it "operates as a security feature within a Commerce Protocol"; catalog and checkout APIs are out of scope, and it is designed to work with the Universal Commerce Protocol (UCP). It is instrument agnostic: cards first, with e-wallets, push payments such as UPI and PIX, and digital currencies on the roadmap. It also does not decide which agent is trustworthy; it is designed "to constrain Agent behaviors without them having to be inherently trustworthy".
Mandates in v0.1 and v0.2: intent, cart, checkout and payment
If you read about AP2 in 2025, you met Intent Mandates and Cart Mandates. If you read the current spec, you meet Checkout and Payment Mandates in open and closed states. They are the same idea, refined.
v0.1: Intent Mandate, Cart Mandate, Payment Mandate
The v0.1 specification described three verifiable credentials:
- Cart Mandate. Generated by the merchant and signed by the user, "typically using a hardware-backed key". It bound payer and payee, a tokenised payment method, a risk payload, the exact products, amount and currency.
- Intent Mandate. Generated by the shopping agent and signed by the user for purchases made while they are away. It carried allowed payment methods, shopping intent (categories or SKUs), a "prompt playback" of the request in natural language, and a time to live.
- Payment Mandate. Shared with the network and issuer to signal agent involvement and whether the human was present.
Google's launch post put it simply: approve a cart and you sign a Cart Mandate; delegate a task and you sign an Intent Mandate with price limits and timing, from which the agent can later generate a Cart Mandate.
v0.2: open and closed Checkout and Payment Mandates
Version 0.2 keeps two mandate types and gives each two states:
| Mandate | vct value (open) | vct value (closed) | Verified by | What it proves |
|---|---|---|---|---|
| Checkout Mandate | mandate.checkout.open.1 | mandate.checkout.1 | Merchant | The agent is authorised to complete this exact merchant-signed checkout |
| Payment Mandate | mandate.payment.open.1 | mandate.payment.1 | Credential Provider, Network, Merchant Payment Processor | The agent is authorised to pay this amount, to this payee, with this instrument, for this checkout |
An open mandate is not yet bound to a transaction. It carries constraints and the agent's public key in a cnf claim, so only that agent can later close it. A closed mandate is bound to one transaction, either signed directly by the user (human present) or signed by the agent's key on top of the user's open mandate (human not present).
Roughly, the v0.1 Intent Mandate became open Checkout and Payment Mandates, and the Cart Mandate became a closed Checkout Mandate. The v0.2 Payment Mandate now carries the approved amount, payee and instrument plus an optional risk_data map. Note that sample READMEs on the main branch still mention IntentMandate and CartMandate in places, so check which vocabulary a file uses.
The checkout mandate fields
A closed Checkout Mandate contains:
vct: the type string,mandate.checkout.1.checkout_jwt: the merchant-signed JWT of the checkout. With UCP, this must be the UCP Checkout object.checkout_hash: the base64url hash of thecheckout_jwtstring, using the SD-JWT's_sd_algor SHA-256 by default.- optional
iatandexptimestamps.
Open Checkout Mandates can use checkout.allowed_merchants and checkout.line_items (the right quantity drawn from each revealed acceptable_items list, no item used twice; the spec suggests evaluating it as a maximum flow problem). The merchant's Checkout Receipt carries status, iss, iat, a reference hash of the closed mandate, and an order_id on success.
The payment mandate fields
A closed Payment Mandate contains:
vct:mandate.payment.1.transaction_id: the base64url hash of thecheckout_jwt, which links this payment to exactly one checkout.payee: the merchant being paid.payment_amount: ISO 4217 currency and an integer in minor units (27999 means 279.99 dollars).payment_instrument, plus optionalpisp,execution_date,risk_data,iatandexp.
Eight constraint types are defined for open Payment Mandates:
Constraint type | What it limits | How it is evaluated |
|---|---|---|
payment.amount_range | Amount within min and max, in one currency | Amount between min and max; currency must match |
payment.budget | Total spend across recurring uses | Requested amount plus all previous closed amounts must not exceed max |
payment.agent_recurrence | How often the open mandate can be reused | Frequency (ON_DEMAND to ANNUALLY) and optional max_occurrences |
payment.allowed_payees | Which merchants can be paid | Payee must be in the revealed list |
payment.allowed_payment_instruments | Which instruments can be used | Instrument must be in the revealed list |
payment.allowed_pisps | Which initiation providers may facilitate | PISP must be in the list |
payment.reference | Ties the payment to an open Checkout Mandate | Hash of that open Checkout Mandate must be in the checkout chain |
payment.execution_date | When payment may execute | not_before and not_after window |
Budget and recurrence are stateful: the verifier must remember what was already spent.
Worked example 1: does this payment pass its constraints?
A user signs an open Payment Mandate with payment.amount_range of USD, min 0, max 20000 (200.00 dollars, as in the spec's own example) and one allowed payee. The agent closes it for trainers at 199.00 dollars: amount 19900. The currency matches and 19900 is within 0 to 20000, so it passes. Had the merchant added 7.50 dollars of shipping, the amount would be 20650, which fails with an error receipt and sends the agent back to the user.
Worked example 2: a budget across recurring purchases
A user asks an agent to top up a coffee subscription. The open Payment Mandate carries payment.agent_recurrence with frequency MONTHLY and max_occurrences 12, and payment.budget with max 1000.00 USD.
| Month | Requested | Previous total | Total if approved | Result |
|---|---|---|---|---|
| 1 | 300.00 | 0.00 | 300.00 | Pass |
| 2 | 450.00 | 300.00 | 750.00 | Pass |
| 3 | 300.00 | 750.00 | 1,050.00 | Fail: budget exceeded |
| 3 (retry) | 250.00 | 750.00 | 1,000.00 | Pass: "less than or equal to max" |
Amounts are added to the total only after approval, so a rejected attempt consumes no budget, and the recurrence check must also confirm month 3 is a new monthly period.
Watch the units. The spec's budget example writes 1000.00 and its payment.amount_range example writes 100.50, while the schema says range limits are integers in minor units and payment_amount is always minor units. If one service reads 1000.00 as dollars and another as cents, a constraint is a hundred times looser than intended. Pin the convention in integration tests.
How verifiable credentials bind the user's approval to a purchase
VDCs, SD-JWT and where W3C credentials fit
AP2 uses the term verifiable digital credentials (VDCs): "tamper-evident, cryptographically signed digital objects". The v0.2 specification says AP2 "specifies the use of SD-JWTs" for securing mandates, and that other VDC formats such as ISO mobile documents could fill the same role.
"Verifiable credentials" often suggests the W3C Verifiable Credentials Data Model 2.0, a W3C Recommendation since 15 May 2025, with its issuer, holder and verifier roles and JSON-LD data model. AP2 v0.2 uses the same three party idea but the IETF format family:
- SD-JWT (RFC 9901, November 2025). A JWT whose claims can be hidden behind salted hashes and revealed one at a time through "disclosures". AP2 uses this so an agent can show a merchant only the constraint entries that apply to this checkout.
- SD-JWT VC (IETF draft, revision 19 at the time of writing). Adds the
vcttype claim that AP2 uses to name each mandate type and version. - Key binding and
cnf(RFC 7800). Acnfclaim names a public key; only the holder of the matching private key can produce a valid key binding JWT. AP2 uses this to name the agent key that may close an open mandate. - Delegate SD-JWT (individual Internet-Draft
draft-gco-oauth-delegate-sd-jwt-00). Chains SD-JWTs so each hop is signed by the key named in the previous hop'scnf. The IETF datatracker lists this draft as no longer active, so expect the chaining format to change as it moves through FIDO.
The chain, hop by hop
The AP2 Python SDK documentation describes the wire format as SD-JWTs joined by ~~:
<root SD-JWT>~<disclosures>~~<intermediate KB-SD-JWT>~<disclosures>~~<closed KB-SD-JWT>~<disclosures>~
- The root, issued by the bank or agent provider, contains
cnfnaming the next key. - Intermediate hops (
typofkb+sd-jwt+kb) are signed by the previouscnfkey and carry their owncnf. - The closed leaf (
typofkb+sd-jwt) carries the final mandate, nocnf, plussd_hash,aud,nonceandiat.
The verifier trusts only the root key; each other signature is checked with the key the previous hop named. sd_hash binds the leaf to the chain, and the receipt's reference, the SHA-256 of the leaf, binds the receipt to the authorised mandate.
Two ways to establish trust in the user's signature
The Agent Authorization Framework in v0.2 defines two delegation models:
- User Credential. An issuer such as a bank or wallet gives a credential to a Trusted Surface the user controls. It is presented with OpenID4VP, with the mandate content in
transaction_data(typeofdelegate), so the user's key binding signature covers the mandate. One credential can then delegate to many agents. - Trusted Agent Provider. The agent's operator is trusted directly: its deterministic Trusted Surface gets consent and a backend key signs. The provider "MUST ensure that the Agent is not able to access the Agent Provider signing key". Simpler, but every verifier must trust every provider.
How AP2 relates to A2A, MCP, UCP and HTTP 402 payments
AP2 is described on its home page as "available as an extension for the open-source Agent2Agent (A2A) protocol and Universal Commerce Protocol", and its principles call it an open extension for A2A and MCP.
- A2A. Extensions are identified by URI in the agent card, can be marked
required, and are activated with anA2A-ExtensionsHTTP header. The sample merchant agent card declareshttps://github.com/google-agentic-commerce/ap2/v1withrequired: trueon A2A protocol version 0.3.0. Mandates travel in message data parts. - MCP. The repository includes MCP server variants of the merchant and credentials provider roles, passing mandates as tool arguments and results. MCP itself defines no payment authorisation.
- UCP. UCP calls AP2 the "trust layer": the business returns a
checkoutSignature(a detached JWT over the checkout) and the platform supplies payment authorisations tied to it. - HTTP 402 and x402. RFC 9110 says status 402 "is reserved for future use". x402 uses it: the server answers 402 with a
PAYMENT-REQUIREDheader, the client retries with a signed payload inPAYMENT-SIGNATURE, and a facilitator offers/verifyand/settle. In the EVMexactscheme the payload is an EIP-3009 authorisation with a 32 byte nonce and avalidBeforetime. AP2 ships x402 samples for both modes: x402 moves value, AP2 proves authorisation.
Comparison: AP2, HTTP 402 style payments and card network agent programs
Each row is described from that project's own documentation.
| AP2 (v0.2) | x402 (v2) | Card network agent programs (example: Visa Trusted Agent Protocol) | |
|---|---|---|---|
| Layer | Authorisation and evidence layer inside a commerce protocol | Payment request and settlement over HTTP, MCP or A2A | Agent identification and request signing toward merchants |
| What is signed | User or agent signed SD-JWT mandates over a merchant-signed checkout and a payment | Payer-signed payment authorisation (for example EIP-3009) | HTTP message signature (RFC 9421) by the agent over request attributes |
| Proof of user authorisation | Closed mandate signed by the user, or by an agent key the user's open mandate named | Payer signature over a payment; user intent is out of scope | Signature bound to the merchant domain and the operation (browsing or payment) |
| Trust root | Credential issuer or trusted agent provider keys | Payer's wallet key; facilitator for verification and settlement | The network's register of approved agents and their public keys |
| Replay defence | sd_hash, nonce, aud, receipts, and a rule against presenting a new open mandate without a rejection receipt | 32 byte nonce, validity window, on-chain nonce reuse checks | Timestamps, session identifier and key identifier in the signature |
| Dispute evidence | Checkout and Payment Mandates plus receipts, hash linked | On-chain settlement record | Existing card dispute processes |
| Status | Open source, donated to FIDO Alliance (April 2026) | Open source, version 2 | Published developer specification and sample code |
The FIDO announcement adds that Mastercard contributed its "Verifiable Intent" framework, co-developed with Google to work with AP2. These layers stack rather than compete: a network signature identifies the agent, AP2 proves what the user approved, and a rail moves the money.
Roles in an AP2 flow and who holds which keys
The v0.2 specification defines five roles. One company can play several, and every role "MAY always delegate" its responsibilities, for example a merchant asking its processor to verify mandates.
| Role | Agentic? | Responsibilities | Keys it holds or checks |
|---|---|---|---|
| Shopping Agent (SA) | Expected to be agentic | Discovery, building the checkout, assembling mandate content, presenting mandates, tracking receipts | Holds the agent key named in open mandates' cnf; signs closed mandates in autonomous mode |
| Trusted Surface (TS) | MUST be non-agentic | Shows mandate content, gets informed consent, produces user-signed mandates | Holds or reaches the user credential key or the agent provider's signing key |
| Merchant (M) | May be either | Signs the checkout JWT, verifies the Checkout Mandate, returns a signed Checkout Receipt | Merchant checkout signing key; verifies user, provider and agent keys |
| Credential Provider (CP) | May be either | Supplies payment instruments, verifies the Payment Mandate, releases a scoped payment credential or token | Verifies mandate chain; holds or obtains tokens |
| Merchant Payment Processor (MPP) | May be either | Verifies the payment credential is scoped to this checkout, processes payment, signs the Payment Receipt | Receipt signing key; verifies the Payment Mandate |
The overview adds the network and issuer, which may issue agent specific tokens and see "AI agent presence signals". The key rule: when a role is agentic, "the Agent itself is a potential attacker", so validation "MUST happen in deterministic code". The model proposes; plain code checks.
Human present and human not present flows
AP2 calls these the direct and autonomous modes. In both, verifiers receive a closed Checkout Mandate and a closed Payment Mandate. The difference is who signed the closed mandates and how verifiers decide to trust that signature.
Human present (direct)
- The agent and merchant build a checkout; the merchant returns a signed checkout JWT.
- The agent passes closed Checkout and Payment Mandate content to the Trusted Surface.
- The user sees the exact checkout and payment there and approves, for example with a biometric.
- The Credential Provider (and possibly the network) verifies the Payment Mandate and returns a payment credential.
- The merchant receives the credential and Checkout Mandate, checks
checkout_hashagainst the checkout it signed, and starts payment. - Any party may challenge with existing mechanisms such as 3-D Secure on a trusted surface.
- The merchant returns a Checkout Receipt; the processor returns a Payment Receipt.
Human not present (autonomous)
- The agent repeats back what it will buy; the user approves open Checkout and Payment Mandates on the Trusted Surface with in-session authentication.
- The open mandates "MUST include the agent's public key as a
cnfclaim", withexpas short as the task allows. - When conditions are met (a price drop, a ticket release), the agent signs closed mandates with its key and presents them with the user-signed open mandates, disclosing only what this checkout needs.
- Verifiers check signatures,
sd_hashchaining and every constraint; unknown constraints "MUST be treated as failing". - The agent "MUST NOT present any subsequent open Payment or Checkout Mandates without receiving a rejection receipt from the previous one".
A merchant unsure it can meet the request, for example when no SKU is named, can force the user back to confirm.
| Human present | Human not present | |
|---|---|---|
| Who signs closed mandates | The user, through the Trusted Surface | The agent key named in the open mandate |
| What the user approves | The exact checkout and payment | Constraints: merchants, items, amounts, dates, recurrence |
| Main residual risk | User approves the wrong thing on a misleading screen | Constraints too loose; agent key misuse; double spend |
| Typical extra controls | Step-up challenge on a trusted surface | Short exp, tight constraints, deterministic signer, notifications |
| Dispute evidence | User-signed closed mandates and receipts | User-signed open mandates, agent-signed closed mandates and receipts |
Security and fraud risks
AP2's security considerations open with an unusually candid line: "AP2 assumes that preventing prompt injection attacks is infeasible." It therefore puts every LLM and agent inside the threat model. That is the right starting point. It also means the protocol's guarantees are exactly as strong as the deterministic code and key custody around the model.
Prompt injection leading to purchases
OWASP's LLM01 describes indirect prompt injection as instructions hidden in external content, such as product pages or reviews, that change a model's behaviour. A shopping agent reads a lot of external content. The AP2 spec lists "Manipulated Discovery" as a threat and says the merchant's signature guarantees the integrity of the offer, while "constraint enforcement during closed Mandate verification ensures that the worst-case financial and logical impacts are strictly bounded."
AP2 does not stop an injected agent from choosing a worse product; it bounds the damage to what the open mandate allows. "Any merchant, up to 1,000 dollars" means a 1,000 dollar bound anywhere. With the human present, injection can still shape the recommendation, so the Trusted Surface must render the merchant-signed checkout, not the agent's summary.
Mandate scope creep
OWASP's LLM06, Excessive Agency, splits the problem into excessive functionality, excessive permissions and excessive autonomy. Open mandates are permissions. Common ways they grow too wide:
- No
checkout.allowed_merchantsorpayment.allowed_payeesconstraint, so any merchant qualifies. - Long
expvalues, even though the spec recommends the smallest workable value. payment.agent_recurrencewithON_DEMANDfrequency and nomax_occurrences, paired with a large budget.- Broad
acceptable_itemslists that turn "these trainers" into "anything in footwear".
The implementation notes ask agents to let users manage active mandates, limit their duration and send notifications.
Replay and double spend
The spec's threat list covers several replay shapes:
- Stolen Payment Mandate reused with another checkout. Mitigated because the closed Payment Mandate's
transaction_idis the hash of one checkout JWT, and open ones carry apayment.referenceconstraint. - Open mandate reused to approve a different closed mandate. Mitigated by
sd_hashbinding and by the agent key incnf. - Closed Checkout Mandate replayed against another session. The merchant must check
checkout_hashagainst the latest checkout JWT. - Double spend. A prompt-injected agent tries to approve several valid checkouts from one open mandate. The spec says the non-deterministic part of the agent must not sign overlapping closed mandates without rejection receipts, and that those receipts "MUST be integrity protected from the Shopping Agent's LLM". Verifiers "MAY" reject overlapping mandates or invalidate earlier tokens.
Rejection by verifiers is only a "MAY", and a verifier that does not track presentations cannot detect double spend alone. If several providers each see a slice of the spending, none sees the total.
One cryptographic detail: the checkout JWT must use a randomised signature such as ECDSA, not a deterministic one such as Ed25519, or include a salt, so a checkout_hash cannot be matched against guessed checkouts. SD-JWT disclosure salts need enough entropy too, per RFC 9901.
Agent impersonation and key custody
In autonomous mode, whoever holds the agent private key can close open mandates within their constraints. If that key sits in the same process as the model, or in an environment variable the model's tools can read, a prompt injection that reaches a code execution tool can sign. The implementation notes suggest a pattern: deterministic code, reached through tool calling, "verifies the closed Mandate being created before being signed". In practice that means a separate signing service with its own policy, an HSM or platform keystore, and no model access to raw key material.
In the trusted agent provider model, the provider's key can mint mandates for every user, which makes it a prime target. Impersonating an agent toward merchants is left to the commerce protocol, where network agent signatures and UCP identification apply.
Dispute and liability gaps
AP2 produces strong evidence: the spec describes how to verify Checkout and Payment Mandates and their receipts at dispute time so they show "what the user, and each role saw". The v0.1 specification even included a table of scenarios, from first-party misuse to merchant non-fulfilment, with the evidence each mandate provides. But it was explicit that "every payment network will define its own liability contracts" and the table was "only a helpful guide". Version 0.2 says dispute details, retention and retrieval are outside its scope.
So the gaps are partly commercial: who retains mandates and receipts, for how long and in what form (the notes say store compact SD-JWTs with disclosures); what happens when the agent stayed within vague constraints but the user says "that is not what I meant"; and how agent signals affect chargeback rights, which each network decides.
Implementation risks that come from the spec itself
- Unknown constraints must fail closed. Skipping unrecognised types turns every new constraint into a bypass.
- Schema strings differ. The checkout schema table says
vct"MUST be 'mandate.checkout'", while the versioning rules require the exact stringmandate.checkout.1. Follow the versioning rule. - Moving drafts. Chaining rests on an expired individual draft and SD-JWT VC is still a draft. Pin versions and test for format changes.
- Hash canonicalisation. Hash the exact base64url compact form. Re-serialising JSON first breaks verification or, worse, binds the wrong data.
Step by step: run the reference sample and inspect each signed artefact
This uses the official human present card sample: a stub card, a mock OTP (123) and local agents. No real money moves. You need a Gemini API key because the samples use Google's Agent Development Kit, though AP2 requires neither. Use a disposable VM and read the run script first.
1. Get the code at a known version
git clone https://github.com/google-agentic-commerce/AP2.git
cd AP2
git checkout v0.2.0 # or the commit you reviewed
git log -1 --format='%H %cd'
2. Read the run script before running it
less code/samples/python/scenarios/a2a/human-present/cards/run.sh
At the time of writing the script creates a virtual environment with uv, syncs the samples package, clears a .logs directory and a .temp-db directory used for keys and state, exports AGENT_PROVIDER_PUBLIC_KEY_PATH pointing at .temp-db/agent_provider_signing_key.pub, and starts the merchant agent on port 8001, the credentials provider on 8002 and the card processor on 8003, each logging to .logs/. Note where the agent provider signing key lives: on disk in a temp directory that every sample agent can read. That is fine for a demo and exactly what you must not copy into production.
3. Inventory the dependencies
find . -name pyproject.toml -not -path './.venv/*' | xargs grep -n -A30 'dependencies'
The JOSE and SD-JWT libraries, cryptography and the A2A SDK decide whether a forged mandate is accepted.
4. Set the key and start the sample
export GOOGLE_API_KEY='your_key' # or use a .env file at the repo root
bash code/samples/python/scenarios/a2a/human-present/cards/run.sh
Open the ADK web UI the README points to, choose shopping_agent, and ask for something specific, adding that you want verbose output: "I want to buy a coffee maker. Be verbose and show all data payloads." The README notes that a follow-up reminder is sometimes needed before the agent prints JSON.
The flow runs through merchant-signed carts, linking the credential provider, choosing a payment method, signing the payment mandate, the mock OTP and the receipt.
5. Read the wire log
ls .logs/
grep -n 'Mandate' .logs/watch.log | head -50
watch.log records each request's method, URL and JSON bodies, A2A message parts and any mandate objects: what actually crossed between agents, not what the shopping agent told you.
6. Decode an SD-JWT chain without trusting it
Copy a compact token from the log into a file and decode it. Decoding is not verification; it only shows what the token claims.
# decode_chain.py: print headers, payloads and disclosures of an AP2 SD-JWT chain
import base64, json, sys
def b64d(s):
return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
token = open(sys.argv[1]).read().strip()
for hop_no, hop in enumerate(token.split("~~")):
parts = [p for p in hop.split("~") if p]
jwt, disclosures = parts[0], parts[1:]
header, payload, _sig = jwt.split(".")
print(f"hop {hop_no} header:", json.loads(b64d(header)))
print(f"hop {hop_no} payload:", json.dumps(json.loads(b64d(payload)), indent=2))
for d in disclosures:
if d.count(".") == 2: # a trailing key binding JWT
print(" key binding JWT payload:", json.loads(b64d(d.split(".")[1])))
else:
print(" disclosure:", json.loads(b64d(d)))
python3 decode_chain.py mandate.txt
What to look for in each artefact:
| Artefact | Check |
|---|---|
| Merchant checkout JWT | Merchant identity, line items, total, currency; signed by the merchant key |
| Open Checkout Mandate | vct of mandate.checkout.open.1; cnf with the agent key; exp; constraints with hidden items |
| Closed Checkout Mandate | typ of kb+sd-jwt; aud, nonce, sd_hash; checkout_hash |
| Open Payment Mandate | vct of mandate.payment.open.1; amount range, payees, payment.reference |
| Closed Payment Mandate | transaction_id equal to the checkout hash; payment_amount in minor units; payee; instrument |
| Checkout and Payment Receipts | status, iss, reference equal to the hash of the closed mandate |
7. Recompute the checkout hash yourself
Take the checkout_jwt string exactly as it appears in the closed Checkout Mandate and hash it:
printf '%s' "$CHECKOUT_JWT" \
| openssl dgst -sha256 -binary \
| openssl base64 -A | tr '+/' '-_' | tr -d '='
The output must equal the Checkout Mandate's checkout_hash and the Payment Mandate's transaction_id. A mismatch usually means you copied re-serialised JSON instead of the compact string.
8. Build and verify a mandate chain offline with the SDK
The SDK README has an offline example: create issuer and agent keys, issue an open Payment Mandate with an amount range, an allowed payee and the agent key in cnf, present a closed mandate on top, then verify with expected_aud and expected_nonce and check constraints with PaymentMandateChain.parse(...).verify(...). There is no PyPI package yet:
uv venv && source .venv/bin/activate
uv pip install "git+https://github.com/google-agentic-commerce/AP2.git@v0.2.0"
Run the example as published, then write the negative tests where implementations fail:
- Change the closed mandate's amount to exceed the open mandate's
maxand confirmverifyreports a violation. - Present the chain with the wrong
expected_audorexpected_nonceand confirm it is rejected. - Sign the closed mandate with a key other than the one in
cnfand confirm it is rejected. - Add a constraint with an unknown
typeand confirm evaluation fails, as the spec requires.
9. Clean up
pkill -f 'roles\.' || true
rm -rf .temp-db .logs
Check the process list before pkill, and rotate the demo API key.
Common mistakes
- Treating the agent's summary as consent. The user must approve the merchant-signed checkout on a Trusted Surface.
- Letting the model hold the agent key. Any tool that reads files or environment variables can then sign.
- Open mandates without payee limits. "Up to 500 dollars" with no payee list means anywhere.
- Ignoring unknown constraint types. The spec says they must fail. Skipping them silently turns every future constraint into a no-op.
- Mixing units. Treating
100.50as dollars in one service and cents in another. - Re-serialising JSON before hashing. Hash the exact compact string you received.
- No double spend ledger. Each verifier sees only its slice; without a shared record, one open mandate can fund several checkouts.
- Copying sample key handling into production. The sample keeps a signing key in a temp directory readable by every agent.
- Assuming AP2 settles liability. It produces evidence. Networks and contracts decide who pays.
FAQ
What is the Agent Payments Protocol (AP2)?
An open protocol, first published by Google on 16 September 2025 and donated to the FIDO Alliance on 28 April 2026, that lets AI agents prove a user authorised a purchase. It uses signed mandates, secured as SD-JWT credentials, that verifiers check against the actual checkout and payment.
What is the difference between an intent mandate and a cart mandate?
In AP2 v0.1, an Intent Mandate captured the user's goals and limits (and a playback of their request) for purchases made while they were away, and a Cart Mandate captured the user's approval of an exact cart and price. In v0.2 these became open and closed forms of Checkout and Payment Mandates.
Does AP2 use W3C Verifiable Credentials?
Not in its current form. AP2 v0.2 specifies SD-JWT (RFC 9901) and SD-JWT VC for mandates, uses OpenID4VP for presenting user credentials, and says other formats such as ISO mobile documents could fill the same role. The issuer, holder and verifier model is similar to the W3C data model, but the encoding is different.
How is AP2 different from x402?
x402 uses HTTP 402 to request payment and carries a signed payment authorisation that a facilitator verifies and settles. AP2 proves what the user authorised. AP2's samples use x402 as a payment method, so they work together.
Can prompt injection make an AP2 agent buy something?
It can make an agent choose badly; the spec assumes injection cannot be prevented. AP2 limits the impact, because verifiers reject closed mandates that break the open mandate's constraints. Tight constraints are the defence.
Who is liable if an AI agent makes a wrong purchase under AP2?
AP2 does not decide that. It supplies signed mandates and receipts as evidence. The v0.1 spec said each payment network defines its own liability rules, and v0.2 leaves dispute handling outside its scope.
What does human not present mean in AP2?
The user approves open mandates with constraints in advance, and the agent later signs the closed mandates for a specific checkout with a key the user's open mandate named. Verifiers check the whole chain and every constraint.
How do I try AP2 without spending money?
Run a sample scenario from the official repository at a release tag, such as the human present card flow, which uses a stub card and a mock OTP on local agents.
Is AP2 a finished standard?
No. The current version is 0.2, and the FIDO Alliance's working groups are developing agent commerce specifications from it. Parts of the underlying formats are still Internet-Drafts, so expect changes.
Where Safeguard fits
Safeguard does not verify mandates, sign payments, detect prompt injection or judge agents, and it is not a fraud tool. The overlap is the software that does those jobs: the AP2 SDK, JOSE and SD-JWT libraries, cryptography, the A2A SDK, an agent framework and container base images. A flaw in the library that checks a signature is a flaw in your payment authorisation. Safeguard can scan those repositories and images (safeguard scan --dir ., safeguard scan --image ap2-merchant), match components against vulnerability databases, apply reachability analysis to rank what your code actually calls, show which projects carry a given library version, and gate builds with policies. The Safeguard CLI's assistant can also edit code and run commands with your approval, which suits upgrading a pinned SDK and rerunning the negative tests above.
Software supply chain hygiene matters here because mandate verification lives in a few small libraries that every role depends on, and the reference implementation is still young and changing between versions. The fit is indirect: it covers the code you build and ship around AP2, not the protocol's design or anyone's payment decisions.
Fix it without waiting for upstream
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
None of these demos shows an AP2 payment; they show Safeguard's agent surfaces handling tool access and approvals. You can download Safeguard and follow the CLI docs to try them.
This demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. It mirrors the principle behind open mandates: give an agent a short, named list of what it may do, decided by a person, rather than broad access.
Click through it at your own pace, or open it full screen.
This is a real CLI session: asked to fix a lodash CVE, the CLI reads the finding and advisory, asks before each command, edits package.json, runs npm install and npm test with approval, and pushes nothing. The same flow applies when a JOSE or SD-JWT library under your AP2 verifier needs an upgrade: change the pin, rerun the negative mandate tests, and approve each step.
Click through it at your own pace, or open it full screen.
This demo sets up the runner on your own machine, approves it with its device code, and scans from the terminal. It suits the disposable machine you use for the AP2 samples: scan the cloned repository and its virtual environment locally before you run anything.
Click through it at your own pace, or open it full screen.
Quick check
An open Payment Mandate has an amount range of 0 to 20000 USD minor units and allows one payee. The agent closes it for a checkout totalling 203.99 dollars at that payee. Should the credential provider release a payment credential?
No. 203.99 dollars is 20399 minor units, which is above the maximum of 20000 (200.00 dollars). The credential provider must reject the Payment Mandate and return a Payment Receipt with an error, and the agent has to go back to the user or find a cheaper checkout.
In a human not present flow, a prompt-injected agent tries to use one open mandate to approve two different checkouts at once. Which AP2 rules stop it, and what must you build to make them work?
The spec says the agent must not present a new open mandate, or sign overlapping closed mandates, without a rejection receipt for the previous one, and that receipts must be integrity protected from the LLM. You need a deterministic signer outside the model that enforces this, plus verifiers that track presentations and budgets, because rejecting overlapping mandates is only a "MAY" for them.
Sources
- AP2 documentation home (ap2-protocol.org)
- AP2 specification: Agentic Payment Protocol v0.2
- AP2: Agent Authorization Framework
- AP2: Checkout Mandate
- AP2: Payment Mandate
- AP2: Security and Privacy Considerations
- AP2: Implementation Considerations
- AP2: Executive Summary and overview
- AP2 GitHub repository (google-agentic-commerce/AP2)
- AP2 GitHub releases (v0.1.0 and v0.2.0)
- AP2 v0.1.0 specification
- AP2 sample: Human Present purchases with a card
- AP2 Python SDK README
- AP2 sample merchant agent card
- Google Cloud: Announcing Agent Payments Protocol (AP2), 16 September 2025
- Google: Donating AP2 to the FIDO Alliance, 28 April 2026
- FIDO Alliance: FIDO Alliance to Develop Standards for Trusted AI Agent Interactions, 28 April 2026
- Universal Commerce Protocol: UCP and AP2
- A2A Protocol specification
- A2A Protocol: Extensions
- Model Context Protocol specification
- x402 protocol specification v2
- x402 project site
- Visa developer: Trusted Agent Protocol
- Visa Trusted Agent Protocol repository
- W3C: Verifiable Credentials Data Model v2.0, W3C Recommendation 15 May 2025
- RFC 9901: Selective Disclosure for JSON Web Tokens (SD-JWT)
- IETF draft: SD-JWT-based Verifiable Digital Credentials (SD-JWT VC)
- IETF individual draft: Delegate SD-JWT
- RFC 7800: Proof-of-Possession Key Semantics for JWTs
- RFC 9110: HTTP Semantics, section 15.5.3 (402 Payment Required)
- OpenID for Verifiable Presentations 1.0
- OWASP GenAI Security Project: LLM01:2025 Prompt Injection
- OWASP GenAI Security Project: LLM06:2025 Excessive Agency
- OWASP Top 10 for Agentic Applications for 2026, 9 December 2025
Last reviewed: 23 October 2026. AP2 is at version 0.2 and is being developed further in FIDO Alliance working groups; check the linked specification and release notes for the current mandate formats before you build.