Skip to main content
The Purchase API turns one POST of plain text into a placed order at a real merchant, paid with the user’s card. You send what the user wants in plain English; Agentcard picks the merchant, signs in, builds the cart, and comes back with an exact all-in price. You approve by echoing back a hash of that cart, and the order goes in. That’s the whole surface. There’s no catalog to sync, no per-merchant integration, and no checkout form to build. One rule governs everything here: money moves only when you confirm the hash of a cart the API showed you. It’s why a plain ask can never charge anyone, why a stale confirmation fails instead of guessing, and why you can hand this endpoint to an autonomous agent. Most of the behavior on this page follows from that rule. This guide walks the full loop and the payment layer underneath it. For the exact request and response contract, see the POST /buy reference. To run everything with no real money first, start with your first order in sandbox.

What you need

You already have everything this page needs. When your server connected the user, it stored their Agentcard user id and a connection access_token. That same access_token is the bearer for every call on this page: there’s no second sign-in and no separate purchase credential. The agent pays with whatever the user has in their wallet, a card they added or their Agentcard balance. Their agent can run the loop two ways, and both hold the same conversation and build the same cart at the merchant:
  • Over MCP. The agent connects to https://mcp.agentcard.sh/mcp with the connection token and calls the buy tool. The loop is conversational: the agent relays each turn, the user confirms in words, and the tool places the order. Most integrations take this path, because the agent talks to Agentcard directly. Buy through MCP shows the wiring.
  • Over HTTP. Your server calls POST /buy with the connection token as the bearer and gets the cart back as data, with a hash it echoes to confirm. That’s what the rest of this page walks through.
If your users never connect an Agentcard of their own, see org-owned accounts: a cardholder you create plus a buy_token stands in for the connection token, and everything else is identical.
To feel the loop before wiring anything, run agent-cards buy in your terminal. It’s the same conversation your users’ agents will have, running as your own personal Agentcard rather than as a connected user, which is why it isn’t a third integration path.

Where agents can buy

Amazon, Walmart, Target, Best Buy, Home Depot, Lowe’s, Macy’s, Wayfair, Staples, Kohl’s, and B&H Photo, plus DoorDash, Good Eggs, Locale, and flights. The list keeps growing, and /buy itself tells the agent when a merchant needs the user to link an account first.
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
We’re building one consistent, modern API to access millions of products across retailers worldwide.

Place your first order

1

Ask for what the user wants

Send the request as plain text. The bearer is the user’s connection access_token, so everything that follows is scoped to that user and your connection:
2

Read the cart, not the prose

The response comes back in two layers. The reply is prose you can show a human. The cart is data for your code, with an all-in total and the hash that identifies exactly this cart.
Response
needs_input is not an error. It’s the API asking the next question on the way to a purchase. Show the reply to your user and send their answer back as the next ask with the same conversation_id.
3

Confirm with the hash

Your user says yes. You don’t send the word “yes”; you send the hash, so what gets approved is exactly what was shown:
Confirm
Response
The order exists at the merchant, the charge is on the user’s card, and you made two HTTP calls.
Between showing the cart and this confirm, no money has moved and nothing is reserved. The entire payment runs inside this one turn; the next section walks it beat by beat.

How the money moves

Look back at the receipt: “Charged $23.06 to a one-time card ending 4832.” That card didn’t exist before the confirm, and it doesn’t exist after. The whole payment happens inside the confirm turn, in four beats:
  1. Reserve. Agentcard checks the cart’s total against the user’s budget and holds that amount, so two agents can’t spend the same dollars twice.
  2. Issue. It creates a one-time virtual card for exactly this order, funded from the user’s wallet.
  3. Pay. The merchant charges that card at its own real checkout, the same way it charges any customer’s card. The merchant never integrates with Agentcard and never knows an agent was involved.
  4. Close. After its single charge, the card is closed, so nobody is left holding a reusable credential for your user.
If any beat fails, everything before it rolls back and the response tells you why. And before this turn, nothing happened at all: an ask never reserves, never authorizes, and never creates a card. That’s the governing rule doing its job at the money layer. What funds the card is the user’s choice in their wallet: their Agentcard balance, or a card they added from their own bank. Their default card decides, so there’s no per-purchase switch on /buy and the envelope doesn’t label the source; the receipt reads the same either way. Two things do differ in practice. Purchases on an added card carry no Agentcard service fee today, so the total in the cart reflects the source before the user confirms anything. And only an added card can trigger a bank approval:
The one case where the funding source surfaces: a card added from the user’s own bank can require a one-time approval before the charge. The confirm then returns declined with an approval link in the reply instead of a receipt. Show the link, let the user approve with their bank, and send the same confirm again to place the order.
For org-owned accounts (a cardholder you created and a buy_token as the bearer, see Authentication), the funding source is your company balance, not a personal wallet. You allocate spending power to a cardholder from your company balance, and every one-time card the confirm issues for that user draws on it. Fund the balance and allocate with the organization MCP server’s company-balance tools (get_company_wallet, create_card), and read a cardholder’s remaining company-funded spending power as headroomCents on GET /api/v1/cardholders/:id or the get_cardholder tool. There’s no per-purchase switch here either: the cardholder spends what the company allocated, and a confirm that outruns the allocation declines rather than drawing on any other source. Allocate more and send the same confirm again.

