Skip to content
guide

AP2 agent payments protocol: a developer guide with 60+ partners

| 9 min read
Credit cards and payment terminal representing agent-led commerce
Photo by CardMapr.nl on Unsplash
Credit cards and payment terminal representing agent-led commerce infrastructure
Agent-led purchases need signed Mandates before card networks will honor them; AP2 is the spec that makes that chain auditable. Photo by CardMapr.nl on Unsplash

Google shipped the Agent Payments Protocol (AP2) with 60+ partners including Mastercard, Visa (via Worldpay), American Express, PayPal, Coinbase, Salesforce, ServiceNow, Adyen, and JCB. The spec answers one question: when an AI agent pays for something on your behalf, who signed what, and how does a card network resolve a chargeback three weeks later?

Stripe Checkout and Apple Pay assume a human clicked a button. Agent commerce breaks that assumption. If your shopping agent books a hotel at 3am while you sleep and the room has bedbugs, the dispute process has to reconstruct whether you authorized that purchase or gave the agent a blank check. AP2 answers with signed Mandates: small, structured objects that bind an agent to a user intent with cryptographic proof.

Here is the six-part breakdown developers need to wire AP2 into an agent, plus the crypto path via the A2A x402 extension that is already live in production.

Part 1: Mandates are the atomic unit

A Mandate is a JSON object the user's identity provider signs when the human authorizes a class of purchases. Every downstream payment references the Mandate by ID; merchants verify the signature, check constraints, and settle. Here is what one looks like on the wire:

{
  "mandate_id": "mnd_01HX9Y2K3F4G5H6J",
  "user_id": "usr_bob_42",
  "agent_id": "agent_shopping_v3",
  "intent": {
    "category": "footwear",
    "constraints": {
      "max_amount": 200.00,
      "currency": "USD",
      "size": "11",
      "brand_allowlist": ["hoka", "brooks", "new-balance"]
    }
  },
  "valid_until": "2026-04-22T00:00:00Z",
  "issued_at": "2026-04-15T14:00:00Z",
  "signature": "ed25519:0xMEUCIQD..."
}

