ACP transaction round trip: worked sequence
The Agentic Commerce Protocol (ACP) is the storefront surface a third-party AI shopping agent drives end to end: it discovers what you sell, builds a cart, and pays under a mandate the shopper signed. The two discovery reads, the.well-known manifest and the product feed, are unauthenticated and rate-limited per IP, so an agent can fetch them cold with no credential. The three checkout operations are scoped to the storefrontId in the path, and completion additionally verifies the agent’s signature before any charge is evaluated. All five operations return raw ACP documents, not the { data, meta } envelope the authenticated Commerce API uses, and every amount is in major currency units.
The four calls below are one continuous transaction against the same storefront (org_8v1a2c) and session (sess_cust_c61f_92e4). Substitute your published storefront id, which you can read from publicUrl on the stored storefront config.
1. Discover the manifest
GET /api/v1/public/commerce/acp/{storefrontId}/.well-known/agentic-commerceX-API-Key header is needed: this read is unauthenticated, so an agent that has never seen your storefront before can resolve it. Parse capabilities to check what the storefront supports, and endpoints for the exact paths to call next; the manifest is self-describing, so the agent never has to guess URLs. The same unauthenticated pattern serves the product feed at endpoints.productFeed, whose items array is what the agent presents to the shopper.
2. Open a checkout session
POST /api/v1/public/commerce/acp/{storefrontId}/checkoutid is opaque and caller-chosen, so put your customer or basket reference in it; it is the handle you correlate the order against later. items comes straight from the feed. Every price in the response is computed server-side against the merchant’s stored catalog, so nothing you send can set a price, and any line that cannot be honoured (unknown product, out of stock, clamped quantity) comes back in messages with a code you can surface to the shopper.
messages contains any type: "error" entry stays not_ready_for_payment and cannot be completed; fix the cart and replace the item set with POST .../checkout/update (replace-items semantics), which re-prices and re-derives the status.
3. Complete checkout under the mandate
POST /api/v1/public/commerce/acp/{storefrontId}/checkout/completePOST /api/v1/commerce/agent-mandate, described in the Commerce API reference) and hands to the agent. The request body round-trips the two snapshots you already hold, the ready_for_payment session from step 2 and the mandate; the agent identifies itself with the Signature-Agent Web Bot Auth header, and an anonymous or unverifiable caller is rejected before any charge. The session is re-priced server-side once more and the mandate’s caps are re-verified, so the charge cannot exceed what the shopper signed.
authorization.authorized: true records the mandate charge, authorization.remainingCap shows what the shopper’s cap has left, and session.order is the minted order. On deployments that settle on-chain (x402), authorization additionally carries a settlement receipt with the network and transaction hash; where settlement is not enabled the field is absent and the mandate authorization alone is the capture record.
4. Confirm the order and its state
The ACP edge is stateless by design: the session snapshot round-trips in each request, so the completion receipt from step 3 is the order status.session.order.id is the order to fulfil against, session.order.amount and currency are the captured total, and session.status is the payment state. There is no separate order-status read on the public edge; the merchant’s backend drives fulfilment from this receipt and from the commerce payment events it already receives on its webhooks.
The session’s status moves through these states, and the two terminal ones are immutable:
Resending a completed session to
checkout/complete or checkout/update is rejected rather than re-charged, so a retried completion is safe: treat the order on the first receipt as authoritative.
Errors worth branching on
Failures on this page keep the platform{ error, meta } envelope. Three statuses carry the transactional meaning:
404
404 means the storefront id is unknown or the merchant has unpublished it. It fires on every operation on this page, including the manifest, so an agent should treat it as “this merchant is not on ACP” and stop, not retry.
402
402 is payment required: on deployments with on-chain settlement enabled, the settlement was rejected or unavailable (a missing or invalid X-PAYMENT header, an unverifiable payment, or a checkout priced in a currency the settlement rail does not accept). The mandate is untouched and the session stays ready_for_payment, so correcting the payment and resending completes the same session.
409
409 means another caller modified the same session first, typically a concurrent completion that already minted the order. Do not open a second session: read the order from the winning receipt and continue fulfilment from there.
A 422 at completion carries the mandate deny reason (for example, a charge past the per-transaction cap or outside the allowed categories) in error.message, and a 422 at checkout lists the offending lines in messages; branch on those and resend a corrected cart rather than blind-retrying the same body. For the platform-wide decision table these branches plug into, see the error handling guide.
For the prose walkthrough of the same round trip, including the merchant-side storefront setup and mandate issue, see Complete a purchase with the Agentic Commerce Protocol.