Request fields

string
What the user wants, in plain language. Required unless the call is a confirm.
string
The thread to continue. Returned on every response, including the first. A confirm always requires it.
string | string[]
A cart hash from a previous response, or an array of hashes to place several carts at once. An array confirm cannot carry an ask in the same call.

Response fields

Every conversational response, meaning any HTTP 200, carries the same envelope. Each field is always present and null when empty, so your client never guesses whether a missing key means “no cart” or “older server”. Error statuses are smaller shapes built around an error string instead: the 409 body appears in How the hash enforces the rule, and a 502 mid multi-cart confirm still carries placements for the orders that already went through.
string
The thread. Send it back on every follow-up.
string
One of needs_input, order_placed, partially_placed, or declined. The only field you branch on.
string
The assistant’s turn as prose, ready to show a human. messages carries the same content split into ordered bubbles for chat surfaces.
object | null
The most recently shown cart: items, fees, tip, the all-in totalCents, and the hash a confirm must echo. Machine-verifiable; never parse the prose.
array
Every open cart in the conversation, each with its own hash. A conversation can hold carts at several merchants at once.
object | null
The last product search as data: item ids, names, prices, the store they came from, and an as_of freshness stamp. Use it to render your own picker.
array | null
Per-cart outcomes of a multi-cart confirm: each entry carries its own status, reply, and error_code. null on every other call.
string | null
A machine-readable failure code when something went wrong.

How the hash enforces the rule

The hash covers exactly what was shown: items, quantities, prices, the fee, and the tip. It’s what makes the governing rule mechanical rather than a promise, through two behaviors:
  1. Money never moves on a plain ask. A cart with an exact total has to be shown first, and the API refuses to place an order in the same turn the cart first appeared.
  2. A confirmation authorizes one specific cart at one specific price. If anything drifted since the cart was shown, the confirm returns a 409 carrying the fresh carts instead of charging something the user never saw:
409 response
Here the coffee’s price rose from 22.50to22.50 to 24.50 between the cart being shown and the confirm arriving. Recovery is one step: show the user the fresh total and confirm the new hash. Confirming before any cart has been shown returns a 409 that says “nothing to confirm”; the fix is to ask first.

Buy from several merchants at once

A conversation can hold an open cart at more than one merchant. Each shows up in carts with its own hash, and you can confirm them together:
Multi-cart confirm
The orders place one after another, each as its own turn with its own audit trail, and placements reports every cart honestly:
Response
This is not one atomic transaction across merchants; no such thing exists at the money layer. All placed means order_placed, some placed means partially_placed, and your code reads placements to know exactly which orders exist.

Authentication

The bearer for /buy is the user’s connection access_token, the token your server stored when the user connected. Call from your backend as that user, and rotate it with the refresh token when it expires. See Connect users. Over MCP, the user’s agent connects with this same token; see Buy through MCP.

Fees

Purchases funded from the user’s Agentcard balance carry a service fee of 2.5% of the merchant total. Purchases on a card the user added from their own bank carry no Agentcard fee today. Either way the fee is computed once, at checkout, and it’s in the cart before any confirm, so the total the user approves is the total the card is charged. There are no fees on ask calls, searches, or carts that never get confirmed.

When something goes wrong

A declined tells you why in the reply, with a machine-readable error_code beside it. Not every rejection is a decline: if a merchant bounces something fixable, say a missing phone number on the shipping address, the loop asks for the missing fact and the status stays needs_input, because the next turn can still place the order.
Treat declined as the end of that attempt and needs_input as the road continuing. The one exception is the bank approval from How the money moves: a declined whose reply carries an approval link is a pause, not a verdict. Show the link, and once the user approves, send the same confirm again to place the order.
If the shopping agent itself cannot complete a turn you get a 502, and when that happens mid multi-cart confirm the response still carries placements for the orders that already went through.

Guardrails for live traffic

Sandbox conversations run the same loop against real merchants: agents search, build carts, and get hash-bound totals, so you can wire everything up to the confirm before a single dollar moves. The confirm itself is where sandbox stops: it returns declined by design, because sandbox test cards can never pay a real merchant. Your first order in sandbox walks that whole arc. Once you’re live, budgets cap what an agent can spend, cards can be locked to one merchant or one purchase, and purchases that need a human wait for the user’s approval while you receive approval.requested.

Rules for your agent

Rules for your agent

Next steps

You’ve seen the whole loop: ask, cart, hash, order. Run it yourself before pointing real traffic at it.

Buy through MCP

Connect your users’ agents to the MCP server with the same token. The buy tool runs this loop.

Your first order in sandbox

Place a complete purchase end to end with no real money, in about five minutes.

POST /buy reference

The exact request and response contract, every field and status code.

Test in sandbox

Every sandbox knob: test cards, simulated KYC, and webhook rehearsal.