Skip to content
Universal Commerce Protocol Brand hub / en

Reference note

The /.well-known/ucp manifest, field by field

The real structure of the UCP discovery manifest: services, capabilities, payment_handlers, signing keys, version negotiation and error codes.

Published . Part of the UCP implementation guide.

A merchant adopting UCP publishes a JSON file at a fixed address, /.well-known/ucp. It is the single entry point: an agent discovering a domain reads that document and infers what it can do with that merchant. Most write-ups stop at that sentence. This note goes one level down, into the fields the document actually contains.

Everything below follows the official specification, version 2026-04-08. UCP versions by date: the structure described here is the one in that revision, and the negotiation mechanism described further down is precisely what allows revisions to coexist.

Two top-level keys

The document exposes two keys at the root:

{
  "ucp": { },
  "signing_keys": [ ]
}

ucp holds all protocol metadata. signing_keys holds the public keys, in JWK format, used to verify signatures. That second key is not decorative: the specification defines dedicated errors signature_missing, signature_invalid and key_not_found, all returning HTTP 401. A manifest without usable keys therefore closes the door on any signed exchange.

Inside ucp sit four registries:

  • version, the protocol version, in YYYY-MM-DD form;
  • services, the API surfaces and their transports;
  • capabilities, the declared features;
  • payment_handlers, how payment instruments are processed.

services: where and how to talk to the merchant

A service describes an API surface for a functional area. Each entry combines version, spec, transport, endpoint and schema. The specification sets a minimum rule: all transports require version, spec and transport; REST, MCP and the embedded mode additionally require schema.

Four transports are defined:

Transport Nature
REST HTTP/1.1 and above, JSON payloads, standard verbs and status codes
MCP JSON-RPC over Model Context Protocol, tools/call
A2A Agent-to-Agent protocol, via the Agent Card specification
EP OpenRPC, host / embedded communication

REST is the core transport; the others are optional and depend on the capabilities you target. This is what quick readings most often miss: UCP does not mandate MCP. A merchant can be fully compliant over REST alone. The distinction between the two protocols is covered on the UCP vs MCP page.

capabilities: what the merchant can do

A capability declares a supported feature. Required fields are version, spec and schema. Optional fields are id, config and extends.

extends is the extension mechanism. A capability can inherit from a single parent, given as a string, or from several parents, given as an array. The specification illustrates this with a fulfillment extension that extends checkout:

{
  "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"
    }
  ]
}

Naming uses reverse namespaces, dev.ucp.shopping.checkout. A merchant or a vendor can therefore declare its own capabilities under its own namespace without colliding with the official registry.

payment_handlers: a specification, not a provider

This is the nuance the specification takes care to state explicitly: payment handlers are specifications, not entities. They describe how a class of instrument is processed, not which provider processes it.

An entry combines id, version, spec, schema, available_instruments and config. The practical consequence is direct: switching PSP does not necessarily change the manifest, as long as the processing specification stays the same. The wider landscape of payment rails is on the agentic payments page.

Negotiation: an intersection, not an agreement

When an agent and a merchant meet, neither imposes its version. The specification defines a four-step intersection algorithm:

  1. compute the intersection, keeping only capabilities present on both sides;
  2. select, for each retained capability, the highest mutually supported version;
  3. prune orphaned extensions, whose parent is not in the intersection;
  4. repeat the pruning until stable.

And the rule that settles empty cases, quoted verbatim: “If the set is empty (no mutual version), exclude the capability from the intersection.” A capability with no common version is not an error, it simply drops out of the exchange.

That repeated pruning loop deserves an implementation team’s attention. Removing a base capability can cascade through every extension depending on it, including ones assumed to be independent.

Error codes, and their double translation

Every error carries a stable code, translated differently per transport. This is the most operational part of the document, and the part to wire into merchant-side monitoring.

Code REST MCP
invalid_profile_url 400 -32001
profile_unreachable 424 -32001
profile_malformed 422 -32001
version_unsupported 422 -32001
capabilities_incompatible 200 result
signature_missing 401 -32000
signature_invalid 401 -32000
key_not_found 401 -32000

Two rows are worth reading twice.

profile_unreachable returns HTTP 424, Failed Dependency. In other words, when your manifest is unreachable, the failure is not reported as a client error but as a failed dependency. Monitoring that only watches 5xx on your own domain will never see this case.

capabilities_incompatible returns HTTP 200. Incompatibility is not a transport error: the request succeeded, it is the negotiation that found nothing in common. A dashboard counting HTTP status codes will file this commercial failure under technical success. That is a blind spot to fix in monitoring before, not after, going to production.

What to settle before implementing

The manifest is not a static configuration file you drop once. It is a versioned, signed contract, negotiated at every encounter, whose failures are partly reported outside the usual HTTP channel. Three consequences for a roadmap:

  • version the manifest like code, with review, since removing a capability prunes its extensions;
  • publish and rotate signing_keys, without which the whole signed path is unusable;
  • instrument negotiation codes, not just HTTP status codes.

For upstream setup, Merchant Center prerequisites and the protocol route, see the implementation guide. For the standard and its partners, see the UCP reference page.

Sources


Back to the UCP implementation guide · All notes · Lire en français