Skip to main content
Use Agentcard’s Purchase API to let your agent buy things online without building merchant integrations or using an agent browser. Merchants supported today include Amazon, Walmart, Target, Best Buy, and many more.

Where agents can buy

Here are a few examples of merchants supported today:
Amazon logoAmazon
Walmart logoWalmart
Target logoTarget
Best Buy logoBest Buy
Home Depot logoHome Depot
Lowe's logoLowe’s
Macy's logoMacy’s
Wayfair logoWayfair
Staples logoStaples
Kohl's logoKohl’s
B&H Photo logoB&H Photo
DoorDash logoDoorDash
Good Eggs logoGood Eggs
Locale logoLocale
Flights
For the live list, call GET /buy/merchants with the same bearer token you send to /buy.

What you need

  1. A user with a card in the Vault (Adding a card).
  2. A user-scoped bearer token.
    • /buy always runs as a single user, so org tokens are rejected.
    • Use the user’s connection access_token, or mint a buy_token for a cardholder you own:
Recommended: set a client timeout of at least 120 seconds. Each turn runs against a live merchant.

Quickstart

Every call is a POST /buy. A single purchase follows a turn-based loop, tied together by conversation_id.

1) Start (send an ask)

2) Loop: reply → ask (until a cart is ready)

If the API needs more info, it responds with status: "needs_input" and a natural-language reply. Show reply to the user, then send the user’s answer back as the next ask with the same conversation_id:
Repeat this loop as needed. Nothing can be charged during it.

3) Read the cart (use structured fields)

Once the API has enough details, the response includes a cart and a cart.hash. Use these structured fields (not the prose) to show the user exactly what will be purchased.
Notes:
  • unmatched lists anything requested that didn’t make it into the cart (plus a reason). Show it instead of guessing from the prose.
  • The status can still be needs_input here, because the API is asking for confirmation.
  • If the user wants a change (for example, “make it two bags”), send that as another ask. You’ll get an updated cart with a new hash.

4) Confirm the cart hash (and choose a payment source)

When the user wants to proceed, confirm the exact cart you showed by sending the cart.hash (not a free-form “yes”). To pay with the user’s own card, pass payment_source: "vault".

5) If approval is required: send the approval URL, then retry confirm

A confirm may pause while the user approves:
This is a pause, not a verdict. Nothing was charged. Send approval_url to the user. After they approve (Face ID), repeat the same confirm call from step 4. When the purchase is placed:

The fields you branch on

Edge cases

If the price changed

A confirm authorizes one cart at one price. If anything drifted since the cart was shown, confirm returns 409 with a fresh cart and a new hash. Show the user the new total, then confirm the new hash.

Track the order

Retail orders confirm asynchronously (often ~1 minute after placement).
This returns the retailer’s order number, delivery window, final total, and shipments once a package ships. Or listen for the order.placed and order.confirmed webhooks instead of polling.

If a confirm times out

Don’t resend. First, read the conversation:
Wait for turn_in_progress to clear, then check orders. A duplicate confirm while a turn is running returns 409 turn_in_progress, so the same cart can never place twice.

Over MCP

The same loop is available as the buy tool on https://mcp.agentcard.sh/mcp, using the same bearer. The agent relays each turn, the user confirms in words, and the tool places the order.

Sandbox

Sandbox runs the real loop against real merchants up to the confirm. The confirm returns declined with decline_code: "sandbox_mode" by design, because sandbox cards can’t pay a real merchant. Everything before it (conversation, cart, hash) is identical to production.