-
Notifications
You must be signed in to change notification settings - Fork 0
UCP and ACP
Brief orientation on the two protocols this plugin speaks. Neither is invented here — both are public specs you'd implement against regardless of which e-commerce platform you're integrating with.
Spec: ucp.dev · GitHub: universal-commerce-protocol/ucp
Version we ship: 2026-04-08
A REST-style protocol that lets agents discover and shop a storefront via well-known endpoints. The merchant publishes a discovery document at /.well-known/ucp describing services, capabilities, and supported payment handlers; agents then call REST endpoints to browse, build a cart, and check out.
| Endpoint | Method | Purpose |
|---|---|---|
/.well-known/ucp |
GET | Discovery — services, capabilities, payment handlers |
/ucp/catalog/search |
POST | Product search |
/ucp/catalog/products/[id] |
GET | Product detail |
/ucp/checkout-sessions |
POST | Create a checkout |
/ucp/checkout-sessions/[id] |
GET / PUT | Fetch / update checkout |
/ucp/checkout-sessions/[id]/complete |
POST | Submit payment, complete |
/ucp/checkout-sessions/[id]/cancel |
POST | Cancel |
/ucp/orders/[id] |
GET | Fetch order |
{
"ucp": {
"version": "2026-04-08",
"services": {
"dev.ucp.shopping": [{ "version": "2026-04-08", "transport": "rest", "endpoint": "https://store.com/ucp" }]
},
"capabilities": {
"dev.ucp.shopping.catalog": [{ "version": "2026-04-08" }],
"dev.ucp.shopping.checkout": [{ "version": "2026-04-08" }],
"dev.ucp.shopping.order": [{ "version": "2026-04-08" }]
},
"payment_handlers": {
"xyz.fd.prism_payment": [{ "id": "x402", "version": "2026-01-15", "spec": "...", "schema": "...", "config": {} }]
}
}
}The payment_handlers block aggregates output from every registered payment handler. Reverse-DNS keys (e.g. xyz.fd.prism_payment) identify handler types; values are arrays of declarations the handler exposed.
Spec: agentic-commerce-protocol GitHub · sponsored by Stripe + OpenAI
Version we ship: 2026-01-30 (storefront response shape) — we track the spec at 2026-04-17 (PaymentHandler schema)
A different style. Discovery is per-session: when the agent creates a CheckoutSession, the seller's response includes a capabilities object with the intersection of supported payment handlers, currencies, intervention types, etc. There is no static .well-known/acp.json for handlers — only DiscoveryCapabilities (services list, supported currencies, etc.).
| Endpoint | Method | Purpose |
|---|---|---|
/.well-known/acp.json |
GET | Capabilities discovery (no per-session handlers) |
/acp/checkout_sessions |
POST | Create a session — response embeds capabilities.payment.handlers
|
/acp/checkout_sessions/[id] |
GET | Get session |
/acp/checkout_sessions/[id] |
POST | Update session (ACP uses POST, not PUT) |
/acp/checkout_sessions/[id]/complete |
POST | Submit payment via payment_data, complete |
/acp/checkout_sessions/[id]/cancel |
POST | Cancel |
ACP requires Authorization: Bearer <token> on every endpoint per the spec's OpenAPI (securitySchemes: bearerAuth, bearerFormat: API Key). The seller chooses the token format and issues it themselves; the spec leaves both out of scope. See Authentication for full details.
{
"id": "x402", // seller-defined instance id
"name": "xyz.fd.prism_payment", // reverse-DNS handler type
"version": "2026-01-15",
"spec": "https://...", // human-readable spec URL
"requires_delegate_payment": false,
"requires_pci_compliance": false,
"psp": "prism", // payment service provider id
"config_schema": "https://...", // JSON Schema URL
"instrument_schemas": ["https://..."],
"config": { /* handler-specific blob */ }
}| UCP | ACP | |
|---|---|---|
| Discovery transport | Static /.well-known/ucp
|
Per-session in CheckoutSession response |
| Reverse-DNS handler type | Object key under payment_handlers
|
name field |
| Schema URL fields | Single schema (combined) |
Separate config_schema + instrument_schemas[]
|
requires_delegate_payment / psp
|
Not present | Required |
| Update verb on checkout | PUT | POST |
| Auth | Open by default | Bearer (spec-required) |
The plugin maintains a single internal handler model and serializes through two adapters — one for each wire format. See packages/core/src/lib/formatters/{ucp,acp}.ts.
Both protocols share these concepts (different field names, same idea):
- Handler instance identifier
- Handler type identifier (reverse-DNS)
- Dated version string (YYYY-MM-DD)
- JSON Schema for handler config (Draft 2020-12)
- Merchant-supplied config blob
This is why a single handler package can serve both protocols without much duplication — the discovery output formatters massage one internal model into both shapes.
Things like shipping options come from Medusa at request time and get translated:
| Medusa source | UCP target | ACP target |
|---|---|---|
| Shipping options for cart's region | fulfillment.methods[] |
fulfillment_options[] |
| Cart total | total_amount |
total |
| Cart line items | line_items[] |
line_items[] |
| Order line items + fulfillments | UCP order shape | ACP order shape |
The merchant configures shipping in Medusa's normal Shipping Options UI. Agents see whatever's currently active. See Architecture for the framing.
- Architecture — how UCP/ACP fit into the bigger picture
- Quick Start — exact endpoints to test against
- Build a Handler — what your handler's discovery output should look like
- Authentication — auth requirements per protocol