UCP and ACP
The Universal Commerce Protocol and the Agentic Commerce Protocol, as every Storeware shop speaks them.
Every Storeware shop speaks two agent commerce protocols: the Universal Commerce Protocol (UCP) and the Agentic Commerce Protocol (ACP). Both are served from https://api.storeware.ai for every shop, both take an agent key, and both are served by the same checkout underneath, so prices, stock and the shop's rules are the same whichever one an agent speaks.
Storeware pins each protocol to one dated release and tests its answers against that release's own schemas. Read the version from the shop's discovery document rather than from this page.
UCP
Discovery
A shop's profile is at https://<shop>/.well-known/ucp. It names the protocol version, the capabilities and extensions the shop offers, the endpoint for each transport, the payment handlers, and the keys the shop signs with. The platform's own profile, which names no shop, is at https://api.storeware.ai/.well-known/ucp.
A profile may also list supported_versions: an older release the shop still answers, each with a profile of its own at /.well-known/ucp/<version>. A platform on a release the shop does not answer is refused with version_unsupported, which is HTTP 422 over REST.
Transports
| Transport | Endpoint |
|---|---|
| REST | https://api.storeware.ai/api/ucp/v1 |
| MCP | https://api.storeware.ai/ucp/mcp |
| A2A | https://api.storeware.ai/api/ucp/a2a, named in the shop's profile beside its agent card at https://<shop>/.well-known/agent-card.json |
Calling it
POST https://api.storeware.ai/api/ucp/v1/catalog/search
Authorization: Bearer swa_...
UCP-Agent: profile="https://platform.example/.well-known/ucp"
Content-Type: application/json- The key. An agent key, as
Authorization: Bearer. The REST routes also take it asX-API-Key, and refuse a request that names two different keys. - Your profile. Every request names the calling platform's own profile in
UCP-Agent. Over MCP it goes inmeta["ucp-agent"].profileinstead. Capabilities are negotiated against it, so an extension your profile does not declare is left out of the answer. - Signatures. A request signed with RFC 9421 is checked against the keys in your profile, and a signature that does not verify is refused. An unsigned request is accepted.
- Retries. Send
Idempotency-Keyon a write, and a retry with the same key gets the first answer.
What a shop offers
| Capability | REST routes |
|---|---|
| Catalogue search and lookup | POST /catalog/search, POST /catalog/lookup, POST /catalog/product |
| Checkout | POST /checkout-sessions, GET and PUT /checkout-sessions/{id}, POST /checkout-sessions/{id}/complete, POST /checkout-sessions/{id}/cancel |
| Cart | POST /carts, GET and PUT /carts/{id}, POST /carts/{id}/cancel |
| Order | GET /orders/{id}, and order webhooks |
Beside those, a shop's profile declares fulfilment, discounts, buyer consent, AP2 mandates and payment authentication on checkout, and two extensions of Storeware's own: ai.storeware.shopping.answer, which explains a catalogue search (see Answers), and ai.storeware.shopping.terms, for a checkout that needs the shopper to accept terms.
A cart and a checkout session are the same basket, so a cart's id is its checkout id. A cart's totals are estimates, because tax and delivery need an address. See Universal Cart.
Identity linking
A shopper can link a platform to their account at a shop with OAuth on the shop's own hostname: the metadata is at https://<shop>/.well-known/oauth-authorization-server, and the shopper consents at the shop's /account/authorize. The one scope a shop names is dev.ucp.shopping.order:read, which lets the platform read the shopper's orders. Self registration is on the same server: see How an agent signs in.
Permalinks
A shop's profile also declares dev.ucp.shopping.permalink: a basket as a link a person opens. https://<shop>/buy/<item>:<quantity>, with pairs joined by commas, lands the shopper on the shop with those items in their basket.
ACP
Discovery
A shop's ACP discovery document is at https://<shop>/.well-known/acp.json, and the platform's at https://api.storeware.ai/.well-known/acp.json.
Calling it
The base is https://api.storeware.ai/api/acp, with an agent key as Authorization: Bearer.
| Resource | Routes |
|---|---|
| Checkout sessions | POST /checkout_sessions, GET and POST /checkout_sessions/{id}, POST /checkout_sessions/{id}/complete, POST /checkout_sessions/{id}/cancel |
| Carts | POST /carts, GET and PUT /carts/{id}, POST /carts/{id}/cancel |
- Version. Send
API-Version. A version the shop does not speak is a 400 withunsupported_api_versionand asupported_versionslist. A request without the header is served at the current version, and every response says which version answered. - Retries.
Idempotency-Keyis honoured on everyPOST. - Money is integer minor units everywhere.
- Errors are flat objects with
type,code,messageand, where it helps,param.
A cart id and a checkout session id are the same identifier. A cart that has been placed, cancelled or has expired is a 404 at /carts, while /checkout_sessions still serves it.
Paying
Storeware takes delegated payment and does not issue it. The agent gets a shared payment token from Stripe and passes it to complete, using the payment handler the session advertises. Storeware never takes a card number, so delegate_payment is not served.
Store credit on a session is shown as a total of type store_credit, and the card is charged the total less that credit. A shop that has turned on stablecoins also advertises an x402 handler: see x402.
Signing requests
Signing is set per agent key. A key with a public key registered must sign every request; a key without one carries on unsigned.
| Algorithm | Ed25519, or ES256 over P-256. The key is registered as an SPKI PEM. |
| Signed value | timestamp + \n + method + \n + path + \n + the raw body as sent |
| Headers | Signature (base64url) and Timestamp (RFC 3339) |
| Window | 300 seconds either side of now |
Ed25519 is the one to choose unless you also sign AP2 mandates, which need ES256. An ES256 signature is the raw r||s pair, not DER.
Order webhooks
Orders a key placed are posted to the URL registered on that key: order_create once, then order_update for every change, each carrying the whole current order. A delivery is signed Merchant-Signature: t=<unix>,v1=<hex>, over the timestamp, a dot and the raw body, with a 300 second tolerance. Revoking the key stops delivery.