Universal Commerce Protocol for Agent Checkout
How UCP business profiles describe services, capabilities, payment handlers, transport bindings, signed requests, and merchant responsibility.
A commerce agent needs to know more than a merchant's checkout URL. It needs compatible capabilities, schemas, payment handlers, and a way to determine which version both parties understand. UCP puts those declarations in a business profile and negotiates the usable set.
Assess the profile against one purchase: its quoted price, payment decision, order and support record. Those systems need to agree on what the customer bought and whether it was delivered.
This review uses the UCP 2026-08-25 overview and official specification repository, checked September 9, 2026. UCP is an industry specification with date-based versions, not an IETF RFC. Adoption requires pinning the implemented protocol and capability versions.
The business profile is the discovery root
A participating business serves GET /.well-known/ucp. Its profile contains a ucp object that declares the protocol version and maps of services, capabilities, and payment handlers. Public signing keys appear in the same profile.
The service entry answers how to call a vertical. For the official shopping service, an entry names a version, transport, schema, endpoint, and specification URL. A REST binding can point to an OpenAPI description and an API base URL. The endpoint plus an OpenAPI path produces the actual request URL.
Capabilities answer what the business supports within that service. Checkout, cart, catalog lookup, fulfillment, and order handling are separate declarations. Each is independently versioned and named under a reverse-domain authority, such as dev.ucp.shopping.checkout. An extension can declare a parent with extends; fulfillment, for example, has no meaning if checkout isn't in the negotiated set.
Payment handlers describe compatible ways to supply a payment instrument. They can identify handler-specific schemas and configuration while keeping raw payment credentials out of general discovery. A declared handler is not proof that every transaction will accept it. The business still evaluates the checkout context and processes payment through its chosen provider.
The profile's URLs are active inputs. A client may fetch remote schemas, which introduces server-side request forgery and stale-content risk. The current specification binds a schema origin to the reverse-domain namespace and requires safe URL fetching. Implementers should also allow only HTTPS, reject user information in URLs, resolve and recheck public addresses, refuse redirects where the specification requires it, and cap response size and fetch time.
Date-based versions support explicit capability intersection
UCP version identifiers use YYYY-MM-DD and represent the last backward-incompatible change. Capabilities carry versions as well. The business can publish version-specific profiles for older protocol releases through supported_versions.
The platform advertises its own profile URL in the UCP-Agent request header. The business intersects capability names, finds mutually supported versions for each name, and selects the highest shared date. Extensions whose parents are absent are removed. The business includes the resulting active capability set in every response.
That repeated result matters during a long checkout. A platform doesn't have to infer that a previously advertised extension stayed active for this request. It reads the response and handles only the selected set.
Version dates are identifiers, not a promise that newer is always safe for a particular merchant. A production upgrade still needs schema compatibility tests, stored-session migration, partner coordination, and a rollback plan. Cache profile responses, but set an expiry that lets a withdrawn key or capability disappear promptly.
Transport bindings share the commerce model
UCP separates a service from its wire binding. Current documentation covers REST with OpenAPI, MCP with OpenRPC over streamable HTTP, A2A through an Agent Card, and an embedded OpenRPC binding. A business can publish more than one binding for the same service.
That doesn't mean every business should. Each transport adds authentication, conformance, support, and observability work. I would start with REST when a merchant already has a suitable server API, because it gives the team fewer new transport and support paths to validate. MCP may fit an existing agent tool surface, but it shouldn't be added merely because the caller is an agent.
The platform chooses a mutually supported binding and uses the schemas attached to it. Business logic must remain consistent across bindings. If REST refuses an out-of-stock item while MCP accepts it, the advertised common model has split into two products.
HTTP Message Signatures protect direct interactions
For UCP's public-profile interaction model, the current message signature specification applies RFC 9421 HTTP Message Signatures to HTTP-based transports. Profiles publish JWK public keys. Implementations must support ES256 verification as the baseline, with other algorithms subject to the specification and counterparty needs.
A state-changing REST request signs derived HTTP components and relevant fields, including the request method, authority, path, UCP-Agent, Idempotency-Key, Content-Digest, and content type in the documented profile. Covering the digest binds the signature to the exact body. Covering the idempotency key prevents an intermediary from changing the duplicate-operation identity without breaking verification.
Idempotency remains a business control. A valid signature authenticates a request and protects its integrity; it doesn't stop the same signed request from arriving twice. Store operation keys with their completed response, and return that result on retry without a second payment capture or order.
Key operations need their own runbook. Publish overlapping keys during planned rotation, remove a compromised key promptly, bound profile caches, and record which key verified a request. Never place private keys in the profile or application logs.
The business stays Merchant of Record
UCP keeps the business at the center of the transaction. The business typically remains Merchant of Record, owns the customer relationship, and carries financial responsibility. Its existing systems still decide price, tax, availability, fulfillment, returns, support, and payment acceptance.
An agent platform presents the interaction and acts for its principal within negotiated capabilities. A credential provider can tokenize payment data. A payment service provider authorizes and captures funds. Those roles reduce unnecessary credential exposure, but they don't transfer the merchant's obligations. A hypothetical shipping change illustrates the boundary: the agent proposes the new address, the merchant recalculates eligible delivery options and totals, and the buyer accepts the resulting terms. A previously signed request doesn't authorize a later higher total by implication.
This boundary should appear in failure handling. A valid payment instrument can't make an unavailable item purchasable, so the business refuses or revises checkout. Late delivery remains a business support issue. And when a refund is due, the business's policy and processor execute it.
Connect the profile to a purchasable offering
UCP discovery needs the commerce operations its profile advertises. An inquiry whose scope and price will be negotiated later can remain a service form. Publish a business profile when the merchant can return authoritative checkout state and carry the purchase through payment, order handling and customer support.
The merchant's system must own item availability and recalculate totals when discounts, tax, fees or shipping change. Identify the supported schemas and transport, payment handlers and processor relationship against that system.
Verify a changed total and a repeated request
Use a transaction fixture that changes shipping after the initial quote. Confirm that both parties agree on the new total before commitment. Then repeat completion after a lost response and check that it returns the existing order rather than charging or fulfilling twice.
Review profile and schema fetching, request signatures, credentials and customer data on that path. Keep the order, payment and webhook records correlated so support can resolve a partial failure.
Every URL in the profile should identify a supported operation. Remove or update its discovery entry when the operation is retired; otherwise cached discovery can continue directing clients to an obsolete contract.