How a store makes itself buyable by AI.
Quote Spec v0.7 · 22 Sep 2026 · supersedes v0.6
Working draft · breaking changes carry a version bump
This is the interface a store speaks inward, once, so any shopper’s AI can buy from it — and what that AI gets back outward. It is versioned because anything built against it should know which edition it read. If you are building something that has to buy from real stores, tell us where this breaks.
We are not adding a protocol.
There are enough. ACP, AP2, UCP, Visa’s Trusted Agent Protocol, Mastercard’s Agent Pay, MCP, x402 — they all work, and none of them failed. What failed was upstream of every one of them: nobody could say what was on the shelf, so nothing could actually be bought. Caravanserai speaks MCP outward today and adds the rest one at a time. The interface below is what a store speaks inward, once — and it does not change as each rail lands.
GET
/v1/merchants
Find stores by city, postal code and category. Every connected store is listed, each marked buyable or not.
GET
/v1/catalog?merchant=
Everything one store sells, with live price and stock. Pass the store's slug or id as ?merchant=. Cursored, and cheap to poll.
POST
/v1/quote
Ask one store for a basket: these items, these quantities, for pickup or delivery to this address. Returns one signed quote with an expiry for what the store has, naming what it does not.
GET
/v1/quotes/:id
The quote and its status. The delivery address is returned only to the key that requested it.
POST
/v1/quote/:id/accept
Convert a live quote into one order on the merchant's own system, paid by one charge to the buyer's saved card. The charge runs on the merchant's own processor, under their own account — we hold no card data and take no fee on it. Two kinds of bearer reach this: a developer's key, and a grant a buyer issued to an assistant of their own, which may spend only that buyer's cards, only where their rules allow, and only inside their caps.
Three properties a store stands behind.
01
A quote expires
Every quote carries an expiry, typically minutes. Nothing is promised indefinitely, because nothing is true indefinitely. An expired quote is refused, not silently repriced.
02
A quote is signed
Ed25519 over the canonical body. An agent can show a person the quote and a merchant can verify what they agreed to. Neither side is taking the other's word for it.
03
A quote says where and when
Pickup at the store, in a window drawn from its own hours, or delivery to a specific address in a specific window — never a generic shipping table. Wrong delivery dates were the single most cited reason the first attempt at this failed.
Response from POST /v1/quote · illustrative store
{
"quote_id": "cvs_q_8Fk2Rd4mNpQw",
"merchant": "good-mutt-supply",
"issued": "2026-08-28T20:37:11Z",
"expires": "2026-08-28T20:52:11Z",
"lines": [
{ "sku": "KIBBLE-SAL-30", "name": "Salmon kibble, 30 lb",
"quantity": 1, "unit_price": 6299, "total": 6299 },
{ "sku": "CHEW-DENT-24", "name": "Dental chews, 24",
"quantity": 1, "unit_price": 1149, "total": 1149 }
],
"unavailable": [
{ "sku": "TOPPER-SARD", "reason": "insufficient-stock",
"in_stock": 0 }
],
"price": {
"subtotal": 7448,
"delivery": 0,
"tax": 661,
"total": 8109,
"currency": "USD"
},
"fulfil": {
"method": "pickup",
"to": "Good Mutt Supply, 5th Ave, Brooklyn NY 11215",
"window": "2026-08-28T21:15:00Z/2026-08-28T22:45:00Z"
},
"returns": {
"cancel_free_until": "2026-08-28T21:15:00Z"
},
"key_id": "cvs_key_7Fq2mXbT",
"signature": "ed25519:9c1f…a04e"
}Open questions.
- Liability. Who pays when an agent buys the wrong thing is negotiated company by company today, and no protocol on the list above settles it. A signed quote fixes what was agreed, which is a start, not the whole of an answer.
- Sales tax. Unsolved industry-wide as of February 2026, and named in the post-mortem of the first attempt. Our position: quote it, and let the merchant remit it, because they already do.
- Verifying delivery. A till can prove what was charged and what was cancelled. It cannot prove a box arrived at an address — a fulfilment marked complete is a staff tap, not a doorstep. Until a courier’s API or the buyer signs for it, delivery is attested rather than verified, and this spec keeps the two apart. Who is entitled to witness an arrival is not settled by anyone.
