Protocols
ACP checkout
The five ACP checkout operations mapped onto your existing checkout API.
The Agentic Commerce Protocol checkout service, pinned to 2026-04-17 and experimental. Five operations, each mapped to one resource that fronts the merchant's existing checkout API.
| ACP operation | Route | Resource |
|---|---|---|
createCheckoutSession | POST /acp/checkout_sessions | acp_checkout_create |
updateCheckoutSession | POST /acp/checkout_sessions/{id} | acp_checkout_update |
getCheckoutSession | GET /acp/checkout_sessions/{id} | acp_checkout_get |
completeCheckoutSession | POST …/{id}/complete | acp_checkout_complete |
cancelCheckoutSession | POST …/{id}/cancel | acp_checkout_cancel |
version: 1
merchant:
id: acp-checkout-example
name: ACP Checkout Example
publicBaseUrl: ${GATEWAY_PUBLIC_BASE_URL:-http://localhost:8080}
server:
port: ${GATEWAY_PORT:-8080}
host: 0.0.0.0
storage:
receipts:
driver: sqlite
path: ${RECEIPT_STORE_PATH:-./data/receipts.sqlite}
protocols:
# Off: this gateway serves ACP, not generic HTTP resource routes.
http:
enabled: false
mcp:
enabled: false
mountPath: /mcp
acp:
enabled: true
mountPath: /acp
auth:
type: bearer
token: ${ACP_BEARER_TOKEN:-local-development-acp-token}
idempotency:
# Its own database — never shared with receipts or x402 replay.
path: ${ACP_IDEMPOTENCY_PATH:-./data/acp-idempotency.sqlite}
retentionHours: 24
checkout:
operations:
createCheckoutSession: acp_checkout_create
updateCheckoutSession: acp_checkout_update
getCheckoutSession: acp_checkout_get
completeCheckoutSession: acp_checkout_complete
cancelCheckoutSession: acp_checkout_cancel
discovery:
supportedCurrencies: [usd]
supportedLocales: [en-US]
# Every ACP checkout resource is free with no payments: ACP checkout carries
# the merchant's own purchase payment in `payment_data`.
resources:
acp_checkout_create:
name: Create checkout session
description: ACP createCheckoutSession. Answers 201 with a checkout session.
input:
type: object
properties:
body: { type: object }
required: [body]
additionalProperties: false
backend:
type: http
method: POST
url: ${MERCHANT_API_BASE_URL:-http://localhost:3000}/checkout_sessions
inputBindings:
body: body
timeoutMs: 10000
pricing:
type: free
expose: [acp]
acp_checkout_update:
name: Update checkout session
description: ACP updateCheckoutSession.
input:
type: object
properties:
path:
type: object
properties:
checkout_session_id: { type: string }
required: [checkout_session_id]
additionalProperties: false
body: { type: object }
required: [path]
additionalProperties: false
backend:
type: http
method: POST
url: ${MERCHANT_API_BASE_URL:-http://localhost:3000}/checkout_sessions/{checkout_session_id}
inputBindings:
path: path
body: body
timeoutMs: 10000
pricing:
type: free
expose: [acp]
acp_checkout_get:
name: Retrieve checkout session
description: ACP getCheckoutSession.
input:
type: object
properties:
path:
type: object
properties:
checkout_session_id: { type: string }
required: [checkout_session_id]
additionalProperties: false
required: [path]
additionalProperties: false
backend:
type: http
method: GET
url: ${MERCHANT_API_BASE_URL:-http://localhost:3000}/checkout_sessions/{checkout_session_id}
inputBindings:
path: path
timeoutMs: 10000
pricing:
type: free
expose: [acp]
acp_checkout_complete:
name: Complete checkout session
description: ACP completeCheckoutSession. `payment_data` reaches the backend as ordinary business input.
input:
type: object
properties:
path:
type: object
properties:
checkout_session_id: { type: string }
required: [checkout_session_id]
additionalProperties: false
body: { type: object }
required: [path]
additionalProperties: false
backend:
type: http
method: POST
url: ${MERCHANT_API_BASE_URL:-http://localhost:3000}/checkout_sessions/{checkout_session_id}/complete
inputBindings:
path: path
body: body
timeoutMs: 15000
pricing:
type: free
expose: [acp]
acp_checkout_cancel:
name: Cancel checkout session
description: ACP cancelCheckoutSession.
input:
type: object
properties:
path:
type: object
properties:
checkout_session_id: { type: string }
required: [checkout_session_id]
additionalProperties: false
body: { type: object }
required: [path]
additionalProperties: false
backend:
type: http
method: POST
url: ${MERCHANT_API_BASE_URL:-http://localhost:3000}/checkout_sessions/{checkout_session_id}/cancel
inputBindings:
path: path
body: body
timeoutMs: 10000
pricing:
type: free
expose: [acp]
payments: {}Why every resource is freeACP checkout carries the merchant's own purchase payment, in
payment_data on completion. It is business input for your backend — never converted into an x402 payment — and a paid mapping is refused at load.Run it
This example assumes a backend that already implements the ACP checkout shapes at ${MERCHANT_API_BASE_URL}/checkout_sessions…; point it at yours.
AGENT_COMMERCE_CONFIG=examples/acp-checkout/config.yaml npx tsx src/gateway/main.ts
# in another terminal
npm run agent-commerce -- validate --config examples/acp-checkout/config.yaml
npm run agent-commerce -- doctor --config examples/acp-checkout/config.yamlCall it
curl -s http://localhost:8080/.well-known/acp.json
curl -s http://localhost:8080/acp/checkout_sessions \
-H "Authorization: Bearer local-development-acp-token" \
-H "API-Version: 2026-04-17" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"line_items":[{"id":"item_123"}],"currency":"usd","capabilities":{}}'Retrying with the same Idempotency-Key replays the stored answer with Idempotent-Replayed: true and never reaches the merchant twice; the same key with a different body is a 422. Wire details: ACP.
Source: examples/acp-checkout