Four fields carry weight. intent is the plain-English thing the user asked for. constraints is the machine-readable envelope: max amount, currency, brand allowlist, category. valid_until caps how long the agent can act on the Mandate. signature is an Ed25519 or ECDSA proof that the issuer (Google Pay, Auth0 for Agents, a bank's identity service) actually signed the payload.

Constraints are where product work happens. A Mandate with max_amount: 10000 and no brand allowlist is an agent-shaped blank check. A Mandate with max_amount: 200, brand_allowlist: [...], category: "footwear" is a scoped authorization a merchant can reason about. Treat Mandate constraint design the same way you treat OAuth scope design: the tightest set the product allows.

Part 2: AP2 runs as an A2A extension

AP2 does not reinvent transport. It rides on Agent2Agent, the open JSON-RPC protocol Google published in 2025 for agent-to-agent communication. An A2A task with payment intent carries the Mandate inside the extensions.ap2 field of the envelope:

{
  "jsonrpc": "2.0",
  "method": "agent.task.create",
  "id": "task_42",
  "params": {
    "recipient": "merchant-shoes.com/agent",
    "message": {
      "role": "user",
      "parts": [{ "type": "text", "text": "Buy size 11 Hoka Clifton 9" }]
    },
    "extensions": {
      "ap2": {
        "mandate_id": "mnd_01HX9Y2K3F4G5H6J",
        "settlement": "card",
        "presentment_amount": { "value": 145.00, "currency": "USD" }
      }
    }
  }
}

The recipient agent (here, the merchant's shopping agent) reads the A2A task, sees the ap2 extension, verifies the Mandate through its PSP, and either accepts the task or returns a signed rejection. For developers who already speak A2A, adding AP2 is one extension key in the task envelope plus a verification call; it is not a parallel stack.

Part 3: x402 handles crypto payments today

Card rails are still negotiating chargeback liability. Crypto moved faster. The A2A x402 extension (co-designed with Coinbase, the Ethereum Foundation, and MetaMask) is production-ready and reuses HTTP 402 Payment Required to negotiate settlement:

# 1. Agent requests a resource; merchant returns 402 with payment requirements
curl -X POST https://merchant-api.example.com/v1/cart/checkout \
  -H "Authorization: Mandate mnd_01HX9Y2K3F4G5H6J"

HTTP/1.1 402 Payment Required
X-Payment-Accept: x402
X-Payment-Amount: 145.00
X-Payment-Currency: USDC
X-Payment-Recipient: 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7
X-Payment-Nonce: 0x9a3f...

# 2. Agent signs a USDC transfer tying the nonce to the Mandate
# 3. Agent retries with the signed transaction as X-Payment-Receipt
# 4. Merchant verifies on-chain, returns 200 with the order

The flow is four steps: request, 402 with payment requirements, signed transfer tying the nonce to the Mandate, retry with the receipt. Merchants verify the on-chain transfer before releasing the resource. Settlement is USDC on Base or Optimism today; stablecoin rails keep the UX close to card purchases without floating-currency drift between signing and confirmation.

The x402 status code was in the original HTTP/1.1 spec in 1997 and sat unused for 29 years. Coinbase revived it in 2024 for micropayments; AP2 adopted it as the agent payment handshake. This is why your old client libraries already know how to parse 402 responses.

Part 4: Request a Mandate from Python

Here is what the agent side looks like in Python using the reference AP2 SDK. The agent asks the user's identity provider for a Mandate, receives a signed object, and threads it through an A2A task to the merchant:

from ap2 import MandateClient, AgentIdentity
from ap2.extensions import a2a

# Load the signing key; in production use a KMS, never a file
agent = AgentIdentity.from_kms("projects/acme/keys/shopping-agent")
client = MandateClient(agent=agent)

# Ask the user once; reuse the Mandate across many merchants
mandate = client.request_mandate(
    user_id="usr_bob_42",
    intent={
        "category": "footwear",
        "constraints": {
            "max_amount": 200.00,
            "currency": "USD",
            "size": "11",
            "brand_allowlist": ["hoka", "brooks", "new-balance"],
        },
    },
    valid_for_hours=168,
)

# Dispatch an A2A task that carries the Mandate via the ap2 extension
result = a2a.send(
    recipient="merchant-shoes.com/agent",
    message="Find and buy size 11 Hoka Clifton 9 under $200",
    extensions={"ap2": {"mandate_id": mandate.id, "settlement": "card"}},
)

print(result.order_id, result.receipt_url)

Two details matter. The signing key lives in a KMS (Google Cloud KMS, AWS KMS, HashiCorp Vault) so an exfiltrated agent binary cannot forge identity. The Mandate is reusable across merchants during valid_until; the user authorizes once, the agent shops many places. That reuse is the whole UX reason AP2 exists; without it, every merchant re-prompts the user and the agent experience collapses.

Part 5: Verify a Mandate from your merchant backend

The merchant side is where most of the fraud surface sits. Verification has to cover four things: signature validity, issuer trust, constraint match, and expiry. Cut corners on any of them and you ship a hole:

// Merchant side: verify the Mandate before charging
import { verifyMandate } from "@ap2/sdk";

async function handlePayment(req, res) {
  const { mandate_id, amount, currency } = req.body;

  const mandate = await verifyMandate(mandate_id, {
    issuerAllowlist: ["google-pay", "apple-pay", "auth0-agents"],
    clockSkewSeconds: 30,
  });

  if (!mandate.valid) return res.status(402).json({ error: mandate.reason });

  // Check the Mandate constraints against the proposed charge
  if (amount > mandate.intent.constraints.max_amount) {
    return res.status(402).json({ error: "amount exceeds mandate cap" });
  }
  if (currency !== mandate.intent.constraints.currency) {
    return res.status(402).json({ error: "currency mismatch" });
  }

  // Settle the payment through your PSP; store the chain for dispute replay
  const charge = await stripe.paymentIntents.create({
    amount: Math.round(amount * 100),
    currency,
    metadata: {
      ap2_mandate_id: mandate.id,
      ap2_agent_id: mandate.agent_id,
      ap2_user_id: mandate.user_id,
    },
  });

  return res.json({ order_id: charge.id });
}

Three patterns worth copying. Keep an issuerAllowlist; do not accept Mandates from any issuer that shows up. Enforce clockSkewSeconds; agents on flaky networks send timestamps 15 seconds in the future routinely. Store the Mandate ID, agent ID, and user ID in your PSP metadata so a chargeback dispute three weeks from now can replay the chain without a support engineer diving into logs.

Part 6: Build a multi-currency cart around the Mandate

Agent buyers cross currencies constantly. A user in Tokyo hands an agent a USD Mandate; the agent finds a deal at a European merchant priced in EUR. The merchant needs to know what USD cap converts to in EUR before accepting the Mandate. A currency conversion call keeps the math honest:

curl -X POST https://api.botoi.com/v1/currency/convert \
  -H "Content-Type: application/json" \
  -d '{"from": "USD", "to": "EUR", "amount": 145.00}'
{
  "data": {
    "from": "USD",
    "to": "EUR",
    "amount": 145.00,
    "result": 133.40,
    "rate": 0.92,
    "rate_date": "2026-04-15"
  }
}

Cache the rate for the lifetime of the Mandate. If the rate moves more than a configured band (typical: 2%), ask the user to re-sign. Settling against a stale rate is how agents produce support tickets.

What AP2 changes about your stack

Layer Pre-AP2 With AP2
Authorization Checkout button click Signed Mandate with constraints
Credential handling Agent holds a card number Agent holds a Mandate ID
Dispute resolution Support guesses who clicked Replay signed Mandate chain
Cross-merchant reuse Re-prompt per merchant One Mandate, many merchants
Crypto settlement Ad-hoc wallet handoff HTTP 402 via x402 extension
Issuer trust PCI DSS plus fraud heuristics Issuer allowlist and signature check

Key takeaways

  • Mandates replace bearer credentials. The agent carries a signed intent, not a card number; the merchant verifies scope before it charges.
  • AP2 runs on A2A. One extension key in the JSON-RPC envelope, not a new transport; if your agent already speaks A2A, you are one verification call away.
  • x402 is the crypto path in production today. HTTP 402 plus USDC on Base or Optimism, with Coinbase and MetaMask already shipping clients.
  • Constraint design is scope design. Treat max_amount, allowlists, and valid_until as the OAuth scopes of agent payments.
  • Store the Mandate chain in your PSP metadata. A chargeback three weeks out cannot dispute what you did not record.

Botoi provides the supporting endpoints an AP2 merchant flow leans on: currency conversion, country lookup, IP and VPN detection, address validation, and BIN lookup for card metadata. One API key, 5 req/min on the free tier. Browse the interactive docs or wire the MCP server into your agent so Claude or Cursor can call the same endpoints from inside the editor.

Frequently asked questions

What is AP2 and how does it differ from A2A?
AP2 (Agent Payments Protocol) is an open payments protocol Google announced for agent-led commerce. A2A (Agent2Agent) is the transport for agents talking to agents. AP2 runs as an extension on top of A2A so any A2A-capable agent can initiate a payment through a signed Mandate without reinventing the messaging layer. Think A2A as the highway and AP2 as the toll booth.
Is AP2 production-ready in April 2026?
The crypto path via the A2A x402 extension is production-ready; Google, Coinbase, the Ethereum Foundation, and MetaMask shipped it as a supported extension. Card-based flows through AP2 partners (Mastercard, Visa via Worldpay, PayPal, American Express) are in pilot through Q2 2026 with broader merchant rollout targeted later in the year. The spec is stable; the card rails are still maturing.
What is a Mandate in AP2?
A Mandate is a cryptographically signed object that binds an agent to a user intent: "spend up to $200 on a pair of size-11 running shoes before Friday." Merchants verify the signature, check the constraints (cap, expiry, category), and either settle the payment or decline. Mandates let an agent pay without being handed a bearer credit card number.
Do I need AP2 if I already accept Stripe Checkout?
Not for human-initiated checkouts; Stripe Checkout handles those. You need AP2 when an AI agent is the buyer. The difference is intent capture and authorization: a human clicks "Pay" and authorizes in the moment; an agent needs to carry a pre-authorized Mandate that proves the human approved this class of purchase. Without it, fraud disputes cannot resolve who authorized the charge.
How does AP2 handle fraud and chargebacks for agent purchases?
Every AP2 payment ties back to three signed objects: the user Mandate (what the human authorized), the agent delegation (which agent is acting), and the merchant acceptance (what was charged). Payment networks can replay the chain during a dispute and see who signed what. This is the piece Visa and Mastercard insisted on before signing up; existing chargeback rules assumed a human clicked, and without signed Mandates the liability model breaks.

Try this API

Crypto Price API — interactive playground and code examples

More guide posts

Start building with botoi

150+ API endpoints for lookup, text processing, image generation, and developer utilities. Free tier, no credit card.