You're implementing agentic commerce endpoints. You've read the specs. Now you need to decide: ACP, UCP, or both? This post gives you the decision framework in developer terms — no marketing fluff.
The 60-Second Summary
ACP (OpenAI + Stripe) is a checkout protocol. Five REST endpoints. Stripe payments. Focused on completing a purchase inside a conversational AI (ChatGPT). Think of it as a headless checkout API.
UCP (Google + Shopify) is a commerce lifecycle protocol. Checkout plus discovery, order management, returns, and loyalty. Multiple transports (REST, MCP, A2A, embedded). Dynamic capability discovery. Think of it as a headless commerce platform.
Both are open-source, Apache 2.0. Both keep you as the merchant of record. Both use similar checkout state machines. The difference is scope, not philosophy.
The Comparison That Matters
Data Model
Both protocols represent checkout as a session object with items, buyer info, fulfillment, and totals. The structure is 80% identical. The differences:
ACP:
{
"status": "ready_for_payment",
"line_items": [{ "id": "li_1", "item": { "id": "SKU-001", "quantity": 1 }, "total": 5999 }],
"totals": [{ "type": "total", "amount": 6499, "display_text": "$64.99" }],
"payment_handlers": [{ "id": "card_tokenized", "psp": "stripe" }],
"messages": [{ "type": "info", "code": "coupon_applied", "message": "10% off applied" }]
} UCP:
{
"state": "ready_for_complete",
"line_items": [{ "product_info": {...}, "quantity": { "total": 1, "fulfilled": 0 }, "totals": {...} }],
"totals": { "subtotal": {...}, "tax": {...}, "total": {...} },
"payment": { "handlers": [{ "id": "google_pay", "config_schema": {...} }] },
"fulfillment": { "methods": [{ "type": "shipping", "destinations": [...] }] }
} Key differences: ACP uses a flat totals array; UCP uses a nested totals object. ACP bundles errors into a messages array; UCP uses a structured error response with severity levels. ACP's fulfillment is baked into the checkout; UCP treats fulfillment as an extension.
State Machine
ACP States: UCP States:
───────────── ──────────
not_ready_for_payment <──> incomplete
(no equivalent) <──> requires_escalation
ready_for_payment <──> ready_for_complete
(no equivalent) <──> complete_in_progress
completed <──> completed
canceled <──> canceled The big difference: UCP has requires_escalation — an explicit state for "the agent can't handle this, hand off to a human via continue_url." ACP handles this implicitly through the messages array with intervention types. UCP's approach is cleaner for complex checkout flows (age verification, custom product configuration, SCA).
Error Handling
ACP errors are flat:
{ "type": "error", "code": "out_of_stock", "message": "...", "param": "items[0].id" } UCP errors have severity:
{
"messages": [{
"type": "error",
"code": "address_invalid",
"content": "...",
"severity": "recoverable"
}]
} UCP's severity levels (recoverable, requires_buyer_input, terminal) tell the agent exactly what to do next. ACP leaves that decision to the agent's judgment. For testing, UCP errors are easier to validate programmatically because the expected agent behavior is encoded in the response.
Authentication
ACP: Bearer token + HMAC-SHA256 signature on every request. OpenAI publishes IP CIDR blocks in chatgpt-connectors.json for allowlisting.
UCP: Flexible — OAuth 2.0, API keys, mutual TLS, or detached JWT signatures. Discovery via /.well-known/ucp can declare the auth method. More options, more complexity.
Payment
ACP: Stripe's SharedPaymentToken (SPT) — single-use, time-bound, amount-scoped. Agent provisions the token, merchant redeems with Stripe. Simple if you're already on Stripe.
UCP: AP2 mandates — cryptographically signed intent, cart, and fulfillment mandates. Supports Google Pay, PayPal, Mastercard, Visa, Adyen, American Express. More payment methods, more complexity.
Updates
ACP: Partial update via POST — send only the fields you're changing.
UCP: Full resource replacement via PUT — send the entire checkout object with your changes. This is safer (no ambiguity about what changed) but more verbose.
The Decision Framework
Choose ACP if:
- You're on Stripe — ACP was built for Stripe. If you already process payments through Stripe, enabling ACP is minimal effort.
- Your primary agent traffic is ChatGPT — ACP is the native protocol for ChatGPT shopping. If that's where your agent-referred customers come from, ACP is the direct path.
- You want the fastest implementation — Five REST endpoints, familiar patterns, well-documented. A strong backend developer can implement ACP in a week.
- Your checkout is simple — Single-item purchases, standard shipping, credit card payments. If you don't need complex escalation flows, ACP's simplicity is an advantage.
- You value ecosystem maturity — ACP has been in production since September 2025. The bugs have been found (and many fixed). Reference implementations exist in TypeScript (Vercel), Python, PHP.
Choose UCP if:
- You're a Shopify merchant — UCP activation is essentially push-button on Shopify. Shopify co-authored the protocol and has native MCP server support.
- Your primary agent traffic is Google — Search AI Mode, Gemini App, Google Shopping all use UCP. If Google is your traffic source, UCP is required.
- You need the full lifecycle — UCP covers order management, fulfillment tracking, returns, and loyalty. If you want agents to answer "where's my order?" post-purchase, UCP is the only option.
- You have complex checkout flows — Age-gated products, custom configurations, multi-step authentication. UCP's
requires_escalationstate withcontinue_urlhandles these cleanly. - You support multiple payment methods — Google Pay, PayPal, bank transfers, crypto. AP2 mandates are payment-method-agnostic. ACP is Stripe-only (for now).
Choose both if:
- You have significant traffic from both Google and conversational AI — Dual-protocol stores capture 40% more agentic traffic than single-protocol stores.
- You can afford the engineering investment — Both protocols share ~80% of the same data model. The incremental cost of the second protocol is ~30% of the first.
- You want maximum agent coverage — ACP covers ChatGPT + Perplexity + Microsoft Copilot. UCP covers Google + Shopify ecosystem. Together, they cover essentially every major agent surface.
Implementation Effort Comparison
| Task | ACP | UCP |
|---|---|---|
| Endpoints to build | 5 REST | 5 REST + optional MCP/A2A |
| Discovery | Manual config | /.well-known/ucp manifest |
| Auth implementation | Bearer + HMAC | OAuth 2.0 + JWT signatures |
| Payment integration | Stripe SPT only | AP2 mandates (multi-PSP) |
| Schema validation | JSON Schema (OpenAPI specs on GitHub) | JSON Schema (auto-generated TypeScript) |
| Reference implementations | Vercel ACP Handler, Locus demo, Nekuda | UCP Python SDK, UCP Samples (FastAPI, Hono) |
| Time to MVP | ~1 week | ~2 weeks |
| Testing complexity | Medium (5 endpoints × edge cases) | High (capabilities + extensions + discovery) |
The Practical Path
If you're starting from zero, here's the order I'd recommend:
- Start with whichever protocol matches your primary traffic source. If your agent traffic is coming from ChatGPT, start with ACP. If it's from Google, start with UCP. Don't guess — check your analytics for AI-referred traffic sources.
- Build a protocol abstraction layer internally. Both protocols use the same concepts (checkout session, items, buyer, fulfillment, payment). Normalize them into a single internal model. This makes adding the second protocol later a thin adapter, not a rewrite.
- Add the second protocol within 3 months. The incremental effort is small if you've built the abstraction. And dual-protocol coverage gives you the 40% traffic uplift.
- Test both protocols continuously. Protocol specs evolve. Model behavior drifts. Inventory data goes stale. Automated testing isn't a one-time thing — it's a continuous process.
Test your ACP and UCP endpoints in one click. Get your Agent Readiness Score →