> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentcard.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Purchases

> One conversational endpoint that builds a cart at a real merchant and places the order once you confirm.

The **Purchase API** is a turn-based loop on one endpoint. You send what the user wants as plain text in `ask`, follow up with the same `conversation_id`, and place a shown cart by echoing its `hash` in `confirm`. Money moves only on a confirm, and only for exactly the cart the hash describes.

The bearer is a **user** token: the connection `access_token` or a cardholder `buy_token`. A platform token is rejected, because a purchase always runs as one user. Use a client timeout of at least 120 seconds.

## The purchase response object

Every `200` from `POST /buy` carries the same envelope. Each field is always present and `null` when empty.

| Field             | Type           | Description                                                                                                              |
| ----------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `conversation_id` | string         | The thread. Send it back on every follow-up.                                                                             |
| `status`          | string         | `needs_input`, `order_placed`, `partially_placed`, `declined`. The only field you branch on.                             |
| `reply`           | string         | The assistant's turn as prose. `messages` carries it split into chat bubbles.                                            |
| `cart`            | object or null | The most recently shown cart. See below.                                                                                 |
| `carts`           | array          | Every open cart in the conversation, each with its own `hash`.                                                           |
| `catalog`         | object or null | The last product search as data, with an `as_of` stamp.                                                                  |
| `unmatched`       | array          | Asks that did not make it into a cart: `{ merchant, requested, reason, detail, at }`.                                    |
| `order_id`        | string or null | Set when this call placed an order. Reconcile on it.                                                                     |
| `payment_source`  | object or null | `{ source, brand, last4 }`. `source` is `balance`, `added_card`, `vault`, `company_balance`, or `stored_payment_method`. |
| `decline_code`    | string or null | `vault_approval_required`, `byoc_approval_required`, `sandbox_mode`, `items_unavailable`, …                              |
| `approval_url`    | string or null | Send to the user when the confirm paused.                                                                                |
| `charge_status`   | string or null | `none`, `confirming`, `settled`, `unknown`.                                                                              |
| `placements`      | array or null  | Per-cart outcomes of a multi-cart confirm.                                                                               |
| `error_code`      | string or null | Machine-readable loop failure.                                                                                           |

## The cart object

| Field                                        | Type            | Description                                                                                          |
| -------------------------------------------- | --------------- | ---------------------------------------------------------------------------------------------------- |
| `merchant`, `merchant_name`                  | string          | Rail id (`retail`, `doordash`, …) and display name.                                                  |
| `items[]`                                    | array           | `{ name, qty, priceCents, product_id }`.                                                             |
| `serviceFeesCents`, `tipCents`, `totalCents` | integer         | The all-in total the user approves.                                                                  |
| `approvedCeilingCents`                       | integer or null | The most a confirm can authorize when tax and shipping finalize later. Null when equal to the total. |
| `hash`                                       | string          | Identifies exactly this cart at this price. Echo it in `confirm`.                                    |

```json theme={null}
{
  "merchant": "retail",
  "merchant_name": "Amazon",
  "items": [{ "name": "Cafe Mesa de los Santos Colombian Ground Coffee, 16 oz", "qty": 1, "priceCents": 2250, "product_id": "https://www.amazon.com/dp/B07ZQ5C4RB" }],
  "serviceFeesCents": 56,
  "tipCents": 0,
  "totalCents": 2306,
  "approvedCeilingCents": 3444,
  "hash": "9f2c4a1b8e3d5f07"
}
```

## Endpoints

| Endpoint                      |                                                                                                                         |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `POST /buy`                   | [Buy](/api-reference/purchases/buy): ask, follow up, confirm                                                            |
| `GET /buy/merchants`          | [List the merchants](/api-reference/purchases/merchants) `/buy` can place at                                            |
| `GET /buy/conversations/{id}` | [Read a purchase conversation](/api-reference/purchases/conversation): reconcile a confirm whose response never arrived |

Webhooks: `order.placed`, `order.failed`, `order.confirmed`. The guide is [Agentcard's Purchase API](/vault/integrations/ecommerce-apis/purchase-api).
