The Universal Commerce Protocol defines a common language for AI agents, platforms, and businesses to conduct commerce without custom integrations. This page walks through the core concepts in plain English.
UCP separates protocol version compatibility from capability negotiation. This is a key design decision:
2026-04-08). Both parties must agree on this.The merchant publishes its profile at /.well-known/ucp. This profile describes capabilities for the protocol version it declares. If the merchant supports multiple versions, it can advertise them via the supported_versions field - a map from protocol version to profile URI.
The business (server) determines the active capabilities. Not the agent. The agent declares what it can do, the merchant intersects that with what it supports, and the merchant selects the final set. This keeps the merchant in control.
Both business and platform profiles can be cached by both parties, enabling efficient capability negotiation within the normal request/response flow.
UCP uses reverse-domain naming to encode governance authority directly into capability identifiers. This eliminates the need for a central registry.
All capability and service names follow this format:
{reverse-domain}.{service}.{capability}
| Name | Authority | Service | Capability |
|---|---|---|---|
dev.ucp.shopping.checkout | ucp.dev | shopping | checkout |
dev.ucp.shopping.fulfillment | ucp.dev | shopping | fulfillment |
dev.ucp.common.identity_linking | ucp.dev | common | identity_linking |
com.example.payments.installments | example.com | payments | installments |
The spec and schema URLs must match the namespace authority. dev.ucp.* capabilities must point to https://ucp.dev/.... com.example.* must point to https://example.com/.... Platforms MUST validate this binding and SHOULD reject mismatches.
| Namespace Pattern | Authority | Governance |
|---|---|---|
dev.ucp.* | ucp.dev | UCP governing body |
com.{vendor}.* | {vendor}.com | Vendor organization |
org.{org}.* | {org}.org | Organization |
A service defines the API surface for a vertical. Current services: shopping, common. Coming soon: lodging, food.
Services include operations, events, and transport bindings defined via standard formats:
| Field | Required | Description |
|---|---|---|
version | Yes | Entity version in YYYY-MM-DD format |
spec | Yes | URL to human-readable specification |
schema | No* | URL to JSON Schema (required for REST, MCP, embedded) |
id | No | Unique identifier when multiple instances exist |
config | No | Entity-specific configuration |
transport | Yes | One of: rest, mcp, a2a, embedded |
endpoint | No | Base URL for API calls |
The endpoint field provides the base URL. OpenAPI paths are appended directly to form complete URLs:
// Service declares:
"endpoint": "https://business.example.com/api/v2"
// OpenAPI path: /checkout-sessions
// Resolved URL:
POST https://business.example.com/api/v2/checkout-sessions
A capability is a feature within a service. It declares what functionality is supported and where to find its documentation and schemas.
| Field | Required | Description |
|---|---|---|
version | Yes | YYYY-MM-DD format |
spec | Yes | URL to human-readable spec |
schema | Yes | URL to JSON Schema |
id | No | Unique identifier for this instance |
config | No | Capability-specific configuration |
extends | No | Parent capability(s) - present for extensions only |
An extension is an optional module that augments another capability. Extensions use the extends field to declare their parent(s).
{
"dev.ucp.shopping.fulfillment": [
{
"version": "2026-04-08",
"spec": "https://ucp.dev/2026-04-08/specification/fulfillment",
"schema": "https://ucp.dev/2026-04-08/schemas/shopping/fulfillment.json",
"extends": "dev.ucp.shopping.checkout"
}
]
}
Extensions can extend multiple parents by using an array:
{
"dev.ucp.shopping.discount": [
{
"version": "2026-04-08",
"spec": "https://ucp.dev/2026-04-08/specification/discount",
"schema": "https://ucp.dev/2026-04-08/schemas/shopping/discount.json",
"extends": ["dev.ucp.shopping.checkout", "dev.ucp.shopping.cart"]
}
]
}
When an extension has multiple parents, it MAY define different fields for each capability (e.g. loyalty_earned for checkout, loyalty_preview for cart).
Extensions use allOf composition. Each extension schema MUST have a $defs entry for each parent, with the key matching the parent's full capability name. This enables deterministic schema resolution.
The business profile at /.well-known/ucp is the complete discovery document. It contains:
ucp.version - the protocol versionucp.services - map of service names to transport bindingsucp.capabilities - map of capability names to capability definitionsucp.payment_handlers - map of payment handler identifiers to handler definitionsucp.supported_versions - optional map of older protocol versions to profile URIsUCP uses dated releases in YYYY-MM-DD format. The protocol version is negotiated on every request:
/.well-known/ucpversion, proceed to capability negotiationsupported_versions, fetch the version-specific profileversion_unsupported errorPre-release implementations MUST NOT be surfaced through public discovery. Businesses MUST NOT advertise a non-date version string (e.g. "draft") in their profile. Pre-release coordination happens outside public discovery.
dev.ucp.* capabilities version with protocol releases by defaultcom.{vendor}.* capabilities version fully independently