@@ -433,7 +433,7 @@ image: assets/banner.png
Order
From purchase confirmation to delivery. Real-time webhooks power status updates, shipment tracking, and return processing across every channel.
-
Get Started
+
Get Started
@@ -609,7 +609,7 @@ image: assets/banner.png
Integrate and negotiate directly with a seller's checkout API to power native UI and workflows for your platform.
-
Get Started
+
Get Started
@@ -1109,7 +1109,7 @@ image: assets/banner.png
-
+
Experiment with the protocol and its different agent roles
diff --git a/docs/specification/ap2-mandates.md b/docs/specification/ap2-mandates.md
index e0fe34936..a6204d376 100644
--- a/docs/specification/ap2-mandates.md
+++ b/docs/specification/ap2-mandates.md
@@ -75,7 +75,7 @@ Businesses declare support by adding `dev.ucp.shopping.ap2_mandate` to their
"dev.ucp.shopping.checkout": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/checkout",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/checkout",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/checkout.json"
}
],
@@ -137,7 +137,7 @@ This extension uses the cryptographic primitives defined in the
* **Canonicalization:** JCS ([RFC 8785](https://datatracker.ietf.org/doc/html/rfc8785))
* **Key Format:** JWK ([RFC 7517](https://datatracker.ietf.org/doc/html/rfc7517))
* **Key Discovery:** `keys[]` in `/.well-known/ucp` (see
- [Key Discovery](overview.md#key-discovery))
+ [Key Discovery](overview/index.md#key-discovery))
See [Message Signatures](signatures.md) for key format and rotation.
diff --git a/docs/specification/buyer-consent.md b/docs/specification/buyer-consent.md
index 1c5e03862..9f6a5317c 100644
--- a/docs/specification/buyer-consent.md
+++ b/docs/specification/buyer-consent.md
@@ -330,8 +330,8 @@ Some consent states depend on additional buyer or checkout data. For example,
SMS marketing consent requires a buyer phone number. When the
platform confirms a consent value whose required dependency is missing,
businesses surface the gap through the standard [Checkout Status
-Lifecycle](checkout.md#checkout-status-lifecycle) and [Error
-Handling](checkout.md#error-handling) mechanisms.
+Lifecycle](shopping/checkout/index.md#checkout-status-lifecycle) and [Error
+Handling](shopping/checkout/index.md#error-handling) mechanisms.
On `create_cart`, `update_cart`, `create_checkout`, and `update_checkout`,
businesses SHOULD surface missing dependencies as `warning` messages so the
@@ -354,7 +354,7 @@ consent decisions remain valid; the warning is informational.
On `complete_checkout`, businesses MUST NOT transition the checkout to
`completed` while a confirmed consent decision has unmet data dependencies.
Missing dependencies MUST be surfaced via the standard [Error
-Handling](checkout.md#error-handling) flow.
+Handling](shopping/checkout/index.md#error-handling) flow.
## Normative requirements
diff --git a/docs/specification/identity-linking.md b/docs/specification/common/identity-linking/index.md
similarity index 98%
rename from docs/specification/identity-linking.md
rename to docs/specification/common/identity-linking/index.md
index 5cd3d3a66..13c428fec 100644
--- a/docs/specification/identity-linking.md
+++ b/docs/specification/common/identity-linking/index.md
@@ -17,7 +17,7 @@
# Identity Linking Capability
* **Capability Name:** `dev.ucp.common.identity_linking`
-* **Schema:** `https://ucp.dev/schemas/common/identity_linking.json`
+* **Schema:** `https://ucp.dev/{{ ucp_version }}/schemas/common/identity_linking.json`
## Overview
@@ -90,8 +90,8 @@ business **MAY** populate it from stored state on the response (for example,
Identity linking provides the authenticated user context for these values.
Subject to the scopes that gate the operation, a business **MAY** return the
-user's loyalty membership in `loyalty` (see [Loyalty](loyalty.md)), saved
-payment instruments in `payment.instruments[]` (see [Checkout](checkout.md)), or
+user's loyalty membership in `loyalty` (see [Loyalty](../../loyalty.md)), saved
+payment instruments in `payment.instruments[]` (see [Checkout](../../shopping/checkout/index.md)), or
buyer profile data in `buyer`.
Businesses **MUST NOT** return stored user-specific state unless the request is
@@ -412,7 +412,7 @@ namespace; its value is an array of mechanism entries.
A provider key is a reverse-domain **identifier**, not a schema-bearing entity:
it declares no `schema` URL, so the
-[Authority Binding](overview.md#authority-binding) (which binds an entity's
+[Authority Binding](../../overview/index.md#authority-binding) (which binds an entity's
`schema` URL to its namespace authority) does not apply here. A provider's trust
anchor is its `auth_url`, governed by the discovery rules below; binding
`auth_url` to the provider's namespace authority is a possible future hardening,
@@ -481,8 +481,8 @@ direct OAuth flows (always available via discovery):
"capabilities": {
"dev.ucp.common.identity_linking": [{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/specification/identity-linking",
- "schema": "https://ucp.dev/schemas/common/identity_linking.json",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/common/identity-linking/",
+ "schema": "https://ucp.dev/{{ ucp_version }}/schemas/common/identity_linking.json",
"config": {
"providers": {
"app.example.login": [
@@ -1123,8 +1123,8 @@ operations gated:
"capabilities": {
"dev.ucp.common.identity_linking": [{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/specification/identity-linking",
- "schema": "https://ucp.dev/schemas/common/identity_linking.json",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/common/identity-linking/",
+ "schema": "https://ucp.dev/{{ ucp_version }}/schemas/common/identity_linking.json",
"config": {
"scopes": {
"dev.ucp.shopping.order:read": {},
@@ -1161,8 +1161,8 @@ No guest checkout — every transaction requires an authenticated user:
"capabilities": {
"dev.ucp.common.identity_linking": [{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/specification/identity-linking",
- "schema": "https://ucp.dev/schemas/common/identity_linking.json",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/common/identity-linking/",
+ "schema": "https://ucp.dev/{{ ucp_version }}/schemas/common/identity_linking.json",
"config": {
"scopes": {
"dev.ucp.shopping.checkout:manage": {},
diff --git a/docs/specification/discount.md b/docs/specification/discount.md
index 033fc8e4c..314b8de8d 100644
--- a/docs/specification/discount.md
+++ b/docs/specification/discount.md
@@ -194,7 +194,7 @@ segment, or promotional rules:
## Eligibility Claims
Eligibility claims are buyer claims about eligible benefits (see
-[Context](checkout.md#context)) such as loyalty membership, payment instrument
+[Context](shopping/checkout/index.md#context)) such as loyalty membership, payment instrument
perks, and similar. When the discount extension is active, Businesses that
choose to accept eligibility claims **MUST** surface their effect on pricing
as provisional discounts in the `applied` array. Platforms **MUST** display
@@ -203,7 +203,7 @@ provisional discounts to the buyer.
### Discount Behavior
Platforms send buyer claims via `context.eligibility` on cart or checkout
-requests (see [Context](checkout.md#context)). When a Business recognizes a
+requests (see [Context](shopping/checkout/index.md#context)). When a Business recognizes a
claim and it affects pricing, it **MUST** surface a corresponding provisional
discount in the `discounts.applied` array. This gives the Platform structured
attribution to display to the buyer.
@@ -226,12 +226,12 @@ Discounts from accepted but unverified claims carry `provisional: true`.
Provisional discounts remain until the claim is verified, rescinded, or
replaced during the session. At checkout completion, all remaining provisional
claims **MUST** be resolved (see
-[Eligibility Verification at Completion](checkout.md#eligibility-verification-at-completion)).
+[Eligibility Verification at Completion](shopping/checkout/index.md#eligibility-verification-at-completion)).
### Example: Provisional Discount with Attribution
Using the same claim-resolution pattern described in
-[Eligibility Verification at Completion](checkout.md#eligibility-verification-at-completion),
+[Eligibility Verification at Completion](shopping/checkout/index.md#eligibility-verification-at-completion),
the discount extension provides structured attribution. The Platform claims a
store card benefit; the Business surfaces the provisional discount with full
stacking and allocation details:
diff --git a/docs/specification/embedded-protocol.md b/docs/specification/embedded-protocol.md
index d0674d5e5..c96405802 100644
--- a/docs/specification/embedded-protocol.md
+++ b/docs/specification/embedded-protocol.md
@@ -33,8 +33,8 @@ Capability-specific details — discovery, URL parameters, delegation contracts,
message payloads, and schema definitions — are defined in each capability's EP
binding specification:
-- [Checkout Capability — EP Binding](embedded-checkout.md)
-- [Cart Capability — EP Binding](embedded-cart.md)
+- [Checkout Capability — EP Binding](shopping/checkout/embedded.md)
+- [Cart Capability — EP Binding](shopping/cart/embedded.md)
## Terminology & Actors
@@ -128,7 +128,7 @@ Transport errors are protocol-level failures that prevent request processing.
These are returned as JSON-RPC `error` using standard JSON-RPC error codes and
indicate the message itself is invalid or could not be processed — not that
executed business logic produced an error outcome. See the
-[Core Specification](overview.md#error-codes) for the complete error code
+[Core Specification](overview/index.md#error-codes) for the complete error code
registry.
For example, if a request cannot be processed (unknown method, malformed
diff --git a/docs/specification/fulfillment.md b/docs/specification/fulfillment.md
index 9dfbc330c..c78a12d12 100644
--- a/docs/specification/fulfillment.md
+++ b/docs/specification/fulfillment.md
@@ -54,10 +54,10 @@ On Checkout, the `fulfillment` field contains:
## Location Context
-Base [Context](catalog/index.md#context) defines an optional `location`: a
+Base [Context](shopping/catalog/index.md#context) defines an optional `location`: a
stable, opaque [Location](glossary.md#commerce) identifier in the Business's
namespace. The field appears on Catalog requests and on Cart and Checkout
-create and update requests (see [Checkout Context](checkout.md#context)).
+create and update requests (see [Checkout Context](shopping/checkout/index.md#context)).
Fulfillment does not add or redefine the field; when the Fulfillment
extension is active, it defines the field's effects.
@@ -89,7 +89,7 @@ Precedence is scoped to what each field governs:
these fields without collapsing their roles. A Catalog response can report a
place-based method at `loc_123`. Because base Cart Context already includes
`location`, `loc_123` can travel forward as `context.location` on a Cart
-request. [Cart-to-Checkout conversion](cart.md#cart-to-checkout-conversion)
+request. [Cart-to-Checkout conversion](shopping/cart/index.md#cart-to-checkout-conversion)
initializes the Checkout from the Cart's `context`, so the Business **MAY**
use `loc_123` to generate an initial Checkout fulfillment destination. Once
the Platform sets `selected_destination_id`, that explicit selection governs.
@@ -372,15 +372,15 @@ describes another location. A Business that cannot honor the submitted
selection rejects it rather than replacing it.
When the Business cannot accept a `selected_destination_id` submitted on
-[Update Checkout](checkout.md#update-checkout) — the ID is not recognized for
+[Update Checkout](shopping/checkout/index.md#update-checkout) — the ID is not recognized for
that method, or revalidation fails — it follows the general behavior for a
rejected Update: it **MUST** leave the current Checkout unchanged and
**MUST** return that Checkout with an error Message with
`severity: "recoverable"` whose `path` selects the attempted method's
`selected_destination_id` (for example
`$.fulfillment.methods[0].selected_destination_id`). See
-[Error Handling](checkout.md#error-handling) and
-[The `path` Field](checkout.md#the-path-field).
+[Error Handling](shopping/checkout/index.md#error-handling) and
+[The `path` Field](shopping/checkout/index.md#the-path-field).
## Rendering
diff --git a/docs/specification/glossary.md b/docs/specification/glossary.md
index fa07e47df..f47164c00 100644
--- a/docs/specification/glossary.md
+++ b/docs/specification/glossary.md
@@ -41,16 +41,16 @@ acronym in each specification Markdown file spells out the full term (e.g.,
## Commerce
-| Term | Acronym | Definition |
-| :--------------------------- | :------ | :---------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **Business** | - | The entity selling goods or services. In UCP, they act as the **Merchant of Record (MoR)**, retaining financial liability and ownership of the order. |
-| **Location** | - | A physical place (e.g., store, restaurant, property, pickup point) identified by a stable, opaque string in a Business's namespace. |
-| **Increment** | - | Optional [ordering granularity](overview.md#ordering-increment) of a sale basis, a count of steps; advisory for Platform-authored quantities. |
-| **Merchant of Record** | MoR | The legal entity responsible for the sale, including financial liability and order ownership. |
-| **Payment Service Provider** | PSP | The financial infrastructure provider that processes payments, authorizations, and settlements on behalf of the business. |
-| **Platform** | - | The consumer-facing surface (AI agent, app, website) acting on behalf of the user to discover businesses and facilitate commerce. |
-| **Quantity Unit** | - | A [sale-basis descriptor](overview.md#quantities-and-units) with machine identity (`unit`, effective `scale`); excludes `display_text`/`increment`. |
-| **Step** | - | One [integer increment](overview.md#quantities-and-units) in the authoritative sale basis: `10^-scale` of `unit`. |
+| Term | Acronym | Definition |
+| :--------------------------- | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Business** | - | The entity selling goods or services. In UCP, they act as the **Merchant of Record (MoR)**, retaining financial liability and ownership of the order. |
+| **Location** | - | A physical place (e.g., store, restaurant, property, pickup point) identified by a stable, opaque string in a Business's namespace. |
+| **Increment** | - | Optional [ordering granularity](overview/index.md#ordering-increment) of a sale basis, a count of steps; advisory for Platform-authored quantities. |
+| **Merchant of Record** | MoR | The legal entity responsible for the sale, including financial liability and order ownership. |
+| **Payment Service Provider** | PSP | The financial infrastructure provider that processes payments, authorizations, and settlements on behalf of the business. |
+| **Platform** | - | The consumer-facing surface (AI agent, app, website) acting on behalf of the user to discover businesses and facilitate commerce. |
+| **Quantity Unit** | - | A [sale-basis descriptor](overview/index.md#quantities-and-units) with machine identity (`unit`, effective `scale`); excludes `display_text`/`increment`. |
+| **Step** | - | One [integer increment](overview/index.md#quantities-and-units) in the authoritative sale basis: `10^-scale` of `unit`. |
## Payments
diff --git a/docs/specification/loyalty.md b/docs/specification/loyalty.md
index 770503cf9..142eed4a4 100644
--- a/docs/specification/loyalty.md
+++ b/docs/specification/loyalty.md
@@ -110,28 +110,28 @@ extended.
"dev.ucp.shopping.catalog.search": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/catalog/search",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/catalog/search",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/catalog_search.json"
}
],
"dev.ucp.shopping.catalog.lookup": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/catalog/lookup",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/catalog/lookup",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/catalog_lookup.json"
}
],
"dev.ucp.shopping.cart": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/cart",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/cart",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/cart.json"
}
],
"dev.ucp.shopping.checkout": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/checkout",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/checkout",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/checkout.json"
}
],
@@ -219,7 +219,7 @@ explicit eligibility claim. In this case, the map key MUST be the same reverse-d
identifier the business would accept as a claim value. This is a specific instance of
the general pattern where identity linking lets a business return its own user state on a
response; see
-[Business-Populated Response Values](identity-linking.md#business-populated-response-values).
+[Business-Populated Response Values](common/identity-linking/index.md#business-populated-response-values).
* When a business verifies a membership claim or determines membership from
authenticated identity, it MUST return `provisional: false`. It MUST populate the
@@ -237,7 +237,7 @@ response; see
and proceed through checkout without loyalty benefits applied.
At checkout completion, all accepted but unverified loyalty claims MUST be resolved per
-the [Eligibility Verification at Completion](checkout.md#eligibility-verification-at-completion)
+the [Eligibility Verification at Completion](shopping/checkout/index.md#eligibility-verification-at-completion)
contract defined in the checkout capability.
### Monetary loyalty benefits
@@ -279,7 +279,7 @@ complete cart and checkout responses also include base required fields such as `
`id`, `currency`, and `totals`.
Building on the store loyalty card example from
-[Eligibility Verification at Completion](checkout.md#eligibility-verification-at-completion),
+[Eligibility Verification at Completion](shopping/checkout/index.md#eligibility-verification-at-completion),
assume the card offers one unconditional product discount and one conditional discount
that the current checkout cart fails to satisfy. The platform can surface the first
provisional discount with disclaimers like "verified at purchase" and additionally show
diff --git a/docs/specification/overview.md b/docs/specification/overview/index.md
similarity index 98%
rename from docs/specification/overview.md
rename to docs/specification/overview/index.md
index cd477679c..041f53473 100644
--- a/docs/specification/overview.md
+++ b/docs/specification/overview/index.md
@@ -69,7 +69,7 @@ language, and UCP therefore defines no rounding tolerances and no epsilon
comparisons anywhere in the quantity lifecycle. A fulfilled quantity that
legitimately differs from the ordered quantity — a 1.90 lb pick against a
2.00 lb order — is a commercial fact reconciled through
-[adjustments](order.md#adjustments) that move money together with quantity,
+[adjustments](../shopping/order/index.md#adjustments) that move money together with quantity,
not a numeric error absorbed by comparison fuzz.
Reading a quantity requires no arithmetic and no unit knowledge: shift the
@@ -91,7 +91,7 @@ values
Section 6) and within which
[JCS](https://www.rfc-editor.org/rfc/rfc8785.html){ target="_blank" }
canonicalization, required for
-[AP2 mandate signing](ap2-mandates.md#canonicalization), is defined. The
+[AP2 mandate signing](../ap2-mandates.md#canonicalization), is defined. The
same cap derives `scale`'s maximum of 15: at scale 16, one whole unit
(10^16 steps) would be unrepresentable. An out-of-range value is
schema-invalid and is rejected like any other invalid payload.
@@ -548,9 +548,9 @@ when its specification explicitly adopts it and defines the parent-specific
behavior: where Actions appear, the effect each Action type gates, how Messages
apply, and how a later response reflects processing. Schema composition alone
does not establish support. Cart, Checkout, and Catalog adopt this shape; see
-[Cart — Actions](cart.md#actions),
-[Checkout — Actions](checkout.md#actions), and
-[Catalog — Actions](catalog/index.md#actions) for their parent-specific
+[Cart — Actions](../shopping/cart/index.md#actions),
+[Checkout — Actions](../shopping/checkout/index.md#actions), and
+[Catalog — Actions](../shopping/catalog/index.md#actions) for their parent-specific
contracts.
Actions and Messages have different roles. An Action represents outstanding
@@ -593,7 +593,7 @@ explanatory Message (an illustrative, partial fragment):
The Action identifies the outstanding work and carries extension-owned
processing configuration under `config`. The Message's `path` selects the exact
Action occurrence it explains. The
-[checkout eligibility example](checkout.md#eligibility-verification-at-completion)
+[checkout eligibility example](../shopping/checkout/index.md#eligibility-verification-at-completion)
composes this pattern into a complete Student Verification flow.
For a newly processed successful response from a capability that adopts Actions,
@@ -603,7 +603,7 @@ the Business **MUST** include every outstanding Action and **MUST** omit
Cart and Checkout define request idempotency separately. Duplicate requests
follow those existing rules and can return the original cached response,
including its `actions` (see
-[Message Signatures — Replay Protection](signatures.md#replay-protection)).
+[Message Signatures — Replay Protection](../signatures.md#replay-protection)).
An Action's gate and an operation-specific outcome are orthogonal. Neither a
parent status nor a Message's type or severity determines whether an Action
@@ -624,7 +624,7 @@ contract.
When an Action prevents a Cart or Checkout operation from succeeding,
processing the Action does not repeat that operation. If the Platform wants to
try again, it submits a new operation under the existing
-[Replay Protection](signatures.md#replay-protection) rules.
+[Replay Protection](../signatures.md#replay-protection) rules.
Each Action key is a reverse-domain **Action type**: the name identifies the
type of outstanding work, which is not necessarily the name of the extension
@@ -641,7 +641,7 @@ Action type keys follow existing [Namespace Governance](#namespace-governance)
rules: an extension can declare only types within a reverse-domain namespace
controlled by its schema authority. An extension can use its own name as the key
for a single Action type — as the
-[Student Verification example](checkout.md#eligibility-verification-at-completion)
+[Student Verification example](../shopping/checkout/index.md#eligibility-verification-at-completion)
does — or declare several Action types under distinct keys. Each value is a
non-empty array of outstanding instances of that one Action type. The key
identifies the type, so an instance carries no separate type discriminator; a
@@ -964,7 +964,7 @@ functionality is supported and where to find documentation and schemas.
#### Capability Definition
-{{ extension_schema_fields('capability.json#/$defs/platform_schema', 'capability-schema') }}
+{{ extension_schema_fields('capability.json#/$defs/platform_schema', 'overview') }}
#### Extensions
@@ -1195,7 +1195,7 @@ effectively revoked until it is absent from `keys[]`.
UCP defines two well-known key types: **EC** (ECDSA P-256, P-384) and
**OKP** (EdDSA Ed25519); the key-type, curve, and algorithm
vocabularies are open and verifiers skip keys they do not recognize.
-See [Message Signatures](signatures.md) for key format, algorithms,
+See [Message Signatures](../signatures.md) for key format, algorithms,
lookup, and rotation.
#### Business Profile
@@ -1211,27 +1211,27 @@ Businesses publish their profile at `/.well-known/ucp`. An example:
"dev.ucp.shopping": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/overview",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/overview/",
"transport": "rest",
"endpoint": "https://business.example.com/ucp/v1",
"schema": "https://ucp.dev/{{ ucp_version }}/services/shopping/rest.openapi.json"
},
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/overview",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/overview/",
"transport": "mcp",
"endpoint": "https://business.example.com/ucp/mcp",
"schema": "https://ucp.dev/{{ ucp_version }}/services/shopping/mcp.openrpc.json"
},
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/overview",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/overview/",
"transport": "a2a",
"endpoint": "https://business.example.com/.well-known/agent-card.json"
},
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/overview",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/overview/",
"transport": "embedded",
"schema": "https://ucp.dev/{{ ucp_version }}/services/shopping/embedded.openrpc.json"
}
@@ -1241,7 +1241,7 @@ Businesses publish their profile at `/.well-known/ucp`. An example:
"dev.ucp.shopping.checkout": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/checkout",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/checkout",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/checkout.json"
}
],
@@ -1264,7 +1264,7 @@ Businesses publish their profile at `/.well-known/ucp`. An example:
"dev.ucp.common.identity_linking": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/identity-linking",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/common/identity-linking/",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/common/identity_linking.json",
"config": {
"providers": {
@@ -1348,7 +1348,7 @@ it will not read `keys[]` from a static `/.well-known/ucp`. See
This example uses two keys. Whether a deployment needs one or two depends
on the algorithms its counterparties accept — many need only one; see
-[Signature Algorithms](signatures.md#signature-algorithms). The two keys
+[Signature Algorithms](../signatures.md#signature-algorithms). The two keys
here:
- An **Ed25519** key (OKP) for HTTP transport identity, WBA-compatible.
@@ -1360,7 +1360,7 @@ A business that does not interact with AP2 or WBA may publish a single
ES256 key in `keys[]` (the universal baseline). See
[Key Discovery](#key-discovery) for key lookup and resolution,
[Deployment Patterns for WBA Interop](#deployment-patterns-for-wba-interop)
-for hosting choices, and [Message Signatures](signatures.md) for
+for hosting choices, and [Message Signatures](../signatures.md) for
signing mechanics.
Businesses that support older protocol versions **SHOULD** include a
@@ -1384,7 +1384,7 @@ example:
"dev.ucp.shopping": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/overview",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/overview/",
"transport": "rest",
"schema": "https://ucp.dev/{{ ucp_version }}/services/shopping/rest.openapi.json",
"endpoint": "https://platform.example.com/ucp/v1"
@@ -1395,7 +1395,7 @@ example:
"dev.ucp.shopping.checkout": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/checkout",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/checkout",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/checkout.json"
}
],
@@ -1410,7 +1410,7 @@ example:
"dev.ucp.shopping.order": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/order",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/order",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/order.json",
"config": {
"webhook_url": "https://platform.example.com/webhooks/ucp/orders"
@@ -1420,7 +1420,7 @@ example:
"dev.ucp.common.identity_linking": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/identity-linking",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/common/identity-linking/",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/common/identity_linking.json"
}
]
@@ -1791,7 +1791,7 @@ the result in the UCP response:
| `digest_mismatch` | Body digest doesn't match `Content-Digest` header | 400 | -32600 |
| `algorithm_unsupported`| Signature algorithm not supported | 400 | -32600 |
-See [Message Signatures](signatures.md) for signature verification details.
+See [Message Signatures](../signatures.md) for signature verification details.
**Protocol Errors:**
@@ -1812,7 +1812,7 @@ responses.
The Embedded Protocol uses the same JSON-RPC error codes for peer-to-peer
communication between host and embedded context. Server-specific scenarios
(rate limiting, idempotency) do not apply to the embedded transport. See
-[Embedded Protocol — Response Handling](embedded-protocol.md#response-handling)
+[Embedded Protocol — Response Handling](../embedded-protocol.md#response-handling)
for the full error handling specification.
##### The `continue_url` Field
@@ -2084,7 +2084,7 @@ can interact with any business without prior registration.
additionally emit a `Signature-Agent` header advertising their keys. See
[Identity Resolution Algorithm](#identity-resolution-algorithm) for how
verifiers resolve identity and
-[Message Signatures — WBA Interop](signatures.md#wba-interop) for the
+[Message Signatures — WBA Interop](../signatures.md#wba-interop) for the
signature shape.
### Authentication Mechanisms
@@ -2097,7 +2097,7 @@ message integrity. UCP is compatible with multiple authentication mechanisms:
- **mTLS** — Mutual TLS with client certificates
- **HTTP Message Signatures** — Cryptographic signatures per
[RFC 9421](https://www.rfc-editor.org/rfc/rfc9421) (see
- [Message Signatures](signatures.md) for full specification)
+ [Message Signatures](../signatures.md) for full specification)
HTTP Message Signatures enable permissionless onboarding — businesses can
verify platforms by their advertised public keys without negotiating shared
@@ -2105,7 +2105,7 @@ secrets. The other mechanisms require prior credential exchange and imply a
pre-established relationship.
Business-to-platform webhooks **MUST** be signed. See
-[Message Signatures — When Signatures Apply](signatures.md#when-signatures-apply).
+[Message Signatures — When Signatures Apply](../signatures.md#when-signatures-apply).
#### Identity Binding
@@ -2144,7 +2144,7 @@ profile fetching, and covered-component enforcement — see
[Identity Resolution Algorithm](#identity-resolution-algorithm) below.
For key format (JWK), supported algorithms, key rotation procedures,
and the Web Bot Auth interop signature shape, see
-[Message Signatures](signatures.md).
+[Message Signatures](../signatures.md).
### Profile Requirements
@@ -2302,7 +2302,7 @@ below processes a single signature.
need not implement Web Bot Auth key discovery. (Verifying a
dual-audience signature does still require supporting the key's
algorithm — whichever the signer used, per
- [Signature Algorithms](signatures.md#signature-algorithms) — and
+ [Signature Algorithms](../signatures.md#signature-algorithms) — and
RFC 9421 §2.1.2 Dictionary-member component selection to cover
`signature-agent;key=""`.) Signatures with tags
other than `web-bot-auth` are skipped unless UCP defines
@@ -2311,11 +2311,11 @@ below processes a single signature.
(WBA-aware verifiers).** For a signature carrying
`tag="web-bot-auth"`, a WBA-aware verifier **MAY** instead resolve
via the `Signature-Agent` member, parsed per the
- [Signature-Agent parsing rules](signatures.md#rest-request-verification).
+ [Signature-Agent parsing rules](../signatures.md#rest-request-verification).
Such a signature **MUST** satisfy the WBA agent-signature
requirements in
[draft-meunier-webbotauth-httpsig-protocol-00](https://datatracker.ietf.org/doc/draft-meunier-webbotauth-httpsig-protocol/00/)
- §4.2 (see [WBA Interop](signatures.md#wba-interop) for the
+ §4.2 (see [WBA Interop](../signatures.md#wba-interop) for the
signer-side shape). The member value **MUST** be an HTTPS URL.
Its `type` selects resolution: `jwks_uri` and `cimd` reach the
keys through the signer's profile and are resolved by the steps
@@ -2389,7 +2389,7 @@ either suffices.
This rule governs **HTTP transport identity**. Payload-layer
assertions (e.g., AP2 mandate JWTs carried in the request body) have
their own identity binding and key-resolution rules; see
-[AP2 Mandates](ap2-mandates.md).
+[AP2 Mandates](../ap2-mandates.md).
## Payment Architecture
@@ -2420,7 +2420,7 @@ autonomous AI agents), UCP supports the **AP2 Mandates Extension**
non-repudiable authorization through verifiable digital credentials.
See [Transaction Integrity](#transaction-integrity-and-non-repudiation)
-and [AP2 Mandates Extension](ap2-mandates.md) for details on when and how to
+and [AP2 Mandates Extension](../ap2-mandates.md) for details on when and how to
use this extension.
#### Credential Flow & PCI Scope
@@ -2494,14 +2494,14 @@ response. The platform's declaration (from its profile) signals what it can
handle; the business intersects that with its own `business_schema` declaration
and cart context, then returns the resolved result. Platforms **MUST** treat the
`available_instruments` in the response as authoritative for that checkout. See
-the [Payment Handler Guide](payment-handler-guide.md#resolving-available_instruments)
+the [Payment Handler Guide](../payment/guide.md#resolving-available_instruments)
for the full resolution semantics.
**Instrument Cardinality:** A checkout submission **MUST** contain exactly one
payment instrument unless the `dev.ucp.shopping.split_payments` capability is
active. Businesses **MUST** reject submissions that violate this constraint with
a `payment_failed` error in `messages[]`. See
-[Split Payments](split-payments.md) for the extension that relaxes this
+[Split Payments](../payment/split-payments.md) for the extension that relaxes this
constraint.
### Implementation Scenarios
@@ -2820,7 +2820,7 @@ certified and handle:
5. Set appropriate credential timeouts
6. For autonomous commerce scenarios requiring cryptographic proof, consider
supporting the `dev.ucp.shopping.ap2_mandate` extension (see
- [AP2 Mandates Extension](ap2-mandates.md))
+ [AP2 Mandates Extension](../ap2-mandates.md))
**For Platforms:**
@@ -2831,7 +2831,7 @@ certified and handle:
5. Handle credential expiration gracefully (re-acquire if needed)
6. For autonomous agents, consider using the `dev.ucp.shopping.ap2_mandate`
extension for cryptographic proof of authorization (see
- [AP2 Mandates Extension](ap2-mandates.md))
+ [AP2 Mandates Extension](../ap2-mandates.md))
**For Payment Credential Providers:**
@@ -2866,11 +2866,11 @@ use cases:
- **AP2 Mandates Extension** (`dev.ucp.shopping.ap2_mandate`): Adds
cryptographic proof of user authorization for autonomous commerce scenarios
where non-repudiable evidence is required. See
- [AP2 Mandates Extension](ap2-mandates.md).
+ [AP2 Mandates Extension](../ap2-mandates.md).
- **Custom Handler Types**: Payment credential providers can define custom
handlers to support new payment instruments. See
- [Payment Handler Guide](payment-handler-guide.md) for details.
+ [Payment Handler Guide](../payment/guide.md) for details.
The extension model ensures the core architecture remains simple while
supporting advanced security and compliance requirements when needed.
@@ -3095,7 +3095,7 @@ item, a regulatory notice — it **MUST** emit a `messages[]` warning that:
- sets `presentation: "disclosure"`, so the Platform displays the content and
cannot hide or dismiss it (see
- [Warning Presentation](checkout.md#warning-presentation));
+ [Warning Presentation](../shopping/checkout/index.md#warning-presentation));
- sets `path` to the item the notice concerns; and
- sets `code` to the policy's `type`, linking the notice to its policy.
@@ -3333,7 +3333,7 @@ This mechanism provides strong, end-to-end cryptographic assurances about
transaction details and participant consent, significantly reducing risks of
tampering and disputes.
-See [AP2 Mandates Extension](ap2-mandates.md) for complete specification,
+See [AP2 Mandates Extension](../ap2-mandates.md) for complete specification,
implementation guide, and examples.
## Versioning
@@ -3657,4 +3657,4 @@ versions.
## Glossary
-For definitions of acronyms and terms used throughout the UCP specification, see the [Glossary](glossary.md).
+For definitions of acronyms and terms used throughout the UCP specification, see the [Glossary](../glossary.md).
diff --git a/docs/specification/payment-terms.md b/docs/specification/payment-terms.md
index b8365ba54..1b9c0bda6 100644
--- a/docs/specification/payment-terms.md
+++ b/docs/specification/payment-terms.md
@@ -194,7 +194,7 @@ charged immediately therefore cannot be offered on a term that defers any part
of the payment.
A term with more than one schedule **MUST** be funded by a single instrument.
-[Split Payments](split-payments.md) composes with a term that has exactly one
+[Split Payments](payment/split-payments.md) composes with a term that has exactly one
schedule, and not otherwise.
## Disclosures
@@ -206,7 +206,7 @@ consumer-protection rules about what must be shown, and when.
This extension does not define a private disclosure channel. It uses the two
that already exist:
-1. A [policy](overview.md#policies) carries the durable terms text, targeted
+1. A [policy](overview/index.md#policies) carries the durable terms text, targeted
with `applies_to` at the node the terms concern — the payment term when the
terms are about payment timing, the line item when they are about the goods.
2. A `messages[]` warning with `presentation: "disclosure"` and `code` set to
@@ -219,7 +219,7 @@ optional for a Platform, so any content that **must** reach the Buyer belongs in
the warning `content`, not only in the policy `description`.
Disclosure display is unconditional. Under [Warning
-Presentation](checkout.md#warning-presentation) a Platform **MUST** display
+Presentation](shopping/checkout/index.md#warning-presentation) a Platform **MUST** display
every returned disclosure, **MUST** keep it in proximity to the node named by
`path`, and **MUST NOT** hide, collapse, or auto-dismiss it. A Platform that
cannot honor that contract — for example one that collapses a list of terms and
@@ -631,7 +631,7 @@ Platforms **MUST**:
* Treat an unrecognized schedule `type` as not due at completion, and present
the term regardless.
* Process disclosures attached to terms per
- [Warning Presentation](checkout.md#warning-presentation), escalating through
+ [Warning Presentation](shopping/checkout/index.md#warning-presentation), escalating through
`continue_url` when the rendering contract cannot be honored.
Platforms **MAY** use `type` and `due_at` for enhanced presentation — calendar
diff --git a/docs/specification/payment-actions/device-data-collection.md b/docs/specification/payment/actions/device-data-collection.md
similarity index 92%
rename from docs/specification/payment-actions/device-data-collection.md
rename to docs/specification/payment/actions/device-data-collection.md
index e53e65469..bb8b39b50 100644
--- a/docs/specification/payment-actions/device-data-collection.md
+++ b/docs/specification/payment/actions/device-data-collection.md
@@ -17,7 +17,7 @@
# Payment Device Data Collection Action
This specification defines the device data collection Action type declared by
-the [Payment Authentication extension](../payment-authentication.md):
+the [Payment Authentication extension](../authentication.md):
```text
dev.ucp.payment.device_data_collection
@@ -99,8 +99,8 @@ The Platform **MUST**:
timeout.
Mounting the surface **MUST** follow the shared
-[Payment Authentication rendering contract](../payment-authentication.md#surface-rendering-and-notifications)
-and [Embedded Protocol security requirements](../embedded-protocol.md#security).
+[Payment Authentication rendering contract](../authentication.md#surface-rendering-and-notifications)
+and [Embedded Protocol security requirements](../../embedded-protocol.md#security).
On the web the surface is typically a hidden iframe. A native Platform may use
an isolated webview or equivalent browser surface. It **MUST NOT** be visible to
@@ -113,9 +113,9 @@ whether an ACS method timed out, or whether 3DS authentication should proceed.
## Embedded Notifications
After completing the shared
-[`action.ready` handshake](../payment-authentication.md#ready-handshake), the
+[`action.ready` handshake](../authentication.md#ready-handshake), the
surface sends JSON-RPC 2.0 notifications defined by the
-[payment Action embedded contract](../payment-authentication.md#surface-rendering-and-notifications).
+[payment Action embedded contract](../authentication.md#surface-rendering-and-notifications).
### Done
@@ -164,7 +164,7 @@ it **MAY** send:
```
Surface-level codes are the shared
-[well-known `action.error` codes](../payment-authentication.md#surface-rendering-and-notifications).
+[well-known `action.error` codes](../authentication.md#surface-rendering-and-notifications).
They are not EMV 3DS or payment outcomes: a provider-domain timeout or
unavailable method that the handler can safely continue past should normally
result in `action.done`, with the Business and provider recording the domain
@@ -193,7 +193,7 @@ parent Checkout Actions fallback, handoff, and cancellation rules.
## Security
-The common [Payment Authentication security requirements](../payment-authentication.md#security-and-data-handling)
+The common [Payment Authentication security requirements](../authentication.md#security-and-data-handling)
apply. In addition:
- The handler's trust policy **MUST** authorize the initial and redirect origins
diff --git a/docs/specification/payment-actions/three-ds-challenge.md b/docs/specification/payment/actions/three-ds-challenge.md
similarity index 93%
rename from docs/specification/payment-actions/three-ds-challenge.md
rename to docs/specification/payment/actions/three-ds-challenge.md
index 7f3025197..979c8cc78 100644
--- a/docs/specification/payment-actions/three-ds-challenge.md
+++ b/docs/specification/payment/actions/three-ds-challenge.md
@@ -17,7 +17,7 @@
# Payment 3DS Challenge Action
This specification defines the 3DS challenge Action type declared by the
-[Payment Authentication extension](../payment-authentication.md):
+[Payment Authentication extension](../authentication.md):
```text
dev.ucp.payment.three_ds_challenge
@@ -101,8 +101,8 @@ The Platform **MUST**:
failure, or abandonment.
Mounting the surface **MUST** follow the shared
-[Payment Authentication rendering contract](../payment-authentication.md#surface-rendering-and-notifications)
-and [Embedded Protocol security requirements](../embedded-protocol.md#security).
+[Payment Authentication rendering contract](../authentication.md#surface-rendering-and-notifications)
+and [Embedded Protocol security requirements](../../embedded-protocol.md#security).
On the web the surface may be a full-page frame, modal frame, or separate window
when the negotiated handler defines that presentation and its security policy.
@@ -117,9 +117,9 @@ URL changes, or notification diagnostics.
## Embedded Notifications
After completing the shared
-[`action.ready` handshake](../payment-authentication.md#ready-handshake), the
+[`action.ready` handshake](../authentication.md#ready-handshake), the
surface sends JSON-RPC 2.0 notifications defined by the
-[payment Action embedded contract](../payment-authentication.md#surface-rendering-and-notifications).
+[payment Action embedded contract](../authentication.md#surface-rendering-and-notifications).
### Done
@@ -177,7 +177,7 @@ If the surface cannot continue, it **MAY** send:
```
Surface-level codes are the shared
-[well-known `action.error` codes](../payment-authentication.md#surface-rendering-and-notifications).
+[well-known `action.error` codes](../authentication.md#surface-rendering-and-notifications).
Buyer abandonment and provider authentication outcomes may be unavailable to the
surface or known only by the provider backend; the Business and payment provider
remain authoritative for those distinctions. After either notification, the
@@ -221,7 +221,7 @@ fallback, handoff, and cancellation rules.
## Security
-The common [Payment Authentication security requirements](../payment-authentication.md#security-and-data-handling)
+The common [Payment Authentication security requirements](../authentication.md#security-and-data-handling)
apply. In addition:
- The handler's trust policy **MUST** authorize the initial and redirect origins
diff --git a/docs/specification/payment-authentication.md b/docs/specification/payment/authentication.md
similarity index 96%
rename from docs/specification/payment-authentication.md
rename to docs/specification/payment/authentication.md
index a2bae9bc1..91980be9d 100644
--- a/docs/specification/payment-authentication.md
+++ b/docs/specification/payment/authentication.md
@@ -20,7 +20,7 @@
The Payment Authentication extension defines browser-surface interactions that
a Platform may need to process while a payment attempt is underway. It declares
-two concrete [Action types](overview.md#actions):
+two concrete [Action types](../overview/index.md#actions):
| Action type | Platform interaction |
| :---------- | :------------------- |
@@ -57,7 +57,7 @@ Businesses and Platforms advertise this extension in their profiles:
{
"version": "{{ ucp_version }}",
"extends": "dev.ucp.shopping.checkout",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/payment-authentication",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/payment/authentication/",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/payment_authentication.json"
}
]
@@ -154,7 +154,7 @@ association cannot be resolved unambiguously.
## Checkout Lifecycle
These Action types use the parent Checkout lifecycle defined in
-[Checkout — Actions](checkout.md#actions):
+[Checkout — Actions](../shopping/checkout/index.md#actions):
- Every emitted Payment Authentication Action gates advancement of its associated
payment attempt while the same Action type and `id` remain outstanding in the
@@ -222,8 +222,8 @@ for instruments that are no longer present in the Checkout.
The individual Action specifications define type-specific timeout and fallback
behavior:
-- [Payment Device Data Collection](payment-actions/device-data-collection.md)
-- [Payment 3DS Challenge](payment-actions/three-ds-challenge.md)
+- [Payment Device Data Collection](actions/device-data-collection.md)
+- [Payment 3DS Challenge](actions/three-ds-challenge.md)
## Surface Rendering and Notifications
@@ -238,7 +238,7 @@ before navigating so an immediately completing surface cannot race
initialization.
The `postMessage` and native-webview mechanics follow
-[Embedded Protocol — Communication Channels](embedded-protocol.md#communication-channels).
+[Embedded Protocol — Communication Channels](../embedded-protocol.md#communication-channels).
Payment Authentication uses the Action methods below. It does not use a
capability-specific Embedded Protocol `ready` method or `MessageChannel` upgrade;
`action.ready` is its scoped handshake.
@@ -333,9 +333,9 @@ reconciliation path above.
## Security and Data Handling
Web Platforms **MUST** follow the shared
-[Embedded Protocol security requirements](embedded-protocol.md#security) for
+[Embedded Protocol security requirements](../embedded-protocol.md#security) for
CSP, iframe sandboxing, credentialless iframe evaluation, and strict origin
-validation. [Embedded Checkout security](embedded-checkout.md#security-for-web-based-hosts)
+validation. [Embedded Checkout security](../shopping/checkout/embedded.md#security-for-web-based-hosts)
shows how a UCP capability applies those requirements. Payment Authentication
uses its own `action.ready` handshake and terminal notification methods; it does
not adopt the Embedded Protocol's capability lifecycle or delegation messages.
diff --git a/docs/specification/examples/encrypted-credential-handler.md b/docs/specification/payment/examples/encrypted-credential-payment-handler.md
similarity index 100%
rename from docs/specification/examples/encrypted-credential-handler.md
rename to docs/specification/payment/examples/encrypted-credential-payment-handler.md
diff --git a/docs/specification/examples/platform-tokenizer-payment-handler.md b/docs/specification/payment/examples/platform-tokenizer-payment-handler.md
similarity index 99%
rename from docs/specification/examples/platform-tokenizer-payment-handler.md
rename to docs/specification/payment/examples/platform-tokenizer-payment-handler.md
index 73e48a71d..67a1aa751 100644
--- a/docs/specification/examples/platform-tokenizer-payment-handler.md
+++ b/docs/specification/payment/examples/platform-tokenizer-payment-handler.md
@@ -413,7 +413,7 @@ Content-Type: application/json
## Runtime Payment Authentication Actions
This handler supports both Action types from the negotiated
-[Payment Authentication extension](../payment-authentication.md):
+[Payment Authentication extension](../authentication.md):
| Action type | Use |
| :---------- | :-- |
@@ -514,6 +514,6 @@ The platform's payment credential provider verifies that:
## References
-* **Pattern:** [Tokenization Payment Handler](../payment-handler-guide.md)
+* **Pattern:** [Tokenization Payment Handler](../guide.md)
* **API Pattern:** [handlers/tokenization/openapi.json](site:handlers/tokenization/openapi.json)
* **Identity Schema:** [schemas/shopping/types/payment_identity.json](site:schemas/shopping/types/payment_identity.json)
diff --git a/docs/specification/examples/processor-tokenizer-payment-handler.md b/docs/specification/payment/examples/processor-tokenizer-payment-handler.md
similarity index 100%
rename from docs/specification/examples/processor-tokenizer-payment-handler.md
rename to docs/specification/payment/examples/processor-tokenizer-payment-handler.md
diff --git a/docs/specification/payment-handler-guide.md b/docs/specification/payment/guide.md
similarity index 98%
rename from docs/specification/payment-handler-guide.md
rename to docs/specification/payment/guide.md
index 1843f2b0e..0aaaecbb0 100644
--- a/docs/specification/payment-handler-guide.md
+++ b/docs/specification/payment/guide.md
@@ -201,7 +201,7 @@ instruments. The path matches the containing handler's `id`
to submitted `handler_id` and the available instrument's `type` to submitted
`type`, and applies when the next request contains matching instruments.
Payment-handler and instrument specifications define any stronger association
-the query needs. See [Request Constraints](overview.md#request-constraints).
+the query needs. See [Request Constraints](../overview/index.md#request-constraints).
---
@@ -744,7 +744,7 @@ Handler authors have two options:
- **Use the standard Payment Authentication extension.** Handlers that need
device data collection or a 3DS challenge use
- [`dev.ucp.shopping.payment_authentication`](payment-authentication.md), which
+ [`dev.ucp.shopping.payment_authentication`](authentication.md), which
defines the `dev.ucp.payment.device_data_collection` and
`dev.ucp.payment.three_ds_challenge` Action types. The handler specification
states which types it can cause and any provider-specific trust or fallback
@@ -759,7 +759,7 @@ its type gates, how the Platform processes its config, how the Business observes
its completion, whether processing the same occurrence is ever safe to retry,
and its trust, failure, abandonment, and fallback behavior.
-See [Overview — Actions](overview.md#actions) for the common envelope and
+See [Overview — Actions](../overview/index.md#actions) for the common envelope and
[Schema Authoring — Extension-Declared Action Types](site:documentation/schema-authoring.html)
for the extension schema pattern.
@@ -808,7 +808,7 @@ Handler specifications **SHOULD** use the standard template structure. Sections
marked **[REQUIRED]** **MUST** be present; sections marked **[CONDITIONAL]**
are required only when applicable.
-**→ [Payment Handler Template](payment-handler-template.md)**
+**→ [Payment Handler Template](template.md)**
## Conformance Checklist for Spec Authors
@@ -915,13 +915,13 @@ specifications:
| :------------------------------ | :----------------------------------------------------------------------------------------------------- |
| **Host schemas at stable URLs** | Schema URLs should not change; use versioned paths if needed. |
| **Fail gracefully** | Define clear error responses for common failure scenarios. |
-| **Link to examples** | Reference existing handler specs and the [Tokenization Guide](tokenization-guide.md) for common flows. |
+| **Link to examples** | Reference existing handler specs and the [Tokenization Guide](tokenization.md) for common flows. |
---
## See Also
-- **[Tokenization Guide](tokenization-guide.md)** — Guide for building
+- **[Tokenization Guide](tokenization.md)** — Guide for building
tokenization payment handlers
- **[Google Pay Handler](https://developers.google.com/merchant/ucp/guides/google-pay-payment-handler){ target="_blank" }**
— Handler for Google Pay integration
diff --git a/docs/specification/split-payments.md b/docs/specification/payment/split-payments.md
similarity index 98%
rename from docs/specification/split-payments.md
rename to docs/specification/payment/split-payments.md
index 86e948139..5598c3b97 100644
--- a/docs/specification/split-payments.md
+++ b/docs/specification/payment/split-payments.md
@@ -67,7 +67,7 @@ allocation, not processing sequence.
When this capability is active, each payment instrument in
`checkout.payment.instruments` gains an optional `amount` field.
-{{ extension_schema_fields('split_payments.json#/$defs/payment_instrument', 'split_payments') }}
+{{ extension_schema_fields('split_payments.json#/$defs/payment_instrument', 'payment/split-payments') }}
## Configuration
@@ -75,7 +75,7 @@ Businesses declare split payments configuration in their profile.
### Business Profile
-{{ schema_fields('types/business_split_payments_config', 'split_payments') }}
+{{ schema_fields('types/business_split_payments_config', 'payment/split-payments') }}
#### `allowed_combinations`
@@ -90,7 +90,7 @@ A set of instruments is valid if it matches **any** combination in the array.
Each group within a combination defines a "slot" that accepts certain
instrument types:
-{{ schema_fields('types/instrument_group', 'split_payments') }}
+{{ schema_fields('types/instrument_group', 'payment/split-payments') }}
**Matching algorithm:** a submission matches a combination if there exists
an assignment of each submitted instrument to exactly one group such that
@@ -175,7 +175,7 @@ reference to prior requests or responses.
> [!NOTE]
> Each split payments submission is processed as a complete,
> self-contained request: a modified instrument set is a new submission,
-> requiring a fresh [idempotency key](signatures.md#replay-protection).
+> requiring a fresh [idempotency key](../signatures.md#replay-protection).
> Split-payments state — including authorizations — does not persist
> between submissions; the unwind-on-failure requirement above
> enforces this.
diff --git a/docs/specification/payment-handler-template.md b/docs/specification/payment/template.md
similarity index 98%
rename from docs/specification/payment-handler-template.md
rename to docs/specification/payment/template.md
index 7aa045304..eaea89ccb 100644
--- a/docs/specification/payment-handler-template.md
+++ b/docs/specification/payment/template.md
@@ -110,7 +110,7 @@ Businesses advertise support for this handler in their UCP profile's
**Schema URL:** `{schema_url}`
The handler schema defines three config variants for different contexts. See
-[Payment Handler Guide: Defining the Schema](payment-handler-guide.md#defining-the-schema)
+[Payment Handler Guide: Defining the Schema](guide.md#defining-the-schema)
for the full pattern.
| Config Variant | Context | Purpose |
@@ -319,7 +319,7 @@ Content-Type: application/json
{Include this section if the handler can cause Actions. Identify the negotiated
Checkout extension that declares them. Use the standard
-[Payment Authentication extension](payment-authentication.md) for device data
+[Payment Authentication extension](authentication.md) for device data
collection and 3DS challenges; link to the defining extension specification for
custom Actions.}
diff --git a/docs/specification/tokenization-guide.md b/docs/specification/payment/tokenization.md
similarity index 97%
rename from docs/specification/tokenization-guide.md
rename to docs/specification/payment/tokenization.md
index c1f64c217..a99f3ee40 100644
--- a/docs/specification/tokenization-guide.md
+++ b/docs/specification/payment/tokenization.md
@@ -35,7 +35,7 @@ We offer a range of examples to utilize forms of tokenization in UCP:
| :------ | :------- |
| [Processor Tokenizer](examples/processor-tokenizer-payment-handler.md) | Business or PSP runs tokenization and processing |
| [Platform Tokenizer](examples/platform-tokenizer-payment-handler.md) | Platform tokenizes credentials for businesses/PSPs |
-| [Encrypted Credential Handler](examples/encrypted-credential-handler.md) | Platform encrypts credentials instead of tokenizing |
+| [Encrypted Credential Handler](examples/encrypted-credential-payment-handler.md) | Platform encrypts credentials instead of tokenizing |
---
@@ -277,5 +277,5 @@ A tokenizer handler conforms to this pattern if it:
## See Also
-- **[Encrypted Credential Handler](examples/encrypted-credential-handler.md)** — Alternative pattern using encryption instead of tokenize/detokenize round-trips
-- **[AP2 Mandates Extension](ap2-mandates.md)** — Add cryptographic proof of checkout agreement for PSP verification
+- **[Encrypted Credential Handler](examples/encrypted-credential-payment-handler.md)** — Alternative pattern using encryption instead of tokenize/detokenize round-trips
+- **[AP2 Mandates Extension](../ap2-mandates.md)** — Add cryptographic proof of checkout agreement for PSP verification
diff --git a/docs/specification/permalink.md b/docs/specification/permalink.md
index 8b7e25245..cce4b9976 100644
--- a/docs/specification/permalink.md
+++ b/docs/specification/permalink.md
@@ -17,7 +17,7 @@
# Permalink Capability
* **Capability Name:** `dev.ucp.shopping.permalink`
-* **Schema:** `https://ucp.dev/schemas/shopping/permalink.json`
+* **Schema:** `https://ucp.dev/{{ ucp_version }}/schemas/shopping/permalink.json`
## Overview
diff --git a/docs/specification/embedded-cart.md b/docs/specification/shopping/cart/embedded.md
similarity index 95%
rename from docs/specification/embedded-cart.md
rename to docs/specification/shopping/cart/embedded.md
index 41f3790c0..2b70e9e60 100644
--- a/docs/specification/embedded-cart.md
+++ b/docs/specification/shopping/cart/embedded.md
@@ -156,7 +156,7 @@ distinguish ECaP parameters from business-specific query parameters:
## Transport & Messaging
ECaP uses the shared EP transport layer. See
-[Embedded Protocol — Transport & Messaging](embedded-protocol.md#transport-messaging)
+[Embedded Protocol — Transport & Messaging](../../embedded-protocol.md#transport-messaging)
for message format, message types, and response handling conventions.
The `ucp.version` in all responses **MUST** echo the `ep_version` negotiated
@@ -167,7 +167,7 @@ of the ECaP session.
### Communication Channels
ECaP follows the shared EP communication channel model. See
-[Embedded Protocol — Communication Channels](embedded-protocol.md#communication-channels)
+[Embedded Protocol — Communication Channels](../../embedded-protocol.md#communication-channels)
for the general pattern.
For native hosts, the cart-specific globals are:
@@ -307,7 +307,7 @@ messages after receiving a handshake error.
#### `ep.cart.auth`
`ep.cart.auth` implements the shared EP authentication pattern — see
-[Embedded Protocol — Authentication](embedded-protocol.md#authentication) for
+[Embedded Protocol — Authentication](../../embedded-protocol.md#authentication) for
the request/response contract, examples, and error escalation flow.
- **Method:** `ep.cart.auth`
@@ -315,12 +315,12 @@ the request/response contract, examples, and error escalation flow.
When error escalation is required, Embedded Cart **MUST** issue an
`ep.cart.error` notification per the
-[session error pattern](embedded-protocol.md#session-error).
+[session error pattern](../../embedded-protocol.md#session-error).
### Lifecycle Messages
Lifecycle notifications follow the shared EP pattern — see
-[Embedded Protocol — Lifecycle](embedded-protocol.md#lifecycle). All lifecycle
+[Embedded Protocol — Lifecycle](../../embedded-protocol.md#lifecycle). All lifecycle
notifications carry the full `cart` object as their payload.
#### `ep.cart.start`
@@ -361,7 +361,7 @@ transitioned to the next stage of their purchase journey.
This marks the completion of Embedded Cart. If `dev.ucp.shopping.checkout` is
part of the negotiated capabilities during service discovery, host **MAY**
proceed to initiate a checkout session based on the completed cart by issuing a
-[create checkout](checkout.md#create-checkout) operation.
+[create checkout](../checkout/index.md#create-checkout) operation.
- **Direction:** Embedded Cart → Host
- **Type:** Notification
@@ -391,7 +391,7 @@ proceed to initiate a checkout session based on the completed cart by issuing a
### State Change Messages
State change notifications follow the shared EP pattern — see
-[Embedded Protocol — State Change](embedded-protocol.md#state-change). All state
+[Embedded Protocol — State Change](../../embedded-protocol.md#state-change). All state
change notifications are sent from the Embedded Cart to the host and carry the
full `cart` object as their payload.
@@ -491,7 +491,7 @@ informational notices about the cart state.
#### `ep.cart.error`
`ep.cart.error` implements the shared EP session error pattern — see
-[Embedded Protocol — Session Error](embedded-protocol.md#session-error) for the
+[Embedded Protocol — Session Error](../../embedded-protocol.md#session-error) for the
payload specification and host handling requirements.
## Security & Error Handling
@@ -499,13 +499,13 @@ payload specification and host handling requirements.
### Error Codes
ECaP uses the shared EP error code set — see
-[Embedded Protocol — Error Codes](embedded-protocol.md#error-codes).
+[Embedded Protocol — Error Codes](../../embedded-protocol.md#error-codes).
### Security for Web-Based Hosts
ECaP inherits the shared EP security requirements for CSP, iframe sandboxing,
credentialless iframes, and strict origin validation. See
-[Embedded Protocol — Security](embedded-protocol.md#security) for the full
+[Embedded Protocol — Security](../../embedded-protocol.md#security) for the full
specification.
## Schema Definitions
@@ -518,4 +518,4 @@ Cart protocol.
The core object representing the current state of the cart, including
line items, totals, and buyer information.
-{{ schema_fields('cart_resp', 'cart') }}
+{{ schema_fields('cart_resp', 'shopping/cart') }}
diff --git a/docs/specification/cart.md b/docs/specification/shopping/cart/index.md
similarity index 81%
rename from docs/specification/cart.md
rename to docs/specification/shopping/cart/index.md
index 982f3c07c..a5c4427b5 100644
--- a/docs/specification/cart.md
+++ b/docs/specification/shopping/cart/index.md
@@ -21,7 +21,7 @@
## Overview
The Cart capability enables basket building without the complexity of checkout.
-While [Checkout](checkout.md) manages payment handlers, status lifecycle, and
+While [Checkout](../checkout/index.md) manages payment handlers, status lifecycle, and
order finalization, cart provides a lightweight CRUD interface for item
collection before purchase intent is established.
@@ -92,7 +92,7 @@ SHOULD be linked for the duration of the checkout.
## Quantity and sale basis
Cart line items apply the shared
-[quantities and units](overview.md#quantities-and-units) contract. Each
+[quantities and units](../../overview/index.md#quantities-and-units) contract. Each
`line_items[].quantity` is an integer step count in the item's authoritative
sale basis. On a Business response, an absent
`line_items[].item.quantity_unit` encodes the default `each` basis, so
@@ -104,7 +104,7 @@ sale basis, so a request for a measure-denominated item can omit the descriptor
without asserting `each`. The Platform **MAY** include `item.quantity_unit` to
assert the sale-basis identity.
-Cart follows [Checkout — Quantity and sale basis](checkout.md#quantity-and-sale-basis)
+Cart follows [Checkout — Quantity and sale basis](../checkout/index.md#quantity-and-sale-basis)
for sale-basis discovery, assertion matching, mismatch conversion or
rejection, response echo, ordering-increment handling, and line pricing.
Cart totals remain estimates (see [Total](#total)). A measure-denominated line
@@ -114,7 +114,7 @@ item count.
## Actions
The cart surfaces outstanding Action instances in its response-only `actions`
-map, defined in [Overview — Actions](overview.md#actions).
+map, defined in [Overview — Actions](../../overview/index.md#actions).
The cart has no status lifecycle. Each Action gates only the cart effect
specified for its Action type. The Business **MUST NOT** treat an outstanding
@@ -134,7 +134,7 @@ user-authenticated access:
| `dev.ucp.shopping.cart:manage` | All cart operations on behalf of the authenticated user — create, read, update, persist. |
Scope declaration, derivation, and rules for extending this set with
-custom scopes are defined in [Identity Linking — Scopes](identity-linking.md#scopes).
+custom scopes are defined in [Identity Linking — Scopes](../../common/identity-linking/index.md#scopes).
## Guidelines
@@ -158,7 +158,7 @@ custom scopes are defined in [Identity Linking — Scopes](identity-linking.md#s
## Cart Schema Definition
-{{ schema_fields('cart_resp', 'cart') }}
+{{ schema_fields('cart_resp', 'shopping/cart') }}
## Operations
@@ -197,16 +197,16 @@ indicator:
}
```
-* [REST Binding](cart-rest.md#create-cart)
-* [MCP Binding](cart-mcp.md#create_cart)
+* [REST Binding](rest.md#create-cart)
+* [MCP Binding](mcp.md#create_cart)
### Get Cart
Retrieves the latest state of a cart session. Returns `not_found` if the cart
does not exist, has expired, or was canceled.
-* [REST Binding](cart-rest.md#get-cart)
-* [MCP Binding](cart-mcp.md#get_cart)
+* [REST Binding](rest.md#get-cart)
+* [MCP Binding](mcp.md#get_cart)
### Update Cart
@@ -214,106 +214,106 @@ Performs a full replacement of the cart session. The platform **MUST** send
the entire cart resource. The provided resource replaces the existing cart
state on the business side.
-* [REST Binding](cart-rest.md#update-cart)
-* [MCP Binding](cart-mcp.md#update_cart)
+* [REST Binding](rest.md#update-cart)
+* [MCP Binding](mcp.md#update_cart)
### Cancel Cart
Cancels a cart session. Business MUST return the cart state before deletion.
Subsequent operations for this cart ID SHOULD return `not_found`.
-* [REST Binding](cart-rest.md#cancel-cart)
-* [MCP Binding](cart-mcp.md#cancel_cart)
+* [REST Binding](rest.md#cancel-cart)
+* [MCP Binding](mcp.md#cancel_cart)
## Entities
-Cart reuses the same entity schemas as [Checkout](checkout.md). This ensures
+Cart reuses the same entity schemas as [Checkout](../checkout/index.md). This ensures
consistent data structures when converting a cart to a checkout session.
### UCP Response Cart {: #ucp-response-cart-schema }
-{{ extension_schema_fields('ucp.json#/$defs/response_cart_schema', 'cart') }}
+{{ extension_schema_fields('ucp.json#/$defs/response_cart_schema', 'shopping/cart') }}
### Line Item
#### Line Item Create Request
-{{ schema_fields('types/line_item_create_req', 'checkout') }}
+{{ schema_fields('types/line_item_create_req', 'shopping/checkout') }}
#### Line Item Update Request
-{{ schema_fields('types/line_item_update_req', 'checkout') }}
+{{ schema_fields('types/line_item_update_req', 'shopping/checkout') }}
#### Line Item
-{{ schema_fields('types/line_item_resp', 'cart') }}
+{{ schema_fields('types/line_item_resp', 'shopping/cart') }}
#### Item
-{{ schema_fields('types/item_resp', 'cart') }}
+{{ schema_fields('types/item_resp', 'shopping/cart') }}
### Buyer
-{{ schema_fields('buyer', 'checkout') }}
+{{ schema_fields('buyer', 'shopping/checkout') }}
### Context
-{{ schema_fields('context', 'checkout') }}
+{{ schema_fields('context', 'shopping/checkout') }}
### Signals
Environment data provided by the platform to support authorization
and abuse prevention. Signal values MUST NOT be buyer-asserted claims. See
-[Signals](overview.md#signals) for details and privacy
+[Signals](../../overview/index.md#signals) for details and privacy
requirements.
-{{ schema_fields('types/signals', 'checkout') }}
+{{ schema_fields('types/signals', 'shopping/checkout') }}
### Attribution
Platform-provided referral and conversion-event context — campaign IDs,
click identifiers, and source/medium markers communicated by the platform.
-See [Attribution](overview.md#attribution) for details and consent
+See [Attribution](../../overview/index.md#attribution) for details and consent
requirements.
-{{ schema_fields('types/attribution', 'checkout') }}
+{{ schema_fields('types/attribution', 'shopping/checkout') }}
### Total
The same totals contract applies to cart and checkout. See
-[Checkout Totals](checkout.md#totals) for the rendering contract, accounting
+[Checkout Totals](../checkout/index.md#totals) for the rendering contract, accounting
identity, well-known types, repeating types, and sub-line semantics.
-{{ schema_fields('types/total_resp', 'checkout') }}
+{{ schema_fields('types/total_resp', 'shopping/checkout') }}
Taxes MAY be included where calculable. Platforms SHOULD assume cart totals
are estimates; accurate taxes are computed at checkout.
### Message
-{{ schema_fields('message', 'checkout') }}
+{{ schema_fields('message', 'shopping/checkout') }}
#### Message Error
-{{ schema_fields('types/message_error', 'checkout') }}
+{{ schema_fields('types/message_error', 'shopping/checkout') }}
#### Message Info
-{{ schema_fields('types/message_info', 'checkout') }}
+{{ schema_fields('types/message_info', 'shopping/checkout') }}
#### Message Warning
-{{ schema_fields('types/message_warning', 'checkout') }}
+{{ schema_fields('types/message_warning', 'shopping/checkout') }}
### Link
-{{ schema_fields('types/link', 'checkout') }}
+{{ schema_fields('types/link', 'shopping/checkout') }}
### Policy
Policies (return/refund terms, warranty, and the like) that apply to the items
in this cart. JSONPath targets in `applies_to` are relative to
this response root (e.g., `$.line_items[0]`). See
-[Policies](overview.md#policies) for the full model.
+[Policies](../../overview/index.md#policies) for the full model.
-{{ schema_fields('types/policy', 'cart') }}
+{{ schema_fields('types/policy', 'shopping/cart') }}
diff --git a/docs/specification/cart-mcp.md b/docs/specification/shopping/cart/mcp.md
similarity index 93%
rename from docs/specification/cart-mcp.md
rename to docs/specification/shopping/cart/mcp.md
index 9c6e0cf9d..1d618dda4 100644
--- a/docs/specification/cart-mcp.md
+++ b/docs/specification/shopping/cart/mcp.md
@@ -17,7 +17,7 @@
# Cart Capability - MCP Binding
This document specifies the Model Context Protocol (MCP) binding for the
-[Cart Capability](cart.md).
+[Cart Capability](index.md).
## Protocol Fundamentals
@@ -46,14 +46,14 @@ Businesses advertise MCP transport availability through their UCP profile at
"dev.ucp.shopping.checkout": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/checkout",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/checkout",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/checkout.json"
}
],
"dev.ucp.shopping.cart": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/cart",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/cart",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/cart.json"
}
]
@@ -89,7 +89,7 @@ protocol metadata:
```
The `meta["ucp-agent"]` field is **required** on all requests to enable
-[capability negotiation](overview.md#negotiation-protocol). Platforms **MAY**
+[capability negotiation](../../overview/index.md#negotiation-protocol). Platforms **MAY**
include additional metadata fields.
## Tools
@@ -109,22 +109,22 @@ MCP tools separate resource identification from payload data:
| Tool | Operation | Description |
| :---- | :---- | :---- |
-| `create_cart` | [Create Cart](cart.md#create-cart) | Create a cart session. |
-| `get_cart` | [Get Cart](cart.md#get-cart) | Get a cart session. |
-| `update_cart` | [Update Cart](cart.md#update-cart) | Update a cart session. |
-| `cancel_cart` | [Cancel Cart](cart.md#cancel-cart) | Cancel a cart session. |
+| `create_cart` | [Create Cart](index.md#create-cart) | Create a cart session. |
+| `get_cart` | [Get Cart](index.md#get-cart) | Get a cart session. |
+| `update_cart` | [Update Cart](index.md#update-cart) | Update a cart session. |
+| `cancel_cart` | [Cancel Cart](index.md#cancel-cart) | Cancel a cart session. |
### `create_cart`
-Maps to the [Create Cart](cart.md#create-cart) operation.
+Maps to the [Create Cart](index.md#create-cart) operation.
#### Input Schema
-{{ schema_fields('cart_create_req', 'cart') }}
+{{ schema_fields('cart_create_req', 'shopping/cart') }}
#### Output Schema
-{{ schema_fields('cart_resp', 'cart') }}
+{{ schema_fields('cart_resp', 'shopping/cart') }}
#### Example
@@ -251,7 +251,7 @@ Maps to the [Create Cart](cart.md#create-cart) operation.
### `get_cart`
-Maps to the [Get Cart](cart.md#get-cart) operation.
+Maps to the [Get Cart](index.md#get-cart) operation.
#### Input Schema
@@ -259,7 +259,7 @@ Maps to the [Get Cart](cart.md#get-cart) operation.
#### Output Schema
-{{ schema_fields('cart_resp', 'cart') }}
+{{ schema_fields('cart_resp', 'shopping/cart') }}
#### Example
@@ -379,17 +379,17 @@ Maps to the [Get Cart](cart.md#get-cart) operation.
### `update_cart`
-Maps to the [Update Cart](cart.md#update-cart) operation.
+Maps to the [Update Cart](index.md#update-cart) operation.
#### Input Schema
* `id` (String, required): The ID of the cart session to update.
-{{ schema_fields('cart_update_req', 'cart') }}
+{{ schema_fields('cart_update_req', 'shopping/cart') }}
#### Output Schema
-{{ schema_fields('cart_resp', 'cart') }}
+{{ schema_fields('cart_resp', 'shopping/cart') }}
#### Example
@@ -507,7 +507,7 @@ Maps to the [Update Cart](cart.md#update-cart) operation.
### `cancel_cart`
-Maps to the [Cancel Cart](cart.md#cancel-cart) operation.
+Maps to the [Cancel Cart](index.md#cancel-cart) operation.
#### Input Schema
@@ -515,7 +515,7 @@ Maps to the [Cancel Cart](cart.md#cancel-cart) operation.
#### Output Schema
-{{ schema_fields('cart_resp', 'cart') }}
+{{ schema_fields('cart_resp', 'shopping/cart') }}
#### Example
@@ -600,7 +600,7 @@ Maps to the [Cancel Cart](cart.md#cancel-cart) operation.
## Error Handling
UCP distinguishes between protocol errors and business outcomes. See the
-[Core Specification](overview.md#error-handling) for the complete error code
+[Core Specification](../../overview/index.md#error-handling) for the complete error code
registry and transport binding examples.
* **Protocol errors**: Transport-level failures (authentication, rate limiting,
@@ -652,7 +652,7 @@ A conforming MCP transport implementation **MUST**:
1. Implement JSON-RPC 2.0 protocol correctly.
2. Provide all core cart tools defined in this specification.
-3. Return errors per the [Core Specification](overview.md#error-handling).
+3. Return errors per the [Core Specification](../../overview/index.md#error-handling).
4. Return business outcomes as JSON-RPC `result` with UCP envelope and
`messages` array.
5. Validate tool inputs against UCP schemas.
diff --git a/docs/specification/cart-rest.md b/docs/specification/shopping/cart/rest.md
similarity index 95%
rename from docs/specification/cart-rest.md
rename to docs/specification/shopping/cart/rest.md
index 7c71790f2..c0df23ded 100644
--- a/docs/specification/cart-rest.md
+++ b/docs/specification/shopping/cart/rest.md
@@ -16,7 +16,7 @@
# Cart Capability - REST Binding
-This document specifies the REST binding for the [Cart Capability](cart.md).
+This document specifies the REST binding for the [Cart Capability](index.md).
## Protocol Fundamentals
@@ -45,14 +45,14 @@ Businesses advertise REST transport availability through their UCP profile at
"dev.ucp.shopping.checkout": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/checkout",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/checkout",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/checkout.json"
}
],
"dev.ucp.shopping.cart": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/cart",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/cart",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/cart.json"
}
]
@@ -93,11 +93,11 @@ All REST endpoints **MUST** be served over HTTPS with minimum TLS version 1.3.
#### Input Schema
-{{ schema_fields('cart_create_req', 'cart') }}
+{{ schema_fields('cart_create_req', 'shopping/cart') }}
#### Output Schema
-{{ schema_fields('cart_resp', 'cart') }}
+{{ schema_fields('cart_resp', 'shopping/cart') }}
#### Example
@@ -205,7 +205,7 @@ All REST endpoints **MUST** be served over HTTPS with minimum TLS version 1.3.
#### Output Schema
-{{ schema_fields('cart_resp', 'cart') }}
+{{ schema_fields('cart_resp', 'shopping/cart') }}
#### Example
@@ -296,11 +296,11 @@ All REST endpoints **MUST** be served over HTTPS with minimum TLS version 1.3.
* `id` (String, required): The cart session ID (path parameter).
-{{ schema_fields('cart_update_req', 'cart') }}
+{{ schema_fields('cart_update_req', 'shopping/cart') }}
#### Output Schema
-{{ schema_fields('cart_resp', 'cart') }}
+{{ schema_fields('cart_resp', 'shopping/cart') }}
#### Example
@@ -406,7 +406,7 @@ All REST endpoints **MUST** be served over HTTPS with minimum TLS version 1.3.
#### Output Schema
-{{ schema_fields('cart_resp', 'cart') }}
+{{ schema_fields('cart_resp', 'shopping/cart') }}
#### Example
@@ -485,7 +485,7 @@ operations unless otherwise noted.
1. Store the key with the operation result for at least 24 hours.
2. Return the cached result for duplicate keys whose request body matches the original.
3. Return `409 Conflict` if the key is reused with a mismatched body.
- See [Message Signatures — Idempotency Key Requirements](signatures.md#replay-protection)
+ See [Message Signatures — Idempotency Key Requirements](../../signatures.md#replay-protection)
for the full payload-matching contract.
## Protocol Mechanics
@@ -508,7 +508,7 @@ operations unless otherwise noted.
### Error Responses
-See the [Core Specification](overview.md#error-handling) for the complete error
+See the [Core Specification](../../overview/index.md#error-handling) for the complete error
code registry and transport binding examples.
* **Protocol errors**: Return appropriate HTTP status code (401, 403, 409, 429,
@@ -553,7 +553,7 @@ authentication is required, the REST transport **MAY** use:
2. **API Keys**: Via `X-API-Key` header.
3. **OAuth 2.0**: Via `Authorization: Bearer {token}` header. Identifies the
platform for agent-authenticated access, or both platform and user for
- user-authenticated access (see [Identity Linking](identity-linking.md)).
+ user-authenticated access (see [Identity Linking](../../common/identity-linking/index.md)).
4. **Mutual TLS**: For high-security environments.
Businesses **MAY** require authentication for some operations while leaving
diff --git a/docs/specification/catalog/index.md b/docs/specification/shopping/catalog/index.md
similarity index 90%
rename from docs/specification/catalog/index.md
rename to docs/specification/shopping/catalog/index.md
index 4b3aec050..1f656c3a1 100644
--- a/docs/specification/catalog/index.md
+++ b/docs/specification/shopping/catalog/index.md
@@ -43,7 +43,7 @@ This enables product discovery before checkout, supporting use cases like:
currency code, enabling multi-currency catalogs.
* **Sale basis**: How quantity is denominated—as whole items (`each`, the
default) or in a unit of measure such as weight, length, area, volume, or
- time. See [Quantities and units](../overview.md#quantities-and-units).
+ time. See [Quantities and units](../../overview/index.md#quantities-and-units).
### Relationship to Checkout
@@ -60,13 +60,13 @@ reused across sessions without re-validation.
`variants[].quantity_unit` advertises a variant's sale basis before a
transaction. The descriptor follows the shared
-[quantities and units](../overview.md#quantities-and-units) contract. Its
+[quantities and units](../../overview/index.md#quantities-and-units) contract. Its
absence advertises the default `each` basis; the Business advertises a
non-`each` basis by including the descriptor.
The catalog is where the Platform learns the sale basis before transacting:
`unit` and `scale` define how quantities are denominated, and an optional
-[`increment`](../overview.md#ordering-increment) advertises the ordering
+[`increment`](../../overview/index.md#ordering-increment) advertises the ordering
granularity the Business sells in, letting the Platform build quantity
steppers and validate input before submission. A Business selling bananas by
the pound in quarter-pound multiples advertises
@@ -96,7 +96,7 @@ questions and are set independently:
The unit fields in `quantity_unit`, `unit_price.measure`, and
`unit_price.reference` follow the shared
-[quantities and units](../overview.md#quantities-and-units) contract. The two
+[quantities and units](../../overview/index.md#quantities-and-units) contract. The two
unit-price fields use the shared measure type, so their integer `value` fields
are step counts. The Business **MAY** provide `quantity_unit`, `unit_price`,
both, or neither on a variant.
@@ -133,7 +133,7 @@ carrying a `unit_price` per metre. Its `measure` can be
On transaction lines, presence marks the role: the Business **MUST** echo
`unit_price` on any line whose pricing basis differs from its sale basis (see
-[Checkout — pricing basis](../checkout.md#quantity-and-sale-basis)). A
+[Checkout — pricing basis](../checkout/index.md#quantity-and-sale-basis)). A
catalog-only `unit_price`, like this spool's per-metre figure, is a display
comparator; a line-level one carries the rate the charge is computed from.
@@ -196,24 +196,24 @@ When `context.eligibility` claims are present, Businesses that accept them
**MAY** use `messages` with `code: "eligibility_benefit"` to attribute the
adjustment to a specific claim.
-{{ schema_fields('types/context', 'catalog') }}
+{{ schema_fields('types/context', 'shopping/catalog') }}
### Signals
Environment data provided by the platform to support authorization
and abuse prevention. Signal values MUST NOT be buyer-asserted claims. See
-[Signals](../overview.md#signals) for details and privacy requirements.
+[Signals](../../overview/index.md#signals) for details and privacy requirements.
-{{ schema_fields('types/signals', 'catalog') }}
+{{ schema_fields('types/signals', 'shopping/catalog') }}
### Attribution
Platform-provided referral and conversion-event context — campaign IDs,
click identifiers, and source/medium markers communicated by the platform.
-See [Attribution](../overview.md#attribution) for details and consent
+See [Attribution](../../overview/index.md#attribution) for details and consent
requirements.
-{{ schema_fields('types/attribution', 'catalog') }}
+{{ schema_fields('types/attribution', 'shopping/catalog') }}
### Product
@@ -223,7 +223,7 @@ A catalog item representing a sellable item with one or more purchasable variant
relevant variant and image first—default for lookups, best match based on query
and context for search. Platforms SHOULD treat the first element as featured.
-{{ schema_fields('types/product', 'catalog') }}
+{{ schema_fields('types/product', 'shopping/catalog') }}
### Variant
@@ -237,44 +237,44 @@ was `exact` or `featured` (server-selected). See
`media` is an ordered array. Businesses SHOULD return the featured variant image
as the first element. Platforms SHOULD treat the first element as featured.
-{{ schema_fields('types/variant', 'catalog') }}
+{{ schema_fields('types/variant', 'shopping/catalog') }}
### Price
-{{ schema_fields('types/price', 'catalog') }}
+{{ schema_fields('types/price', 'shopping/catalog') }}
### Price Range
-{{ schema_fields('types/price_range', 'catalog') }}
+{{ schema_fields('types/price_range', 'shopping/catalog') }}
### Media
-{{ schema_fields('types/media', 'catalog') }}
+{{ schema_fields('types/media', 'shopping/catalog') }}
### Product Option
-{{ schema_fields('types/product_option', 'catalog') }}
+{{ schema_fields('types/product_option', 'shopping/catalog') }}
### Option Value
-{{ schema_fields('types/option_value', 'catalog') }}
+{{ schema_fields('types/option_value', 'shopping/catalog') }}
### Selected Option
-{{ schema_fields('types/selected_option', 'catalog') }}
+{{ schema_fields('types/selected_option', 'shopping/catalog') }}
### Rating
-{{ schema_fields('types/rating', 'catalog') }}
+{{ schema_fields('types/rating', 'shopping/catalog') }}
### Policy
Policies (return/refund terms, warranty, and the like) that apply to the
products in a catalog response. JSONPath targets in `applies_to` are
relative to the response root — `$.products[N]` for search and batch lookup,
-`$.product` for get_product. See [Policies](../overview.md#policies) for the full model.
+`$.product` for get_product. See [Policies](../../overview/index.md#policies) for the full model.
-{{ schema_fields('types/policy', 'catalog') }}
+{{ schema_fields('types/policy', 'shopping/catalog') }}
## Actions
@@ -298,7 +298,7 @@ After processing an Action, the Platform performs a fresh Catalog operation and
the later Business response is authoritative. Catalog defines no Action
lifecycle, polling, or resume behavior; a concrete Action-type contract **MAY**
define those behaviors for processing its instances. The common shape and rules
-are defined in [Overview — Actions](../overview.md#actions).
+are defined in [Overview — Actions](../../overview/index.md#actions).
For example, this Search response returns no products and explains that age
verification may affect the results:
@@ -347,7 +347,7 @@ Messages communicate business outcomes and provide context:
Warnings with `presentation: "disclosure"` carry notices (e.g., allergen
declarations, safety warnings) that platforms must not hide or dismiss. See
-[Warning Presentation](../checkout.md#warning-presentation) for the full
+[Warning Presentation](../checkout/index.md#warning-presentation) for the full
rendering contract.
**Note**: Most catalog errors use `severity: "recoverable"` - agents
@@ -359,15 +359,15 @@ examples).
#### Message (Error)
-{{ schema_fields('types/message_error', 'catalog') }}
+{{ schema_fields('types/message_error', 'shopping/catalog') }}
#### Message (Warning)
-{{ schema_fields('types/message_warning', 'catalog') }}
+{{ schema_fields('types/message_warning', 'shopping/catalog') }}
#### Message (Info)
-{{ schema_fields('types/message_info', 'catalog') }}
+{{ schema_fields('types/message_info', 'shopping/catalog') }}
### Common Scenarios
@@ -505,7 +505,7 @@ disclosure applies to all of its variants.
}
```
-See [Warning Presentation](../checkout.md#warning-presentation) for the
+See [Warning Presentation](../checkout/index.md#warning-presentation) for the
full rendering contract.
## Scopes
@@ -519,7 +519,7 @@ well-known scopes for user-authenticated access:
| `dev.ucp.shopping.catalog.lookup:read` | Lookup on behalf of the authenticated user — personalized pricing or availability for specific products. |
Scope declaration, derivation, and rules for extending this set with
-custom scopes are defined in [Identity Linking — Scopes](../identity-linking.md#scopes).
+custom scopes are defined in [Identity Linking — Scopes](../../common/identity-linking/index.md#scopes).
## Transport Bindings
diff --git a/docs/specification/catalog/lookup.md b/docs/specification/shopping/catalog/lookup.md
similarity index 96%
rename from docs/specification/catalog/lookup.md
rename to docs/specification/shopping/catalog/lookup.md
index 631244900..0e4e56c9c 100644
--- a/docs/specification/catalog/lookup.md
+++ b/docs/specification/shopping/catalog/lookup.md
@@ -63,7 +63,7 @@ resolve to the same product, it MUST be returned once.
The response does not guarantee order. Each variant carries an `inputs`
array identifying which request identifiers resolved to it, and how.
-{{ schema_fields('types/input_correlation', 'catalog') }}
+{{ schema_fields('types/input_correlation', 'shopping/catalog') }}
Multiple request identifiers may resolve to the same variant (e.g., a
product ID and one of its variant IDs). When this occurs, the variant's
@@ -101,11 +101,11 @@ from the response.
### Request
-{{ extension_schema_fields('catalog_lookup.json#/$defs/lookup_request', 'catalog') }}
+{{ extension_schema_fields('catalog_lookup.json#/$defs/lookup_request', 'shopping/catalog') }}
### Response
-{{ extension_schema_fields('catalog_lookup.json#/$defs/lookup_response', 'catalog') }}
+{{ extension_schema_fields('catalog_lookup.json#/$defs/lookup_response', 'shopping/catalog') }}
---
@@ -193,11 +193,11 @@ selection changes the availability map.
### Request
-{{ extension_schema_fields('catalog_lookup.json#/$defs/get_product_request', 'catalog') }}
+{{ extension_schema_fields('catalog_lookup.json#/$defs/get_product_request', 'shopping/catalog') }}
### Response
-{{ extension_schema_fields('catalog_lookup.json#/$defs/get_product_response', 'catalog') }}
+{{ extension_schema_fields('catalog_lookup.json#/$defs/get_product_response', 'shopping/catalog') }}
---
@@ -208,7 +208,7 @@ response-only `actions` map. Batch Lookup retains its required `products` array,
which can be empty; successful Get Product retains its required `product`, and
its existing error response is unchanged. See
[Catalog — Actions](index.md#actions) for the parent contract and
-[Overview — Actions](../overview.md#actions) for the common rules.
+[Overview — Actions](../../overview/index.md#actions) for the common rules.
## Transport Bindings
diff --git a/docs/specification/catalog/mcp.md b/docs/specification/shopping/catalog/mcp.md
similarity index 96%
rename from docs/specification/catalog/mcp.md
rename to docs/specification/shopping/catalog/mcp.md
index d92fa4ea3..e90c26a71 100644
--- a/docs/specification/catalog/mcp.md
+++ b/docs/specification/shopping/catalog/mcp.md
@@ -45,12 +45,12 @@ Businesses advertise MCP transport availability through their UCP profile at
"capabilities": {
"dev.ucp.shopping.catalog.search": [{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/catalog/search",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/catalog/search",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/catalog_search.json"
}],
"dev.ucp.shopping.catalog.lookup": [{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/catalog/lookup",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/catalog/lookup",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/catalog_lookup.json"
}]
},
@@ -108,13 +108,13 @@ Maps to the [Catalog Search](search.md) capability.
#### Search Request
{{ extension_schema_fields(
- 'catalog_search.json#/$defs/search_request', 'catalog/mcp'
+ 'catalog_search.json#/$defs/search_request', 'shopping/catalog/mcp'
) }}
### Search Response
{{ extension_schema_fields(
- 'catalog_search.json#/$defs/search_response', 'catalog/mcp'
+ 'catalog_search.json#/$defs/search_response', 'shopping/catalog/mcp'
) }}
#### Search Example
@@ -268,13 +268,13 @@ The `catalog.ids` parameter accepts an array of identifiers and optional context
#### Lookup Request
{{ extension_schema_fields(
- 'catalog_lookup.json#/$defs/lookup_request', 'catalog/mcp'
+ 'catalog_lookup.json#/$defs/lookup_request', 'shopping/catalog/mcp'
) }}
### Lookup Response
{{ extension_schema_fields(
- 'catalog_lookup.json#/$defs/lookup_response', 'catalog/mcp'
+ 'catalog_lookup.json#/$defs/lookup_response', 'shopping/catalog/mcp'
) }}
#### Lookup Example
@@ -458,13 +458,13 @@ Maps to the [Catalog Lookup](lookup.md#get-product-get_product) capability. Retu
#### Get Product Request
{{ extension_schema_fields(
- 'catalog_lookup.json#/$defs/get_product_request', 'catalog/mcp'
+ 'catalog_lookup.json#/$defs/get_product_request', 'shopping/catalog/mcp'
) }}
#### Get Product Response
{{ extension_schema_fields(
- 'catalog_lookup.json#/$defs/get_product_response', 'catalog/mcp'
+ 'catalog_lookup.json#/$defs/get_product_response', 'shopping/catalog/mcp'
) }}
#### Get Product Example
@@ -639,7 +639,7 @@ UCP uses a two-layer error model separating transport errors from business outco
Transport-level failures (authentication, rate limiting, unavailability) that
prevent request processing are returned as JSON-RPC `error`. See the
-[Core Specification](../overview.md#error-codes) for the complete error code
+[Core Specification](../../overview/index.md#error-codes) for the complete error code
registry and JSON-RPC error code mappings.
### Business Outcomes
@@ -690,15 +690,15 @@ results.
### Detail Product {: #detail-product }
-{{ extension_schema_fields('catalog_lookup.json#/$defs/detail_product', 'catalog/mcp') }}
+{{ extension_schema_fields('catalog_lookup.json#/$defs/detail_product', 'shopping/catalog/mcp') }}
### Get Product Response {: #catalog-lookup-get-product-response }
-{{ extension_schema_fields('catalog_lookup.json#/$defs/get_product_response', 'catalog/mcp') }}
+{{ extension_schema_fields('catalog_lookup.json#/$defs/get_product_response', 'shopping/catalog/mcp') }}
### Error Response {: #error-response }
-{{ schema_fields('types/error_response', 'catalog/mcp') }}
+{{ schema_fields('types/error_response', 'shopping/catalog/mcp') }}
## Conformance
diff --git a/docs/specification/catalog/rest.md b/docs/specification/shopping/catalog/rest.md
similarity index 97%
rename from docs/specification/catalog/rest.md
rename to docs/specification/shopping/catalog/rest.md
index cd5b2ca31..27b31f473 100644
--- a/docs/specification/catalog/rest.md
+++ b/docs/specification/shopping/catalog/rest.md
@@ -45,12 +45,12 @@ Businesses advertise REST transport availability through their UCP profile at
"capabilities": {
"dev.ucp.shopping.catalog.search": [{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/catalog/search",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/catalog/search",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/catalog_search.json"
}],
"dev.ucp.shopping.catalog.lookup": [{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/catalog/lookup",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/catalog/lookup",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/catalog_lookup.json"
}]
},
@@ -71,7 +71,7 @@ Businesses advertise REST transport availability through their UCP profile at
Maps to the [Catalog Search](search.md) capability.
-{{ method_fields('search_catalog', 'rest.openapi.json', 'catalog/rest') }}
+{{ method_fields('search_catalog', 'rest.openapi.json', 'shopping/catalog/rest') }}
#### Example
@@ -201,7 +201,7 @@ for supported identifiers, resolution behavior, and client correlation requireme
The request body contains an array of identifiers and optional context that
applies to all lookups in the batch.
-{{ method_fields('lookup_catalog', 'rest.openapi.json', 'catalog/rest') }}
+{{ method_fields('lookup_catalog', 'rest.openapi.json', 'shopping/catalog/rest') }}
#### Example: Batch Lookup with Context
@@ -353,7 +353,7 @@ messages indicating which identifiers were not found.
Maps to the [Catalog Lookup](lookup.md#get-product-get_product) capability. Returns a singular
`product` object (not an array) for full product detail page rendering.
-{{ method_fields('get_product', 'rest.openapi.json', 'catalog/rest') }}
+{{ method_fields('get_product', 'rest.openapi.json', 'shopping/catalog/rest') }}
#### Example: With Option Selection
@@ -582,19 +582,19 @@ Business outcomes use the standard HTTP 200 status with messages in the response
### UCP Response Catalog {: #ucp-response-catalog-schema }
-{{ extension_schema_fields('ucp.json#/$defs/response_catalog_schema', 'catalog/rest') }}
+{{ extension_schema_fields('ucp.json#/$defs/response_catalog_schema', 'shopping/catalog/rest') }}
### Detail Product {: #detail-product }
-{{ extension_schema_fields('catalog_lookup.json#/$defs/detail_product', 'catalog/rest') }}
+{{ extension_schema_fields('catalog_lookup.json#/$defs/detail_product', 'shopping/catalog/rest') }}
### Get Product Response {: #catalog-lookup-get-product-response }
-{{ extension_schema_fields('catalog_lookup.json#/$defs/get_product_response', 'catalog/rest') }}
+{{ extension_schema_fields('catalog_lookup.json#/$defs/get_product_response', 'shopping/catalog/rest') }}
### Error Response {: #error-response }
-{{ schema_fields('types/error_response', 'catalog/rest') }}
+{{ schema_fields('types/error_response', 'shopping/catalog/rest') }}
## Conformance
diff --git a/docs/specification/catalog/search.md b/docs/specification/shopping/catalog/search.md
similarity index 91%
rename from docs/specification/catalog/search.md
rename to docs/specification/shopping/catalog/search.md
index 53aa5f910..9c1d85a6a 100644
--- a/docs/specification/catalog/search.md
+++ b/docs/specification/shopping/catalog/search.md
@@ -29,11 +29,11 @@ queries, filtering by category and price, and pagination.
### Request
-{{ extension_schema_fields('catalog_search.json#/$defs/search_request', 'catalog') }}
+{{ extension_schema_fields('catalog_search.json#/$defs/search_request', 'shopping/catalog') }}
### Response
-{{ extension_schema_fields('catalog_search.json#/$defs/search_response', 'catalog') }}
+{{ extension_schema_fields('catalog_search.json#/$defs/search_response', 'shopping/catalog') }}
## Search Inputs
@@ -55,11 +55,11 @@ empty `query` strings, or accepting filter-only requests for category browsing.
Filter criteria for narrowing search results. Standard filters are defined below;
merchants MAY support additional custom filters via `additionalProperties`.
-{{ schema_fields('types/search_filters', 'catalog') }}
+{{ schema_fields('types/search_filters', 'shopping/catalog') }}
### Price Filter
-{{ schema_fields('types/price_filter', 'catalog') }}
+{{ schema_fields('types/price_filter', 'shopping/catalog') }}
## Pagination
@@ -76,11 +76,11 @@ error. Clients MUST NOT assume the response size equals the requested limit.
### Pagination Request
-{{ extension_schema_fields('types/pagination.json#/$defs/request', 'catalog') }}
+{{ extension_schema_fields('types/pagination.json#/$defs/request', 'shopping/catalog') }}
### Pagination Response
-{{ extension_schema_fields('types/pagination.json#/$defs/response', 'catalog') }}
+{{ extension_schema_fields('types/pagination.json#/$defs/response', 'shopping/catalog') }}
## Actions
@@ -88,7 +88,7 @@ Search responses adopt the response-only `actions` map. The required `products`
array can be empty; the Business decides whether it contains zero, some, or all
otherwise relevant products under the Action-type contract. See
[Catalog — Actions](index.md#actions) for the parent contract and example, and
-[Overview — Actions](../overview.md#actions) for the common rules.
+[Overview — Actions](../../overview/index.md#actions) for the common rules.
## Transport Bindings
diff --git a/docs/specification/checkout-a2a.md b/docs/specification/shopping/checkout/a2a.md
similarity index 98%
rename from docs/specification/checkout-a2a.md
rename to docs/specification/shopping/checkout/a2a.md
index 70d9f4ab8..e32d473eb 100644
--- a/docs/specification/checkout-a2a.md
+++ b/docs/specification/shopping/checkout/a2a.md
@@ -17,7 +17,7 @@
# Checkout Capability - A2A Binding
This document specifies the Agent2Agent Protocol (A2A) binding for
-[Checkout Capability](checkout.md).
+[Checkout Capability](index.md).
## Transport Discovery
@@ -355,10 +355,10 @@ be submitted as part of a `DataPart` with attribute name
`a2a.ucp.checkout.payment`. Signed checkout mandate must be specified in
the `DataPart` as `ap2.checkout_mandate`. The `token` attribute of
`payment` contains the payment mandate. Refer to
-[AP2 Mandates Extension](ap2-mandates.md) documentation for more details about
+[AP2 Mandates Extension](../../ap2-mandates.md) documentation for more details about
verification and processing of the mandates to complete the checkout.
-### Request format
+#### Request format
```json
diff --git a/docs/specification/embedded-checkout.md b/docs/specification/shopping/checkout/embedded.md
similarity index 98%
rename from docs/specification/embedded-checkout.md
rename to docs/specification/shopping/checkout/embedded.md
index ef9ef07a1..04fbaf4b7 100644
--- a/docs/specification/embedded-checkout.md
+++ b/docs/specification/shopping/checkout/embedded.md
@@ -403,7 +403,7 @@ completion.
## Transport & Messaging
ECP uses the shared EP transport layer. See
-[Embedded Protocol — Transport & Messaging](embedded-protocol.md#transport-messaging)
+[Embedded Protocol — Transport & Messaging](../../embedded-protocol.md#transport-messaging)
for message format, message types, and response handling conventions.
The `ucp.version` in all responses **MUST** echo the `ec_version` negotiated
@@ -414,7 +414,7 @@ of the ECP session.
### Communication Channels
ECP follows the shared EP communication channel model. See
-[Embedded Protocol — Communication Channels](embedded-protocol.md#communication-channels)
+[Embedded Protocol — Communication Channels](../../embedded-protocol.md#communication-channels)
for the general pattern.
For native hosts, the checkout-specific globals are:
@@ -659,7 +659,7 @@ messages after receiving a handshake error.
#### `ec.auth`
`ec.auth` implements the shared EP authentication pattern — see
-[Embedded Protocol — Authentication](embedded-protocol.md#authentication) for
+[Embedded Protocol — Authentication](../../embedded-protocol.md#authentication) for
the request/response contract, examples, and error escalation flow.
- **Method:** `ec.auth`
@@ -667,12 +667,12 @@ the request/response contract, examples, and error escalation flow.
When error escalation is required, Embedded Checkout **MUST** issue an
`ec.error` notification per the
-[session error pattern](embedded-protocol.md#session-error).
+[session error pattern](../../embedded-protocol.md#session-error).
### Lifecycle Messages
Lifecycle notifications follow the shared EP pattern — see
-[Embedded Protocol — Lifecycle](embedded-protocol.md#lifecycle). All lifecycle
+[Embedded Protocol — Lifecycle](../../embedded-protocol.md#lifecycle). All lifecycle
notifications carry the full `checkout` object as their payload.
#### `ec.start`
@@ -748,7 +748,7 @@ Indicates successful checkout completion.
### State Change Messages
State change notifications follow the shared EP pattern — see
-[Embedded Protocol — State Change](embedded-protocol.md#state-change). All state
+[Embedded Protocol — State Change](../../embedded-protocol.md#state-change). All state
change notifications are sent from the Embedded Checkout to the host and carry
the full `checkout` object as their payload.
@@ -918,7 +918,7 @@ Payment state has been updated. See the
#### `ec.error`
`ec.error` implements the shared EP session error pattern — see
-[Embedded Protocol — Session Error](embedded-protocol.md#session-error) for the
+[Embedded Protocol — Session Error](../../embedded-protocol.md#session-error) for the
payload specification and host handling requirements.
## Payment Extension
@@ -1391,7 +1391,7 @@ rather than attempting to merge the new data with existing state.
### Address Format
The address object uses the UCP
-[PostalAddress](site:specification/checkout/#postal-address) format:
+[PostalAddress](site:specification/reference/#postal-address) format:
### Postal Address
@@ -1514,7 +1514,7 @@ Requests the host to handle a link activated by the buyer within the checkout.
### Error Codes
-See [Embedded Protocol — Error Codes](embedded-protocol.md#error-codes) for
+See [Embedded Protocol — Error Codes](../../embedded-protocol.md#error-codes) for
the shared error codes. Embedded Checkout defines the following additional
codes for delegation-specific scenarios:
@@ -1530,7 +1530,7 @@ gesture before re-attempting the delegation.
ECP inherits the shared EP security requirements for CSP, iframe sandboxing,
credentialless iframes, and strict origin validation. See
-[Embedded Protocol — Security](embedded-protocol.md#security) for the full
+[Embedded Protocol — Security](../../embedded-protocol.md#security) for the full
specification.
### Prevention of Unsolicited Payment Requests
@@ -1554,14 +1554,14 @@ Checkout protocol and its extensions.
The core object representing the current state of the transaction, including
line items, totals, and buyer information.
-{{ schema_fields('checkout_resp', 'checkout') }}
+{{ schema_fields('checkout_resp', 'shopping/checkout') }}
### Order
The object returned upon successful completion of a checkout, containing
confirmation details.
-{{ schema_fields('order', 'order') }}
+{{ schema_fields('order', 'shopping/order') }}
### Payment
diff --git a/docs/specification/checkout.md b/docs/specification/shopping/checkout/index.md
similarity index 93%
rename from docs/specification/checkout.md
rename to docs/specification/shopping/checkout/index.md
index b7bc86421..c1e72a7dc 100644
--- a/docs/specification/checkout.md
+++ b/docs/specification/shopping/checkout/index.md
@@ -49,10 +49,10 @@ methods the authenticated buyer has saved with the business. Such an instrument
carries no raw credential: it is a display-safe, business-scoped reference (an
opaque `id` plus `display` fields) that the business resolves server-side when
the buyer selects it. The
-[create checkout REST example](checkout-rest.md#create-checkout) already returns
+[create checkout REST example](rest.md#create-checkout) already returns
this shape for a Shop Pay instrument. Returning user-specific saved state
requires a user-authenticated request; see
-[Identity Linking](identity-linking.md#business-populated-response-values) for
+[Identity Linking](../../common/identity-linking/index.md#business-populated-response-values) for
the access levels and scopes that gate it.
The `display` fields let the platform present a saved instrument and let the
@@ -72,7 +72,7 @@ fulfillment details more relevant for physical goods.
### Quantity and sale basis
Checkout applies the shared
-[quantities and units](overview.md#quantities-and-units) contract, including the
+[quantities and units](../../overview/index.md#quantities-and-units) contract, including the
default (`C62`, `0`) identity. The Business determines each item's authoritative
sale basis for the transaction. The Business's response is authoritative, and
each `line_items[].quantity` is an integer step count in that basis.
@@ -80,7 +80,7 @@ each `line_items[].quantity` is an integer step count in that basis.
**Discovering the sale basis.** The sale basis is item data: the Platform
**SHOULD** discover an item's `quantity_unit` — including `scale` and any
`increment` — from the
-[catalog](catalog/index.md#sale-basis-and-quantity-units) before transacting.
+[catalog](../catalog/index.md#sale-basis-and-quantity-units) before transacting.
A Platform without catalog knowledge can omit the descriptor: the Business
applies its authoritative basis and confirms it on the response line, and the
Platform inspects the echoed descriptor and, if that interpretation is not
@@ -98,7 +98,7 @@ omit the descriptor without asserting the default identity.
The Platform **MAY** include `quantity_unit` on a request line to assert the
basis it believes it is ordering in. When the Platform includes it, the Business
**MUST** compare the asserted and authoritative
-[machine identities](overview.md#quantities-and-units). An explicit assertion
+[machine identities](../../overview/index.md#quantities-and-units). An explicit assertion
with `unit: "C62"` and effective `scale` `0` matches the default identity
represented by an absent descriptor; a `display_text` difference is not a
mismatch.
@@ -240,7 +240,7 @@ requested `275` — and the error names the authoritative basis:
```
**Ordering increment.** The sale basis **MAY** declare an
-[`increment`](overview.md#ordering-increment) — the ordering granularity, in
+[`increment`](../../overview/index.md#ordering-increment) — the ordering granularity, in
steps, the Business sells in. The declaration lets the Platform build quantity
steppers and validate input before submission. Platform-authored quantities
**SHOULD** be integer multiples of the line's effective increment. The
@@ -284,7 +284,7 @@ absent, it is the price per `each`. Other characteristics of a sale unit may
affect the quoted `item.price`, but do not change its sale-basis denominator.
The Business **MUST** compute the line total as
`price × quantity × 10^-scale` and round once at the line. The presented
-`totals[]` remain authoritative (see [Totals](checkout.md#totals)). The Platform
+`totals[]` remain authoritative (see [Totals](index.md#totals)). The Platform
**MUST NOT** recompute a line total from the fractional quantity and substitute
its own rounding.
@@ -410,7 +410,7 @@ platform receives messages indicating what's needed to progress.
When an active extension has outstanding work for the checkout, the Business
surfaces instances under the Action types that extension declares in the
response-only `actions` map. The common rules are defined in
-[Overview — Actions](overview.md#actions); this section states only how the
+[Overview — Actions](../../overview/index.md#actions); this section states only how the
checkout status lifecycle interprets them.
[Status Values](#status-values) is the authoritative home for the status
invariants governing outstanding Actions.
@@ -429,7 +429,7 @@ identify an outstanding Action without reporting failure. A recoverable error
Message can identify an Action to report that the requested effect was not
applied because of it. In that case, the Business returns the current Checkout
and sets the Message's `path` to the exact Action occurrence, as defined in
-[Overview — Actions](overview.md#actions). The Message does not turn the Action
+[Overview — Actions](../../overview/index.md#actions). The Message does not turn the Action
into a lock on unrelated Checkout operations.
If an Action prevents Complete Checkout from being accepted, the Business
@@ -448,7 +448,7 @@ following operation contract applies:
| Operation | Contract |
| :-------- | :------- |
| Get Checkout | The Platform **MAY** invoke Get Checkout; the Business's response is authoritative. The Platform **MAY** repeat Get Checkout with bounded backoff set by the Action contract or Platform policy, and **MUST** stop repeated requests at `expires_at`. |
-| Update Checkout | The Platform **MUST NOT** start a new Update Checkout operation. Duplicate requests remain subject to [Replay Protection](signatures.md#replay-protection). If the Business receives a new Update Checkout request, it **MUST** leave the Checkout unchanged and return the current Checkout with a recoverable error Message. |
+| Update Checkout | The Platform **MUST NOT** start a new Update Checkout operation. Duplicate requests remain subject to [Replay Protection](../../signatures.md#replay-protection). If the Business receives a new Update Checkout request, it **MUST** leave the Checkout unchanged and return the current Checkout with a recoverable error Message. |
| Complete Checkout | The Platform **MUST NOT** start a new Complete Checkout operation during `complete_in_progress`. See [Complete Checkout](#complete-checkout) for the narrow lost-response recovery retry. |
| Cancel Checkout | The Platform **MUST** follow the fallback, handoff, and cancellation race rules below before attempting Cancel Checkout. |
@@ -536,8 +536,8 @@ items are unavailable:
}
```
-See [REST](checkout-rest.md#create-checkout) and
-[MCP](checkout-mcp.md#create_checkout) binding examples.
+See [REST](rest.md#create-checkout) and
+[MCP](mcp.md#create_checkout) binding examples.
#### Error Processing Algorithm
@@ -730,11 +730,11 @@ This example is illustrative. It uses a negotiated vendor extension,
`com.example.identity.student_verification`, that declares a single Action type
under a key of the same name in `actions` and defines the instance `config` and
verification transport. It composes that extension with `context.eligibility`, a
-provisional [Discount](discount.md), an [Action](#actions), and
+provisional [Discount](../../discount.md), an [Action](#actions), and
`messages`.
The provisional discount fields (`provisional`, `eligibility`) belong to the
-[Discount extension](discount.md#eligibility-claims) and are available only when
+[Discount extension](../../discount.md#eligibility-claims) and are available only when
that extension is active for the checkout.
**1. Claim accepted, discount provisional, verification Action outstanding.**
@@ -861,7 +861,7 @@ downgrading to a notice.
* **SHOULD** provide a `code` that identifies the disclosure category
(e.g., `prop65`, `allergens`, `energy_label`). When the disclosure renders a
structured `policies[]` entry, the `code` **MUST** equal that policy's `type`
- to link the two (see [Policies](overview.md#policies)).
+ to link the two (see [Policies](../../overview/index.md#policies)).
* **SHOULD** provide `image_url` when the disclosure has an associated
visual element (e.g., warning symbol, energy class label).
* **SHOULD** provide `url` when a reference link is available for the
@@ -978,7 +978,7 @@ this format to facilitate checkout handoff and accelerated entry—for example,
platform can prefill checkout state when initiating a buy-now flow.
> **Note:** Checkout permalinks are a REST-specific construct that extends the
-> [REST transport binding](checkout-rest.md). Accessing a permalink returns a
+> [REST transport binding](rest.md). Accessing a permalink returns a
> redirect to the checkout UI or renders the checkout page directly.
## Scopes
@@ -991,7 +991,7 @@ user-authenticated access:
| `dev.ucp.shopping.checkout:manage` | All checkout operations on behalf of the authenticated user — create, update, complete, and cancel checkout sessions. |
Scope declaration, derivation, and rules for extending this set with
-custom scopes are defined in [Identity Linking — Scopes](identity-linking.md#scopes).
+custom scopes are defined in [Identity Linking — Scopes](../../common/identity-linking/index.md#scopes).
## Guidelines
@@ -1030,7 +1030,7 @@ custom scopes are defined in [Identity Linking — Scopes](identity-linking.md#s
## Capability Schema Definition
-{{ schema_fields('checkout_resp', 'checkout') }}
+{{ schema_fields('checkout_resp', 'shopping/checkout') }}
## Operations
@@ -1053,12 +1053,12 @@ To be invoked by the platform when the user has expressed purchase intent
product data (price/title etc.) provided by the business through the feeds
**SHOULD** match the actual attributes returned in the response.
-When the [Cart](cart.md) capability is negotiated, the request payload
+When the [Cart](../cart/index.md) capability is negotiated, the request payload
should accept an additional `cart_id` field for cart-to-checkout conversion. See
-[Cart → Cart-to-Checkout Conversion](cart.md#cart-to-checkout-conversion) for
+[Cart → Cart-to-Checkout Conversion](../cart/index.md#cart-to-checkout-conversion) for
the field contract.
-{{ method_fields('create_checkout', 'rest.openapi.json', 'checkout') }}
+{{ method_fields('create_checkout', 'rest.openapi.json', 'shopping/checkout') }}
### Get Checkout
@@ -1071,7 +1071,7 @@ checkout.
The platform will honor the TTL provided by the business via `expires_at` at the
time of checkout session creation.
-{{ method_fields('get_checkout', 'rest.openapi.json', 'checkout') }}
+{{ method_fields('get_checkout', 'rest.openapi.json', 'shopping/checkout') }}
### Update Checkout
@@ -1083,7 +1083,7 @@ general replacement rule does not apply during `complete_in_progress` because
Update Checkout is not permitted; see
[Accepted completion](#accepted-completion) for the frozen operation contract.
-{{ method_fields('update_checkout', 'rest.openapi.json', 'checkout') }}
+{{ method_fields('update_checkout', 'rest.openapi.json', 'shopping/checkout') }}
### Complete Checkout
@@ -1124,7 +1124,7 @@ to construct the order representation (i.e. information like `line_items`,
After the order is placed, other details will be updated through subsequent
events as the order, and its associated items, move through the supply chain.
-{{ method_fields('complete_checkout', 'rest.openapi.json', 'checkout') }}
+{{ method_fields('complete_checkout', 'rest.openapi.json', 'shopping/checkout') }}
### Cancel Checkout
@@ -1134,23 +1134,23 @@ already canceled or completed), then businesses **SHOULD** send back an error
indicating the operation is not allowed. Any checkout session with a status
that is not equal to `completed` or `canceled` **SHOULD** be cancelable.
-{{ method_fields('cancel_checkout', 'rest.openapi.json', 'checkout') }}
+{{ method_fields('cancel_checkout', 'rest.openapi.json', 'shopping/checkout') }}
## Transport Bindings
The abstract operations above are bound to specific transport protocols as
defined below:
-* [REST Binding](checkout-rest.md): RESTful API mapping using standard HTTP verbs and JSON payloads.
-* [MCP Binding](checkout-mcp.md): Model Context Protocol mapping for agentic interaction.
-* [A2A Binding](checkout-a2a.md): Agent-to-Agent Protocol mapping for agentic interactions.
-* [Embedded Checkout Binding](embedded-checkout.md): JSON-RPC for powering embedded checkout.
+* [REST Binding](rest.md): RESTful API mapping using standard HTTP verbs and JSON payloads.
+* [MCP Binding](mcp.md): Model Context Protocol mapping for agentic interaction.
+* [A2A Binding](a2a.md): Agent-to-Agent Protocol mapping for agentic interactions.
+* [Embedded Checkout Binding](embedded.md): JSON-RPC for powering embedded checkout.
## Entities
### Buyer
-{{ schema_fields('buyer', 'checkout') }}
+{{ schema_fields('buyer', 'shopping/checkout') }}
### Context
@@ -1161,7 +1161,7 @@ ignore or down-rank them if inconsistent with higher-confidence signals
controls). Eligibility and policy enforcement MUST occur at checkout time using
binding transaction data.
-{{ schema_fields('context', 'checkout') }}
+{{ schema_fields('context', 'shopping/checkout') }}
### Signals
@@ -1170,51 +1170,51 @@ and abuse prevention. Unlike `context` (buyer-asserted preferences) and `buyer`
(self-reported identity), signal values MUST NOT be buyer-asserted claims —
platforms provide signals based on direct observation or by relaying
independently verifiable third-party attestations. See
-[Signals](overview.md#signals) for details and privacy
+[Signals](../../overview/index.md#signals) for details and privacy
requirements.
-{{ schema_fields('types/signals', 'checkout') }}
+{{ schema_fields('types/signals', 'shopping/checkout') }}
### Attribution
Platform-provided referral and conversion-event context — campaign IDs,
click identifiers, and source/medium markers communicated by the platform.
-See [Attribution](overview.md#attribution) for details and consent
+See [Attribution](../../overview/index.md#attribution) for details and consent
requirements.
-{{ schema_fields('types/attribution', 'checkout') }}
+{{ schema_fields('types/attribution', 'shopping/checkout') }}
### Item
#### Item Create Request
-{{ schema_fields('types/item_create_req', 'checkout') }}
+{{ schema_fields('types/item_create_req', 'shopping/checkout') }}
#### Item Update Request
-{{ schema_fields('types/item_update_req', 'checkout') }}
+{{ schema_fields('types/item_update_req', 'shopping/checkout') }}
#### Item
-{{ schema_fields('types/item_resp', 'checkout') }}
+{{ schema_fields('types/item_resp', 'shopping/checkout') }}
### Line Item
#### Line Item Create Request
-{{ schema_fields('types/line_item_create_req', 'checkout') }}
+{{ schema_fields('types/line_item_create_req', 'shopping/checkout') }}
#### Line Item Update Request
-{{ schema_fields('types/line_item_update_req', 'checkout') }}
+{{ schema_fields('types/line_item_update_req', 'shopping/checkout') }}
#### Line Item
-{{ schema_fields('types/line_item_resp', 'checkout') }}
+{{ schema_fields('types/line_item_resp', 'shopping/checkout') }}
### Link
-{{ schema_fields('types/link', 'checkout') }}
+{{ schema_fields('types/link', 'shopping/checkout') }}
#### Well-Known Link Types
@@ -1238,53 +1238,53 @@ field or omitting them.
Policies (return/refund terms, warranty, and the like) that apply to the items
in this checkout. JSONPath targets in `applies_to` are relative to
this response root (e.g., `$.line_items[0]`). See
-[Policies](overview.md#policies) for the full model.
+[Policies](../../overview/index.md#policies) for the full model.
-{{ schema_fields('types/policy', 'checkout') }}
+{{ schema_fields('types/policy', 'shopping/checkout') }}
### Message
-{{ schema_fields('message', 'checkout') }}
+{{ schema_fields('message', 'shopping/checkout') }}
### Message Error
-{{ schema_fields('types/message_error', 'checkout') }}
+{{ schema_fields('types/message_error', 'shopping/checkout') }}
#### Error Code
-{{ schema_fields('types/error_code', 'checkout') }}
+{{ schema_fields('types/error_code', 'shopping/checkout') }}
### Message Info
-{{ schema_fields('types/message_info', 'checkout') }}
+{{ schema_fields('types/message_info', 'shopping/checkout') }}
### Message Warning
-{{ schema_fields('types/message_warning', 'checkout') }}
+{{ schema_fields('types/message_warning', 'shopping/checkout') }}
### Payment
-{{ schema_fields('payment', 'checkout') }}
+{{ schema_fields('payment', 'shopping/checkout') }}
#### Selected Payment Instrument
-{{ extension_schema_fields('types/payment_instrument.json#/$defs/selected_payment_instrument', 'checkout') }}
+{{ extension_schema_fields('types/payment_instrument.json#/$defs/selected_payment_instrument', 'shopping/checkout') }}
### Payment Credential
-{{ schema_fields('payment_credential', 'checkout') }}
+{{ schema_fields('payment_credential', 'shopping/checkout') }}
### Postal Address
-{{ schema_fields('postal_address', 'checkout') }}
+{{ schema_fields('postal_address', 'shopping/checkout') }}
### Response
-{{ extension_schema_fields('capability.json#/$defs/response_schema', 'checkout') }}
+{{ extension_schema_fields('capability.json#/$defs/response_schema', 'shopping/checkout') }}
### Total {: #totals }
-{{ schema_fields('types/total_resp', 'checkout') }}
+{{ schema_fields('types/total_resp', 'shopping/checkout') }}
#### Rendering Contract
@@ -1425,12 +1425,12 @@ when provided.
### UCP Response Checkout {: #ucp-response-checkout-schema }
-{{ extension_schema_fields('ucp.json#/$defs/response_checkout_schema', 'checkout') }}
+{{ extension_schema_fields('ucp.json#/$defs/response_checkout_schema', 'shopping/checkout') }}
### Order Confirmation
-{{ schema_fields('order_confirmation', 'checkout') }}
+{{ schema_fields('order_confirmation', 'shopping/checkout') }}
### Error Response
-{{ schema_fields('types/error_response', 'checkout') }}
+{{ schema_fields('types/error_response', 'shopping/checkout') }}
diff --git a/docs/specification/checkout-mcp.md b/docs/specification/shopping/checkout/mcp.md
similarity index 90%
rename from docs/specification/checkout-mcp.md
rename to docs/specification/shopping/checkout/mcp.md
index c306afab3..a511d30d1 100644
--- a/docs/specification/checkout-mcp.md
+++ b/docs/specification/shopping/checkout/mcp.md
@@ -17,7 +17,7 @@
# Checkout Capability - MCP Binding
This document specifies the Model Context Protocol (MCP) binding for the
-[Checkout Capability](checkout.md).
+[Checkout Capability](index.md).
## Protocol Fundamentals
@@ -46,7 +46,7 @@ Businesses advertise MCP transport availability through their UCP profile at
"dev.ucp.shopping.checkout": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/checkout",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/checkout",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/checkout.json"
}
],
@@ -104,7 +104,7 @@ protocol metadata:
```
The `meta["ucp-agent"]` field is **required** on all requests to enable
-[capability negotiation](overview.md#negotiation-protocol). The
+[capability negotiation](../../overview/index.md#negotiation-protocol). The
`complete_checkout` and `cancel_checkout` operations also require
`meta["idempotency-key"]` for retry safety. Platforms **MAY** include
additional metadata fields.
@@ -126,29 +126,29 @@ MCP tools separate resource identification from payload data:
| Tool | Operation | Description |
| :------------------ | :------------------------------------------------- | :------------------------- |
-| `create_checkout` | [Create Checkout](checkout.md#create-checkout) | Create a checkout session. |
-| `get_checkout` | [Get Checkout](checkout.md#get-checkout) | Get a checkout session. |
-| `update_checkout` | [Update Checkout](checkout.md#update-checkout) | Update a checkout session. |
-| `complete_checkout` | [Complete Checkout](checkout.md#complete-checkout) | Place the order. |
-| `cancel_checkout` | [Cancel Checkout](checkout.md#cancel-checkout) | Cancel a checkout session. |
+| `create_checkout` | [Create Checkout](index.md#create-checkout) | Create a checkout session. |
+| `get_checkout` | [Get Checkout](index.md#get-checkout) | Get a checkout session. |
+| `update_checkout` | [Update Checkout](index.md#update-checkout) | Update a checkout session. |
+| `complete_checkout` | [Complete Checkout](index.md#complete-checkout) | Place the order. |
+| `cancel_checkout` | [Cancel Checkout](index.md#cancel-checkout) | Cancel a checkout session. |
### `create_checkout`
-Maps to the [Create Checkout](checkout.md#create-checkout) operation.
+Maps to the [Create Checkout](index.md#create-checkout) operation.
#### Input Schema
-* `checkout` ([Checkout](checkout.md#create-checkout)): **Required**. Contains
+* `checkout` ([Checkout](index.md#create-checkout)): **Required**. Contains
the initial checkout session data and optional extensions.
* Extensions (Optional):
- * `dev.ucp.shopping.buyer_consent`: [Buyer Consent](buyer-consent.md)
- * `dev.ucp.shopping.fulfillment`: [Fulfillment](fulfillment.md)
- * `dev.ucp.shopping.discount`: [Discount](discount.md)
- * `dev.ucp.shopping.ap2_mandate`: [AP2 Mandates](ap2-mandates.md)
+ * `dev.ucp.shopping.buyer_consent`: [Buyer Consent](../../buyer-consent.md)
+ * `dev.ucp.shopping.fulfillment`: [Fulfillment](../../fulfillment.md)
+ * `dev.ucp.shopping.discount`: [Discount](../../discount.md)
+ * `dev.ucp.shopping.ap2_mandate`: [AP2 Mandates](../../ap2-mandates.md)
#### Output Schema
-* [Checkout](checkout.md#create-checkout) object.
+* [Checkout](index.md#create-checkout) object.
#### Example
@@ -375,7 +375,7 @@ Maps to the [Create Checkout](checkout.md#create-checkout) operation.
### `get_checkout`
-Maps to the [Get Checkout](checkout.md#get-checkout) operation.
+Maps to the [Get Checkout](index.md#get-checkout) operation.
#### Input Schema
@@ -383,32 +383,32 @@ Maps to the [Get Checkout](checkout.md#get-checkout) operation.
#### Output Schema
-* [Checkout](checkout.md#get-checkout) object.
+* [Checkout](index.md#get-checkout) object.
### `update_checkout`
-Maps to the [Update Checkout](checkout.md#update-checkout) operation.
+Maps to the [Update Checkout](index.md#update-checkout) operation.
The Platform **MUST NOT** start a new `update_checkout` operation while the
Checkout is `complete_in_progress`. Duplicate requests remain subject to
-[Replay Protection](signatures.md#replay-protection). If the Business receives a
+[Replay Protection](../../signatures.md#replay-protection). If the Business receives a
new `update_checkout` request in that state, it **MUST** leave the Checkout
unchanged and return the current Checkout with a recoverable error Message.
#### Input Schema
* `id` (String): **Required**. The ID of the checkout session to update.
-* `checkout` ([Checkout](checkout.md#update-checkout)): **Required**.
+* `checkout` ([Checkout](index.md#update-checkout)): **Required**.
Contains the updated checkout session data.
* Extensions (Optional):
- * `dev.ucp.shopping.buyer_consent`: [Buyer Consent](buyer-consent.md)
- * `dev.ucp.shopping.fulfillment`: [Fulfillment](fulfillment.md)
- * `dev.ucp.shopping.discount`: [Discount](discount.md)
- * `dev.ucp.shopping.ap2_mandate`: [AP2 Mandates](ap2-mandates.md)
+ * `dev.ucp.shopping.buyer_consent`: [Buyer Consent](../../buyer-consent.md)
+ * `dev.ucp.shopping.fulfillment`: [Fulfillment](../../fulfillment.md)
+ * `dev.ucp.shopping.discount`: [Discount](../../discount.md)
+ * `dev.ucp.shopping.ap2_mandate`: [AP2 Mandates](../../ap2-mandates.md)
#### Output Schema
-* [Checkout](checkout.md#update-checkout) object.
+* [Checkout](index.md#update-checkout) object.
#### Example
@@ -605,7 +605,7 @@ unchanged and return the current Checkout with a recoverable error Message.
### `complete_checkout`
-Maps to the [Complete Checkout](checkout.md#complete-checkout) operation.
+Maps to the [Complete Checkout](index.md#complete-checkout) operation.
#### Input Schema
@@ -613,18 +613,18 @@ Maps to the [Complete Checkout](checkout.md#complete-checkout) operation.
* `ucp-agent` (Object): **Required**. Platform agent identification.
* `idempotency-key` (String, UUID): **Required**. Unique key for retry safety.
* `id` (String): **Required**. The ID of the checkout session.
-* `checkout` ([Checkout](checkout.md#complete-checkout)): **Required**.
+* `checkout` ([Checkout](index.md#complete-checkout)): **Required**.
Contains payment credentials and other finalization data to execute the transaction.
#### Output Schema
-* [Checkout](checkout.md#complete-checkout) object. See core
- [Complete Checkout](checkout.md#complete-checkout) for status and `order`
+* [Checkout](index.md#complete-checkout) object. See core
+ [Complete Checkout](index.md#complete-checkout) for status and `order`
semantics.
### `cancel_checkout`
-Maps to the [Cancel Checkout](checkout.md#cancel-checkout) operation.
+Maps to the [Cancel Checkout](index.md#cancel-checkout) operation.
#### Input Schema
@@ -635,12 +635,12 @@ Maps to the [Cancel Checkout](checkout.md#cancel-checkout) operation.
#### Output Schema
-* [Checkout](checkout.md#cancel-checkout) object with `status: canceled`.
+* [Checkout](index.md#cancel-checkout) object with `status: canceled`.
## Error Handling
UCP distinguishes between protocol errors and business outcomes. See the
-[Core Specification](overview.md#error-handling) for the complete error code
+[Core Specification](../../overview/index.md#error-handling) for the complete error code
registry and transport binding examples.
* **Protocol errors**: Transport-level failures (authentication, rate limiting,
@@ -736,7 +736,7 @@ JSON-RPC `result` with `structuredContent` containing the UCP envelope and `mess
Platforms **SHOULD** authenticate agents when using MCP transport. When using
HTTP Message Signatures, all checkout operations follow the
-[Message Signatures](signatures.md) specification.
+[Message Signatures](../../signatures.md) specification.
### Request Signing
@@ -771,7 +771,7 @@ Signature: sig1=:6G4i8TS6oUkGrx8KnCFUpsSPwd74...:
The `Content-Digest` binds the JSON-RPC body to the signature. No JSON
canonicalization is required.
-See [Message Signatures - MCP Transport](signatures.md#mcp-transport)
+See [Message Signatures - MCP Transport](../../signatures.md#mcp-transport)
for details.
### Response Signing
@@ -796,7 +796,7 @@ Signature: sig1=:6G4i8TS6oUkGrx8KnCFUpsSPwd74...:
{"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"..."}],"structuredContent":{"id":"checkout_abc123","status":"completed"}}}
```
-See [Message Signatures - REST Response Signing](signatures.md#rest-response-signing)
+See [Message Signatures - REST Response Signing](../../signatures.md#rest-response-signing)
for the signing algorithm (identical for MCP over HTTP).
## Conformance
@@ -805,7 +805,7 @@ A conforming MCP transport implementation **MUST**:
1. Implement JSON-RPC 2.0 protocol correctly.
2. Provide all core checkout tools defined in this specification.
-3. Return errors per the [Core Specification](overview.md#error-handling).
+3. Return errors per the [Core Specification](../../overview/index.md#error-handling).
4. Return business outcomes as JSON-RPC `result` with UCP envelope and
`messages` array.
5. Validate tool inputs against UCP schemas.
@@ -814,7 +814,7 @@ A conforming MCP transport implementation **MUST**:
A conforming implementation **SHOULD**:
1. Authenticate agents using one of the supported mechanisms (API keys, OAuth,
- mTLS, or HTTP Message Signatures per [Message Signatures](signatures.md)).
+ mTLS, or HTTP Message Signatures per [Message Signatures](../../signatures.md)).
2. Verify authentication on incoming requests before processing.
## Implementation
diff --git a/docs/specification/checkout-rest.md b/docs/specification/shopping/checkout/rest.md
similarity index 97%
rename from docs/specification/checkout-rest.md
rename to docs/specification/shopping/checkout/rest.md
index a29ce4b55..3f8023f4a 100644
--- a/docs/specification/checkout-rest.md
+++ b/docs/specification/shopping/checkout/rest.md
@@ -17,7 +17,7 @@
# Checkout Capability - REST Binding
This document specifies the REST binding for the
-[Checkout Capability](checkout.md).
+[Checkout Capability](index.md).
## Protocol Fundamentals
@@ -46,7 +46,7 @@ Businesses advertise REST transport availability through their UCP profile at
"dev.ucp.shopping.checkout": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/checkout",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/checkout",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/checkout.json"
}
]
@@ -80,11 +80,11 @@ All REST endpoints **MUST** be served over HTTPS with minimum TLS version
| Operation | Method | Endpoint | Description |
| :------------------------------------------------- | :----- | :--------------------------------- | :------------------------- |
-| [Create Checkout](checkout.md#create-checkout) | `POST` | `/checkout-sessions` | Create a checkout session. |
-| [Get Checkout](checkout.md#get-checkout) | `GET` | `/checkout-sessions/{id}` | Get a checkout session. |
-| [Update Checkout](checkout.md#update-checkout) | `PUT` | `/checkout-sessions/{id}` | Update a checkout session. |
-| [Complete Checkout](checkout.md#complete-checkout) | `POST` | `/checkout-sessions/{id}/complete` | Place the order. |
-| [Cancel Checkout](checkout.md#cancel-checkout) | `POST` | `/checkout-sessions/{id}/cancel` | Cancel a checkout session. |
+| [Create Checkout](index.md#create-checkout) | `POST` | `/checkout-sessions` | Create a checkout session. |
+| [Get Checkout](index.md#get-checkout) | `GET` | `/checkout-sessions/{id}` | Get a checkout session. |
+| [Update Checkout](index.md#update-checkout) | `PUT` | `/checkout-sessions/{id}` | Update a checkout session. |
+| [Complete Checkout](index.md#complete-checkout) | `POST` | `/checkout-sessions/{id}/complete` | Place the order. |
+| [Cancel Checkout](index.md#cancel-checkout) | `POST` | `/checkout-sessions/{id}/cancel` | Cancel a checkout session. |
## Examples
@@ -233,7 +233,7 @@ entire Checkout resource, including any data updates to write-only fields; the
supplied resource replaces the existing Checkout session state. The Platform
**MUST NOT** start a new Update Checkout operation while the Checkout is
`complete_in_progress`. Duplicate requests remain subject to
-[Replay Protection](signatures.md#replay-protection). If the Business receives a
+[Replay Protection](../../signatures.md#replay-protection). If the Business receives a
new Update Checkout request in that state, it **MUST** leave the Checkout
unchanged and return the current Checkout with a recoverable error Message.
@@ -780,7 +780,7 @@ addresses (i.e. `fulfillment_address`, `billing_address`), this is the right
place to set these expectations via `messages`.
The response is the Checkout object; the example below shows the synchronous
-`completed` case. See core [Complete Checkout](checkout.md#complete-checkout)
+`completed` case. See core [Complete Checkout](index.md#complete-checkout)
for status and `order` semantics.
=== "Request"
@@ -1313,7 +1313,7 @@ operations unless otherwise noted.
1. Store the key with the operation result for at least 24 hours.
2. Return the cached result for duplicate keys whose request body matches the original.
3. Return `409 Conflict` if the key is reused with a mismatched body.
- See [Message Signatures — Idempotency Key Requirements](signatures.md#replay-protection)
+ See [Message Signatures — Idempotency Key Requirements](../../signatures.md#replay-protection)
for the full payload-matching contract.
## Protocol Mechanics
@@ -1339,7 +1339,7 @@ request.
### Error Responses
-See the [Core Specification](overview.md#error-handling) for the complete error
+See the [Core Specification](../../overview/index.md#error-handling) for the complete error
code registry and transport binding examples.
* **Protocol errors**: Return appropriate HTTP status code (401, 403, 409, 429,
@@ -1415,7 +1415,7 @@ HTTP 200 and the UCP envelope containing `messages`
Platforms **MAY** choose among authentication mechanisms (API keys, OAuth,
mTLS, HTTP Message Signatures). When using
HTTP Message Signatures, checkout operations follow the
-[Message Signatures](signatures.md) specification.
+[Message Signatures](../../signatures.md) specification.
### Request Signing
@@ -1446,7 +1446,7 @@ Signature: sig1=:6G4i8TS6oUkGrx8KnCFUpsSPwd74...:
{"line_items":[{"item":{"id":"item_123"},"quantity":2}]}
```
-See [Message Signatures - REST Request Signing](signatures.md#rest-request-signing)
+See [Message Signatures - REST Request Signing](../../signatures.md#rest-request-signing)
for the complete signing algorithm.
### Response Signing
@@ -1471,7 +1471,7 @@ Signature: sig1=:6G4i8TS6oUkGrx8KnCFUpsSPwd74...:
{"id":"chk_123","status":"completed","order":{"id":"ord_456"}}
```
-See [Message Signatures - REST Response Signing](signatures.md#rest-response-signing)
+See [Message Signatures - REST Response Signing](../../signatures.md#rest-response-signing)
for the complete signing algorithm.
## Security Considerations
@@ -1485,7 +1485,7 @@ authentication is required, the REST transport **MAY** use:
2. **API Keys**: Via `X-API-Key` header.
3. **OAuth 2.0**: Via `Authorization: Bearer {token}` header. Identifies the
platform for agent-authenticated access, or both platform and user for
- user-authenticated access (see [Identity Linking](identity-linking.md)).
+ user-authenticated access (see [Identity Linking](../../common/identity-linking/index.md)).
4. **Mutual TLS**: For high-security environments.
5. **HTTP Message Signatures**: Per [RFC 9421](https://www.rfc-editor.org/rfc/rfc9421)
(see [Message Signing](#message-signing) above).
diff --git a/docs/specification/order.md b/docs/specification/shopping/order/index.md
similarity index 92%
rename from docs/specification/order.md
rename to docs/specification/shopping/order/index.md
index 1a5c2e657..91514c40a 100644
--- a/docs/specification/order.md
+++ b/docs/specification/shopping/order/index.md
@@ -58,7 +58,7 @@ Line items reflect what was purchased at checkout and their current state:
* Item details (product, price, quantity ordered)
* Quantity counts and fulfillment status — `original`, `total`, and `fulfilled`
are integer step counts of the item's inherited `quantity_unit` under the
- shared [quantities and units](overview.md#quantities-and-units) contract; an
+ shared [quantities and units](../../overview/index.md#quantities-and-units) contract; an
absent `quantity_unit` means the quantities count whole items (`each`) at
`scale` 0
@@ -66,7 +66,7 @@ All order lifecycle arithmetic over quantities operates on sale-basis step
counts inherited from the item; other item characteristics do not enter that
arithmetic. Business-recorded quantities — fulfillment events, adjustments, and
revised totals — are bounded only by `scale`: a declared ordering
-[`increment`](overview.md#ordering-increment) binds Platform requests at cart
+[`increment`](../../overview/index.md#ordering-increment) binds Platform requests at cart
and checkout and does not constrain what the Business records (a 0.25-lb
ordering increment does not prevent recording an actual picked weight of
1.90 lb).
@@ -104,13 +104,13 @@ Expectations can be split, merged, or adjusted post-order. For example:
Businesses MAY surface a snapshot of the originating checkout's
`attribution` on the order. Read-only on the order — agents do not write
-`order.attribution`. See [Attribution](overview.md#attribution) for the
+`order.attribution`. See [Attribution](../../overview/index.md#attribution) for the
underlying contract.
### Policies
Businesses MAY surface a snapshot of the policies that applied at checkout on
-the order. See [Policies](overview.md#policies) for the underlying contract.
+the order. See [Policies](../../overview/index.md#policies) for the underlying contract.
### Adjustments
@@ -131,13 +131,13 @@ fulfillment:
### Order
-{{ schema_fields('order', 'order') }}
+{{ schema_fields('order', 'shopping/order') }}
### Order Line Item
Line items reflect what was purchased at checkout and their current state.
-{{ schema_fields('order_line_item', 'order') }}
+{{ schema_fields('order_line_item', 'shopping/order') }}
**Quantity Structure:**
@@ -173,7 +173,7 @@ Expectations are buyer-facing groupings representing when/how items will be
delivered. They represent the current promise to the buyer and can be
split, merged, or adjusted post-order.
-{{ schema_fields('expectation', 'order') }}
+{{ schema_fields('expectation', 'shopping/order') }}
### Fulfillment Event
@@ -181,7 +181,7 @@ Events are append-only records tracking actual shipments. The `type` field is
an open string - businesses can use any values that make sense for their
fulfillment process.
-{{ schema_fields('fulfillment_event', 'order') }}
+{{ schema_fields('fulfillment_event', 'shopping/order') }}
Examples: `processing`, `shipped`, `in_transit`, `delivered`, `failed_attempt`,
`canceled`, `undeliverable`, `returned_to_sender`, etc.
@@ -192,7 +192,7 @@ Adjustments are polymorphic events that exist independently of fulfillment.
The `type` field is an open string - businesses can use any values that make
sense to them.
-{{ schema_fields('adjustment', 'order') }}
+{{ schema_fields('adjustment', 'shopping/order') }}
Examples: `refund`, `return`, `credit`, `price_adjustment`, `dispute`,
`cancellation`, etc.
@@ -375,7 +375,7 @@ Some items are sold by count but priced by measurement — apples at $2.00/lb,
sold per `each`, with a nominal per-apple weight. Two bases are in play, and
both travel: the sale basis governs `quantity` (whole apples, lifecycle
arithmetic untouched), and the pricing basis — the line's echoed
-[`unit_price`](checkout.md#quantity-and-sale-basis) — carries the rate and
+[`unit_price`](../checkout/index.md#quantity-and-sale-basis) — carries the rate and
nominal measure the charge is computed from. When the price settles against an
actual measurement, the adjustment **MUST** carry the settled `measure`; its
unit identity **MUST** match the pricing basis (no conversion), and a pure
@@ -473,7 +473,7 @@ counts throughout.
A Buyer orders 2.00 lb of the same bananas at $0.79/lb, sold in quarter-pound
increments (`quantity` `200`, line total `79 × 2.00 = 158`). The picker weighs
out 1.90 lb — an off-increment fact, recorded as-is, because the
-[`increment`](overview.md#ordering-increment) binds Platform ordering, not
+[`increment`](../../overview/index.md#ordering-increment) binds Platform ordering, not
Business records. The fulfillment event records the actual `190` steps, and a
`price_adjustment` of `-10` steps reconciles `total` to the actual pick with
its price delta (`79 × 0.10 = 7.9`, rounded once to `8`). `fulfilled == total`
@@ -547,7 +547,7 @@ user-authenticated access:
| `dev.ucp.shopping.order:manage` | Post-purchase operations on the user's orders — cancellation, returns, and other modifications. |
Scope declaration, derivation, and rules for extending this set with
-custom scopes are defined in [Identity Linking — Scopes](identity-linking.md#scopes).
+custom scopes are defined in [Identity Linking — Scopes](../../common/identity-linking/index.md#scopes).
## Operations
@@ -566,8 +566,8 @@ cases.
| :-------------------------------------- | :----- | :------------- | :-------------------------------------- |
| [Get Order](#get-order) | `GET` | `/orders/{id}` | Platform retrieves current order state. |
-For transport-specific details, see [REST Binding](order-rest.md), and
-[MCP Binding](order-mcp.md)
+For transport-specific details, see [REST Binding](rest.md), and
+[MCP Binding](mcp.md)
### Get Order
@@ -578,7 +578,7 @@ Returns the current-state snapshot of an order.
The business **MUST** authenticate requests to order data before returning a
response, using any supported UCP mechanism - API keys, OAuth 2.0, mutual
TLS, or HTTP Message Signatures (see
-[Identity and Authentication](checkout-rest.md#authentication)). The
+[Identity and Authentication](../checkout/rest.md#authentication)). The
authentication method determines which orders are accessible to the
caller:
@@ -594,7 +594,7 @@ observed the order confirmation, and is retrieving the latest state of an
order it already has context for.
**Buyer authorization** - the platform obtains buyer authorization via
-[Identity Linking](identity-linking.md) with the necessary scopes, or a
+[Identity Linking](../../common/identity-linking/index.md) with the necessary scopes, or a
similar mechanism. This grants access to the buyer's orders regardless of
which platform originated them.
@@ -687,7 +687,7 @@ during partner onboarding. The URL format is platform-specific.
Headers follow **[Standard Webhooks](https://www.standardwebhooks.com/){ target="_blank" }**;
except for request signing, which follows [RFC 9421](https://www.rfc-editor.org/rfc/rfc9421).
-See [Message Signatures](signatures.md) for more details.
+See [Message Signatures](../../signatures.md) for more details.
**Required Headers:**
@@ -696,7 +696,7 @@ See [Message Signatures](signatures.md) for more details.
| `Webhook-Timestamp` | Event occurrence timestamp (unix) |
| `Webhook-Id` | Unique event identifier |
-{{ method_fields('order_event_webhook', 'rest.openapi.json', 'order') }}
+{{ method_fields('order_event_webhook', 'rest.openapi.json', 'shopping/order') }}
### Webhook URL Configuration
@@ -704,7 +704,7 @@ The platform provides its webhook URL in the order capability's `config` field
during capability negotiation. The business discovers this URL from the
platform's profile and uses it to send order lifecycle events.
-{{ extension_schema_fields('order.json#/$defs/platform_schema', 'order') }}
+{{ extension_schema_fields('order.json#/$defs/platform_schema', 'shopping/order') }}
**Example:**
@@ -714,7 +714,7 @@ platform's profile and uses it to send order lifecycle events.
"dev.ucp.shopping.order": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/order",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/order",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/order.json",
"config": {
"webhook_url": "https://platform.example.com/webhooks/ucp/orders"
@@ -728,7 +728,7 @@ platform's profile and uses it to send order lifecycle events.
Webhook payloads **MUST** be signed by the business and verified by the platform
to ensure authenticity and integrity. Signatures follow the
-[Message Signatures](signatures.md) specification using the REST binding
+[Message Signatures](../../signatures.md) specification using the REST binding
(RFC 9421).
**Required Headers:**
@@ -761,7 +761,7 @@ Signature: sig1=:MEUCIQDTxNq8h7LGHpvVZQp1iHkFp9+3N8Mxk2zH1wK4YuVN8w...:
3. Sign using a key from `keys` in the business's UCP profile
4. Set `Signature-Input` and `Signature` headers
-See [Message Signatures - REST Request Signing](signatures.md#rest-request-signing)
+See [Message Signatures - REST Request Signing](../../signatures.md#rest-request-signing)
for complete algorithm.
#### Verification (Platform)
@@ -774,7 +774,7 @@ for complete algorithm.
4. Verify `Content-Digest` matches SHA-256 of raw body
5. Reconstruct signature base and verify signature
-See [Message Signatures - REST Request Verification](signatures.md#rest-request-verification)
+See [Message Signatures - REST Request Verification](../../signatures.md#rest-request-verification)
for complete algorithm.
**Authorization** (order ownership):
@@ -791,7 +791,7 @@ business's orders, even with a valid signature.
#### Key Rotation
-See [Message Signatures - Key Rotation](signatures.md#key-rotation) for
+See [Message Signatures - Key Rotation](../../signatures.md#key-rotation) for
zero-downtime key rotation procedures.
### Guidelines {: #events-guidelines }
@@ -805,7 +805,7 @@ zero-downtime key rotation procedures.
* **MUST** include `UCP-Agent` header with profile URL for signer identification
* **MUST** sign all webhook payloads per the
- [Message Signatures](signatures.md) specification using RFC 9421 headers
+ [Message Signatures](../../signatures.md) specification using RFC 9421 headers
(`Signature`, `Signature-Input`, `Content-Digest`)
* **MUST** send "Order created" event with fully populated order entity
* **MUST** send full order entity on updates (not incremental deltas)
@@ -815,20 +815,20 @@ zero-downtime key rotation procedures.
### Item
-{{ schema_fields('types/item_resp', 'order') }}
+{{ schema_fields('types/item_resp', 'shopping/order') }}
### Postal Address
-{{ schema_fields('postal_address', 'order') }}
+{{ schema_fields('postal_address', 'shopping/order') }}
### Response
-{{ extension_schema_fields('capability.json#/$defs/response_schema', 'order') }}
+{{ extension_schema_fields('capability.json#/$defs/response_schema', 'shopping/order') }}
### Total
-{{ schema_fields('types/total_resp', 'order') }}
+{{ schema_fields('types/total_resp', 'shopping/order') }}
### UCP Response Order Schema {: #ucp-response-order-schema }
-{{ extension_schema_fields('ucp.json#/$defs/response_order_schema', 'order') }}
+{{ extension_schema_fields('ucp.json#/$defs/response_order_schema', 'shopping/order') }}
diff --git a/docs/specification/order-mcp.md b/docs/specification/shopping/order/mcp.md
similarity index 94%
rename from docs/specification/order-mcp.md
rename to docs/specification/shopping/order/mcp.md
index 34041e0e0..630a26506 100644
--- a/docs/specification/order-mcp.md
+++ b/docs/specification/shopping/order/mcp.md
@@ -17,7 +17,7 @@
# Order Capability - MCP Binding
This document specifies the Model Context Protocol (MCP) binding for the
-[Order Capability](order.md).
+[Order Capability](index.md).
## Protocol Fundamentals
@@ -46,7 +46,7 @@ Businesses advertise MCP transport availability through their UCP profile at
"dev.ucp.shopping.order": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/order",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/order",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/order.json"
}
]
@@ -82,7 +82,7 @@ protocol metadata:
```
The `meta["ucp-agent"]` field is **required** on all requests to enable
-[capability negotiation](overview.md#negotiation-protocol). Platforms **MAY**
+[capability negotiation](../../overview/index.md#negotiation-protocol). Platforms **MAY**
include additional metadata fields.
## Tools
@@ -91,11 +91,11 @@ UCP Capabilities map 1:1 to MCP Tools.
| Tool | Operation | Description |
| :---- | :---- | :---- |
-| `get_order` | [Get Order](order.md#get-order) | Get the current state of an order. |
+| `get_order` | [Get Order](index.md#get-order) | Get the current state of an order. |
### `get_order`
-Maps to the [Get Order](order.md#get-order) operation. Returns the
+Maps to the [Get Order](index.md#get-order) operation. Returns the
current-state snapshot of an order.
#### Input Schema
@@ -105,7 +105,7 @@ current-state snapshot of an order.
#### Output Schema
-{{ schema_fields('order', 'order') }}
+{{ schema_fields('order', 'shopping/order') }}
#### Example
@@ -297,7 +297,7 @@ Platforms implementing the MCP binding:
Businesses implementing the MCP binding:
* **MUST** implement the `get_order` tool per the
- [OpenRPC schema](https://ucp.dev/services/shopping/mcp.openrpc.json)
+ [OpenRPC schema]()
-See [Order Capability - Guidelines](order.md#operations-guidelines) for
+See [Order Capability - Guidelines](index.md#operations-guidelines) for
capability-level requirements that apply across all transports.
diff --git a/docs/specification/order-rest.md b/docs/specification/shopping/order/rest.md
similarity index 93%
rename from docs/specification/order-rest.md
rename to docs/specification/shopping/order/rest.md
index b93477d04..48a77fe27 100644
--- a/docs/specification/order-rest.md
+++ b/docs/specification/shopping/order/rest.md
@@ -16,7 +16,7 @@
# Order Capability - REST Binding
-This document specifies the REST binding for the [Order Capability](order.md).
+This document specifies the REST binding for the [Order Capability](index.md).
## Protocol Fundamentals
@@ -45,7 +45,7 @@ Businesses advertise REST transport availability through their UCP profile at
"dev.ucp.shopping.order": [
{
"version": "{{ ucp_version }}",
- "spec": "https://ucp.dev/{{ ucp_version }}/specification/order",
+ "spec": "https://ucp.dev/{{ ucp_version }}/specification/shopping/order",
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/order.json"
}
]
@@ -79,7 +79,7 @@ All REST endpoints **MUST** be served over HTTPS with minimum TLS version 1.3.
| [Get Order](#get-order) | `GET` | `/orders/{id}` | Get the current state of an order. |
For the Order Event Webhook (business -> platform push), see the
-[Order Capability overview](order.md#order-event-webhook).
+[Order Capability overview](index.md#order-event-webhook).
### Get Order
@@ -91,7 +91,7 @@ Returns the current-state snapshot of an order.
#### Output Schema
-{{ schema_fields('order', 'order') }}
+{{ schema_fields('order', 'shopping/order') }}
#### Example
@@ -244,10 +244,10 @@ UCP-Agent: profile="https://platform.example/.well-known/ucp"
## Message Signing
Request and response signatures follow the
-[Message Signatures](signatures.md) specification using RFC 9421 HTTP Message
+[Message Signatures](../../signatures.md) specification using RFC 9421 HTTP Message
Signatures. See
-[REST Request Signing](signatures.md#rest-request-signing) and
-[REST Request Verification](signatures.md#rest-request-verification) for
+[REST Request Signing](../../signatures.md#rest-request-signing) and
+[REST Request Verification](../../signatures.md#rest-request-verification) for
the complete algorithm.
## Conformance
@@ -264,7 +264,7 @@ Businesses implementing the REST binding:
* **MUST** serve all endpoints over HTTPS with TLS 1.3+
* **SHOULD** sign responses per the
- [Message Signatures](signatures.md) specification
+ [Message Signatures](../../signatures.md) specification
-See [Order Capability - Guidelines](order.md#operations-guidelines) for
+See [Order Capability - Guidelines](index.md#operations-guidelines) for
capability-level requirements that apply across all transports.
diff --git a/docs/specification/playground.md b/docs/specification/shopping/playground.md
similarity index 99%
rename from docs/specification/playground.md
rename to docs/specification/shopping/playground.md
index 38d154c9d..b13992c24 100644
--- a/docs/specification/playground.md
+++ b/docs/specification/shopping/playground.md
@@ -490,14 +490,14 @@ const UcpData = {
"dev.ucp.shopping.checkout": [
{
version: "{{ ucp_version }}",
- spec: "https://ucp.dev/{{ ucp_version }}/specification/checkout",
+ spec: "https://ucp.dev/{{ ucp_version }}/specification/shopping/checkout",
schema: "https://ucp.dev/{{ ucp_version }}/schemas/shopping/checkout.json"
}
],
"dev.ucp.shopping.order": [
{
version: "{{ ucp_version }}",
- spec: "https://ucp.dev/{{ ucp_version }}/specification/order",
+ spec: "https://ucp.dev/{{ ucp_version }}/specification/shopping/order",
schema: "https://ucp.dev/{{ ucp_version }}/schemas/shopping/order.json"
}
],
diff --git a/docs/specification/signatures.md b/docs/specification/signatures.md
index f2465bd57..4593cdc28 100644
--- a/docs/specification/signatures.md
+++ b/docs/specification/signatures.md
@@ -25,7 +25,7 @@ This specification defines how to sign and verify UCP messages using
[RFC 9421](https://www.rfc-editor.org/rfc/rfc9421) HTTP Message Signatures.
For UCP's identity model, supported authentication mechanisms, and key
discovery protocol, see
-[Identity & Authentication](overview.md#identity-authentication).
+[Identity & Authentication](overview/index.md#identity-authentication).
HTTP Message Signatures protect against:
@@ -105,7 +105,7 @@ additive option that unlocks Web Bot Auth (WBA) interop.
remains unusable to that verifier. A signature that references such a
key fails with `algorithm_unsupported` (and, in a multi-signature
request, is skipped per the [Identity Resolution
- Algorithm](overview.md#identity-resolution-algorithm)).
+ Algorithm](overview/index.md#identity-resolution-algorithm)).
**Usage guidance:**
@@ -132,7 +132,7 @@ algorithm constraints — for example, a WBA verifier that accepts only
Ed25519 together with an AP2 mandate algorithm requirement that excludes
it (see [AP2 Mandates](ap2-mandates.md)). When one algorithm satisfies
every audience, a single key serves all of them. See
-[Business Profile](overview.md#business-profile) for a two-key example.
+[Business Profile](overview/index.md#business-profile) for a two-key example.
For on-the-wire signature encoding details, see
[REST Request Signing — Signature Encoding](#rest-request-signing).
@@ -211,8 +211,8 @@ opaque identifier (RFC 7517) and MAY be any stable value.
### Key Discovery
Public keys are published in the signer's UCP profile. See
-[Profile Structure](overview.md#profile-structure) for the publishing
-contract and [Key Discovery](overview.md#key-discovery) for the
+[Profile Structure](overview/index.md#profile-structure) for the publishing
+contract and [Key Discovery](overview/index.md#key-discovery) for the
verifier lookup rule (which key list to read for each resolution
mechanism).
@@ -288,7 +288,7 @@ One signature on the wire, two audiences. UCP-shape verifiers resolve via
key. Here both headers point at the same `/.well-known/ucp` URL
(`type=jwks_uri`, so WBA verifiers read the profile's `keys[]` as the JWK
Set — see
-[Deployment Patterns](overview.md#deployment-patterns-for-wba-interop)),
+[Deployment Patterns](overview/index.md#deployment-patterns-for-wba-interop)),
but `Signature-Agent` MAY point elsewhere.
The three `sig1` labels are bound together — the `Signature-Agent`
@@ -312,7 +312,7 @@ signature. Items marked **MUST** are required by
is an HTTPS URL and whose `type` parameter selects the discovery
mechanism; the member key matches the `Signature-Input` signature
label. See
- [Deployment Patterns](overview.md#deployment-patterns-for-wba-interop)
+ [Deployment Patterns](overview/index.md#deployment-patterns-for-wba-interop)
for the `jwks_uri`/`cimd`/`directory` variants and how each can reuse
the UCP profile. (`data:` URI inline form is out of scope.)
3. **MUST sign the `signature-agent` component with `;key=""`**
@@ -345,7 +345,7 @@ signature does (the Required set in the
"additional components" per
[draft-meunier-webbotauth-httpsig-protocol-00](https://datatracker.ietf.org/doc/draft-meunier-webbotauth-httpsig-protocol/00/)
§4.2.4. The verifier enforces this regardless of `tag` per the
-[Identity Resolution Algorithm](overview.md#identity-resolution-algorithm),
+[Identity Resolution Algorithm](overview/index.md#identity-resolution-algorithm),
so opting into Web Bot Auth never widens what UCP authenticates.
**Interop is one-way.** A UCP signer satisfies a Web Bot Auth
@@ -377,7 +377,7 @@ UCP verifiers see the same signature with three new things:
**Identity resolution.** WBA opt-in does not change default UCP
verification; see
-[Identity Resolution Algorithm](overview.md#identity-resolution-algorithm).
+[Identity Resolution Algorithm](overview/index.md#identity-resolution-algorithm).
**Tags.** UCP does not define its own `tag` (RFC 9421 §2.3). UCP
verifiers identify their signatures via the `UCP-Agent` header,
@@ -553,7 +553,7 @@ Response signatures use `@status` instead of `@method`:
The response body below is abbreviated for clarity — only the key fields
used in signing are shown. A full checkout response includes additional
required fields (`ucp`, `currency`, `line_items`, `totals`, `links`); see
-[Create Checkout response](checkout-rest.md#create-checkout) for the
+[Create Checkout response](shopping/checkout/rest.md#create-checkout) for the
complete shape.
```http
@@ -606,7 +606,7 @@ sign_rest_response(status, body_bytes, private_key, kid):
**Resolving the Signer's Keys:**
See
-[Identity Resolution Algorithm](overview.md#identity-resolution-algorithm)
+[Identity Resolution Algorithm](overview/index.md#identity-resolution-algorithm)
for the key-resolution rule (chosen by verifier capability and the
headers present, not by the signature's `tag`). This section specifies
header parsing only — `UCP-Agent` for the default UCP regime,
@@ -633,7 +633,7 @@ header parsing only — `UCP-Agent` for the default UCP regime,
Set URL, e.g. the UCP profile), `cimd` (a Client ID Metadata
Document), or `directory` (an origin hosting a well-known
directory); see
- [Deployment Patterns](overview.md#deployment-patterns-for-wba-interop).
+ [Deployment Patterns](overview/index.md#deployment-patterns-for-wba-interop).
`data:` URI inline form is out of scope for UCP-WBA interop.
4. Verification of this signature **MUST** fail if the URL is
non-HTTPS.
@@ -669,7 +669,7 @@ Both routines below verify a **single candidate** signature.
`skip_signature(reason)` means the candidate does not authenticate the
message: under multi-signature handling
([RFC 9421 §4.3](https://www.rfc-editor.org/rfc/rfc9421#section-4.3); see
-the [Identity Resolution Algorithm](overview.md#identity-resolution-algorithm)),
+the [Identity Resolution Algorithm](overview/index.md#identity-resolution-algorithm)),
the verifier tries the next candidate and rejects the message only when
**every** candidate skips. `success()` authenticates the message.
@@ -681,7 +681,7 @@ verify_rest_request(request):
components = sig_input.components
// 2. Resolve signer's public key (capability-based; see
- // overview.md#identity-resolution-algorithm).
+ // overview/index.md#identity-resolution-algorithm).
key_set = resolve_signer_key_set(request.headers)
// sig_capable skips keys not usable for verification: use:"enc", or
// key_ops present without "verify" (RFC 7517 §4.2, §4.3)
@@ -689,12 +689,12 @@ verify_rest_request(request):
if not public_key:
return skip_signature("key_not_found")
- // pre-2a. WBA-shape signatures bind key identity to key bytes:
- // keyid MUST equal the matched JWK's RFC 7638 thumbprint
- // (see IRA step 4 / WBA architecture draft §4.2).
- if sig_input.tag == "web-bot-auth":
- if keyid != rfc7638_thumbprint(public_key):
- return skip_signature("signature_invalid")
+ // pre-2a. WBA-shape signatures bind key identity to key bytes:
+ // keyid MUST equal the matched JWK's RFC 7638 thumbprint
+ // (see IRA step 4 / WBA architecture draft §4.2).
+ if sig_input.tag == "web-bot-auth":
+ if keyid != rfc7638_thumbprint(public_key):
+ return skip_signature("signature_invalid")
// 2a. Skip keys whose algorithm this verifier does not support.
// The kty/crv/alg vocabularies are open (see Signature Algorithms);
// an unsupported key never invalidates the whole key set.
@@ -912,7 +912,7 @@ No JSON canonicalization is required.
## Error Handling
Signature verification errors use standard UCP error codes. See
-[Error Handling](overview.md#error-handling) in the specification overview for
+[Error Handling](overview/index.md#error-handling) in the specification overview for
the complete error code registry and transport bindings.
**Signature-specific errors:**
diff --git a/docs/versioning.md b/docs/versioning.md
index 14a78e5f3..5294eaf05 100644
--- a/docs/versioning.md
+++ b/docs/versioning.md
@@ -2,9 +2,9 @@
This guide defines UCP's release-branch and backport process. UCP uses date-based
version identifiers in `YYYY-MM-DD` format; see
-[Component Versioning and Release Snapshots](specification/overview.md#component-versioning-and-release-snapshots)
+[Component Versioning and Release Snapshots](specification/overview/index.md#component-versioning-and-release-snapshots)
for the normative release model and
-[Protocol Version](specification/overview.md#protocol-version) for profile
+[Protocol Version](specification/overview/index.md#protocol-version) for profile
selection.
New development occurs on the `main` branch. We maintain long-lived branches for
@@ -12,7 +12,7 @@ all supported releases of the spec so that a published snapshot `D` stays
available for reference and maintenance. Backport eligibility and approval —
approved backwards-compatible changes by default, breaking changes only through
exceptional Governance Council approval — are defined in
-[Component Versioning and Release Snapshots](specification/overview.md#component-versioning-and-release-snapshots).
+[Component Versioning and Release Snapshots](specification/overview/index.md#component-versioning-and-release-snapshots).
A backported change lands on the maintained `release/D` branch, and UCP
re-certifies the snapshot before publishing the updated artifacts.
diff --git a/main.py b/main.py
index a656fb509..64047d92b 100644
--- a/main.py
+++ b/main.py
@@ -360,11 +360,11 @@ def create_link(ref_string, spec_file_name, context=None):
# Refer to checkout.json for ap2-mandates.json entities that are not
# explicitly defined in ap2-mandates.json.
if (
- spec_file_name == "ap2-mandates"
+ spec_file_name in ("ap2-mandates", "shopping/checkout/ap2-mandates")
and "ap2_mandate" not in ref_string
and not ref_string.startswith("#")
):
- spec_file_name = "checkout"
+ spec_file_name = "shopping/checkout"
# Extract fragment identifier if present (e.g., #/$defs/response)
# This handles cases like "types/pagination.json#/$defs/response"
diff --git a/mkdocs.yml b/mkdocs.yml
index 166b2c21d..42fb266bb 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -41,59 +41,64 @@ nav:
- Versioning: versioning.md
- Announcements: documentation/announcements.md
- Specification:
- - Overview: specification/overview.md
- - Checkout Capability:
- - Overview: specification/checkout.md
- - Transports:
- - REST: specification/checkout-rest.md
- - MCP: specification/checkout-mcp.md
- - A2A: specification/checkout-a2a.md
- - Embedded: specification/embedded-checkout.md
- - AP2 Mandates Extension: specification/ap2-mandates.md
- - Payment Authentication Extension:
- - Overview: specification/payment-authentication.md
- - Device Data Collection: specification/payment-actions/device-data-collection.md
- - 3DS Challenge: specification/payment-actions/three-ds-challenge.md
- - Buyer Consent Extension: specification/buyer-consent.md
- - Discounts Extension: specification/discount.md
- - Fulfillment Extension: specification/fulfillment.md
- - Loyalty Extension: specification/loyalty.md
- - Split Payments Extension: specification/split-payments.md
- - Payment Terms Extension: specification/payment-terms.md
- - Cart Capability:
- - Overview: specification/cart.md
- - Transports:
- - REST: specification/cart-rest.md
- - MCP: specification/cart-mcp.md
- - Embedded: specification/embedded-cart.md
- - Permalink Capability: specification/permalink.md
- - Catalog Capability:
- - Overview: specification/catalog/index.md
- - Search: specification/catalog/search.md
- - Lookup: specification/catalog/lookup.md
- - Transports:
- - REST: specification/catalog/rest.md
- - MCP: specification/catalog/mcp.md
- - Order Capability:
- - Overview: specification/order.md
- - Transports:
- - REST: specification/order-rest.md
- - MCP: specification/order-mcp.md
- - Identity Linking Capability: specification/identity-linking.md
- - Payment Handlers:
- - Guide: specification/payment-handler-guide.md
- - Template: specification/payment-handler-template.md
- - Tokenization Guide: specification/tokenization-guide.md
- - Examples:
- - Processor Tokenizer: "specification/examples/\
- processor-tokenizer-payment-handler.md"
- - Platform Tokenizer: "specification/examples/\
- platform-tokenizer-payment-handler.md"
- - Encrypted Credential: "specification/examples/\
- encrypted-credential-handler.md"
+ - Overview: specification/overview/index.md
+ - Common:
+ - Identity Linking: specification/common/identity-linking/index.md
+ - Shopping:
+ - Checkout Capability:
+ - Overview: specification/shopping/checkout/index.md
+ - Transports:
+ - REST: specification/shopping/checkout/rest.md
+ - MCP: specification/shopping/checkout/mcp.md
+ - A2A: specification/shopping/checkout/a2a.md
+ - Embedded: specification/shopping/checkout/embedded.md
+ - AP2 Mandates Extension: specification/ap2-mandates.md
+ - Buyer Consent Extension: specification/buyer-consent.md
+ - Discounts Extension: specification/discount.md
+ - Fulfillment Extension: specification/fulfillment.md
+ - Loyalty Extension: specification/loyalty.md
+ - Payment Terms Extension: specification/payment-terms.md
+ - Cart Capability:
+ - Overview: specification/shopping/cart/index.md
+ - Transports:
+ - REST: specification/shopping/cart/rest.md
+ - MCP: specification/shopping/cart/mcp.md
+ - Embedded: specification/shopping/cart/embedded.md
+ - Permalink Capability: specification/permalink.md
+ - Catalog Capability:
+ - Overview: specification/shopping/catalog/index.md
+ - Search: specification/shopping/catalog/search.md
+ - Lookup: specification/shopping/catalog/lookup.md
+ - Transports:
+ - REST: specification/shopping/catalog/rest.md
+ - MCP: specification/shopping/catalog/mcp.md
+ - Order Capability:
+ - Overview: specification/shopping/order/index.md
+ - Transports:
+ - REST: specification/shopping/order/rest.md
+ - MCP: specification/shopping/order/mcp.md
+ - Playground: specification/shopping/playground.md
+ - Payment:
+ - Payment Authentication:
+ - Overview: specification/payment/authentication.md
+ - Device Data Collection:
+ specification/payment/actions/device-data-collection.md
+ - 3DS Challenge:
+ specification/payment/actions/three-ds-challenge.md
+ - Split Payments: specification/payment/split-payments.md
+ - Payment Handlers:
+ - Guide: specification/payment/guide.md
+ - Template: specification/payment/template.md
+ - Tokenization Guide: specification/payment/tokenization.md
+ - Examples:
+ - Processor Tokenizer:
+ specification/payment/examples/processor-tokenizer-payment-handler.md
+ - Platform Tokenizer:
+ specification/payment/examples/platform-tokenizer-payment-handler.md
+ - Encrypted Credential:
+ specification/payment/examples/encrypted-credential-payment-handler.md
- Signatures: specification/signatures.md
- Reference: specification/reference.md
- - Playground: specification/playground.md
repo_name: UCP on GitHub # Override repo name to be shorter on site header.
repo_url: https://github.com/Universal-Commerce-Protocol/ucp
@@ -225,6 +230,73 @@ plugins:
on_error_fail: true
- site-urls
- social
+ - redirects:
+ redirect_maps:
+ # Cart
+ specification/cart.md:
+ specification/shopping/cart/index.md
+ specification/cart-rest.md:
+ specification/shopping/cart/rest.md
+ specification/cart-mcp.md:
+ specification/shopping/cart/mcp.md
+ specification/embedded-cart.md:
+ specification/shopping/cart/embedded.md
+ # Catalog
+ specification/catalog/index.md:
+ specification/shopping/catalog/index.md
+ specification/catalog/search.md:
+ specification/shopping/catalog/search.md
+ specification/catalog/lookup.md:
+ specification/shopping/catalog/lookup.md
+ specification/catalog/rest.md:
+ specification/shopping/catalog/rest.md
+ specification/catalog/mcp.md:
+ specification/shopping/catalog/mcp.md
+ # Checkout
+ specification/checkout.md:
+ specification/shopping/checkout/index.md
+ specification/checkout-rest.md:
+ specification/shopping/checkout/rest.md
+ specification/checkout-mcp.md:
+ specification/shopping/checkout/mcp.md
+ specification/checkout-a2a.md:
+ specification/shopping/checkout/a2a.md
+ specification/embedded-checkout.md:
+ specification/shopping/checkout/embedded.md
+ # Order
+ specification/order.md:
+ specification/shopping/order/index.md
+ specification/order-rest.md:
+ specification/shopping/order/rest.md
+ specification/order-mcp.md:
+ specification/shopping/order/mcp.md
+ # Playground
+ specification/playground.md:
+ specification/shopping/playground.md
+ # Common
+ specification/identity-linking.md:
+ specification/common/identity-linking/index.md
+ # Payment
+ specification/payment-authentication.md:
+ specification/payment/authentication.md
+ specification/payment-handler-guide.md:
+ specification/payment/guide.md
+ specification/payment-handler-template.md:
+ specification/payment/template.md
+ specification/split-payments.md:
+ specification/payment/split-payments.md
+ specification/tokenization-guide.md:
+ specification/payment/tokenization.md
+ specification/payment-actions/device-data-collection.md:
+ specification/payment/actions/device-data-collection.md
+ specification/payment-actions/three-ds-challenge.md:
+ specification/payment/actions/three-ds-challenge.md
+ specification/examples/processor-tokenizer-payment-handler.md:
+ specification/payment/examples/processor-tokenizer-payment-handler.md
+ specification/examples/platform-tokenizer-payment-handler.md:
+ specification/payment/examples/platform-tokenizer-payment-handler.md
+ specification/examples/encrypted-credential-handler.md:
+ specification/payment/examples/encrypted-credential-payment-handler.md
- llmstxt:
full_output: llms-full.txt
markdown_description: |
@@ -275,33 +347,38 @@ plugins:
General announcements, release notes, and community updates for
the Universal Commerce Protocol.
Specification:
- - specification/overview.md: >-
+ - specification/overview/index.md: >-
Master technical specification of UCP, discovery mechanisms,
- secure transports, and error taxonomies.
+ secure transports, capability negotiation, and error taxonomies.
- specification/glossary.md: >-
Definitions of the protocol, commerce, payment, regulatory, and
standards terms and acronyms used throughout the specification,
including Capability, Extension, Action, Platform, Business, and
Merchant of Record.
+ Common:
+ - specification/common/identity-linking/index.md: >-
+ User authentication via the Identity Linking Capability,
+ specifying direct B2C/B2B OAuth 2.0 flows (with PKCE and
+ RFC 9207) to unlock personalized commerce data.
Message Signatures:
- specification/signatures.md: >-
Implementation details for RFC 9421 HTTP Message Signatures and
RFC 9530 Content-Digests to achieve secure, transport-agnostic
request authentication and replay protection.
Checkout Capability:
- - specification/checkout.md: >-
+ - specification/shopping/checkout/index.md: >-
Core Checkout Capability specifications detailing session state
lifecycles, totals calculation rules, and buyer input validation
severity states.
- - specification/checkout-rest.md: >-
+ - specification/shopping/checkout/rest.md: >-
HTTP REST transport binding for Checkout operations, specifying
standard headers, API endpoints, status codes, and payload
structures.
- - specification/checkout-mcp.md: >-
+ - specification/shopping/checkout/mcp.md: >-
Model Context Protocol (MCP) transport binding for Checkout
operations, mapping UCP capabilities to JSON-RPC tools with
agent metadata rules.
- - specification/checkout-a2a.md: >-
+ - specification/shopping/checkout/a2a.md: >-
Agent2Agent Protocol (A2A) binding for Checkout Capability,
detailing transport discovery, agent card profile advertisement,
and message negotiation flows.
@@ -310,7 +387,7 @@ plugins:
formats, handshake patterns, communication channels, security
constraints, and shared error handling structures for
iframe/webview integrations.
- - specification/embedded-checkout.md: >-
+ - specification/shopping/checkout/embedded.md: >-
Embedded Checkout Protocol (ECP) specification, detailing
per-session delegation negotiation, URL parameters, native UI
event mappings, W3C Payment Request conceptual alignment, and
@@ -320,15 +397,6 @@ plugins:
checkout commitments (using SD-JWT+kb digital credentials and
detached JWS signatures) between business, platform, and payment
providers.
- - specification/payment-authentication.md: >-
- Payment Authentication Extension, defining negotiation,
- payment-handler association, lifecycle, trust, and embedded
- notifications for standard payment authentication Actions.
- - specification/payment-actions/device-data-collection.md: >-
- Standard Action type for running invisible device-data collection
- surfaces during payment processing.
- - specification/payment-actions/three-ds-challenge.md: >-
- Standard Action type for presenting buyer-facing 3DS challenges.
- specification/buyer-consent.md: >-
Buyer Consent Extension, defining data schemas for transmitting
buyer privacy choices (analytics, marketing, personalization) to
@@ -342,31 +410,25 @@ plugins:
Fulfillment extension for checkouts, defining delivery methods,
pickup destinations, and method-agnostic UI rendering contracts.
- specification/loyalty.md: >-
- Loyalty Extension, enabling high-fidelity member benefit recognition
- during catalog, cart, and checkout by defining schemas for
- memberships, tiers, benefits, and reward earning forecasts while
- managing provisional eligibility claims and enforcing
+ Loyalty Extension, enabling high-fidelity member benefit
+ recognition during catalog, cart, and checkout by defining schemas
+ for memberships, tiers, benefits, and reward earning forecasts
+ while managing provisional eligibility claims and enforcing
data-minimization privacy rules.
- specification/payment-terms.md: >-
Payment Terms Extension, enabling checkout payment schedules for
immediate and deferred payments such as deposits, installments,
and lodging balance-at-check-in flows.
- - specification/split-payments.md: >-
- Split Payments Extension, enabling a single checkout to be paid
- with multiple instruments by defining business-declared allowed
- combinations, specified- and open-amount contributions,
- per-instrument charge reporting, and all-or-nothing failure
- handling.
Cart Capability:
- - specification/cart.md: >-
+ - specification/shopping/cart/index.md: >-
Pre-purchase Cart Capability, detailing item collection, state
modification, and seamless transition handoff to active checkout
sessions.
- - specification/cart-rest.md: >-
+ - specification/shopping/cart/rest.md: >-
HTTP REST transport binding for Cart operations, including
endpoints for session creation, modification, retrieval, and
cancellation.
- - specification/cart-mcp.md: >-
+ - specification/shopping/cart/mcp.md: >-
Model Context Protocol (MCP) transport binding for
Cart operations, mapping item management to JSON-RPC
tools for AI shopping agents.
@@ -375,7 +437,7 @@ plugins:
formats, handshake patterns, communication channels, security
constraints, and shared error handling structures for
iframe/webview integrations.
- - specification/embedded-cart.md: >-
+ - specification/shopping/cart/embedded.md: >-
Embedded Cart Protocol (ECaP), enabling secure, cross-origin
iframe communication and synchronized event states between
platform agents and business websites.
@@ -385,70 +447,81 @@ plugins:
endpoint discovery, compact item paths, open query initialization
fields, and redirect resolution.
Catalog Capability:
- - specification/catalog/index.md: >-
+ - specification/shopping/catalog/index.md: >-
Core Catalog Capability, detailing high-level product discovery
models, variant structures, merchant attribution, and real-time
pricing context.
- - specification/catalog/search.md: >-
+ - specification/shopping/catalog/search.md: >-
Product discovery via the Search Catalog capability, specifying
text queries, category browsing, and multi-attribute filtering
contracts.
- - specification/catalog/lookup.md: >-
+ - specification/shopping/catalog/lookup.md: >-
Direct item retrieval via the Lookup Catalog capability,
specifying variant resolution logic, batch identifiers,
and interactive option selection.
- - specification/catalog/rest.md: >-
+ - specification/shopping/catalog/rest.md: >-
HTTP REST transport binding for the Catalog Capability,
detailing search, batch lookup, and product detail
endpoints with JSON payload examples.
- - specification/catalog/mcp.md: >-
+ - specification/shopping/catalog/mcp.md: >-
Model Context Protocol (MCP) transport binding for the Catalog
Capability, mapping discovery operations to JSON-RPC tools with
metadata validation rules.
- Other Capabilities:
- - specification/order.md: >-
+ Order Capability:
+ - specification/shopping/order/index.md: >-
Post-purchase tracking via the Order Capability, detailing line
item updates, fulfillment expectations, shipment events,
adjustments, and webhook-based status updates.
- - specification/order-rest.md: >-
+ - specification/shopping/order/rest.md: >-
HTTP REST transport binding for the Order Capability, detailing
endpoints, HTTP headers, payload schemas, and error structures.
- - specification/order-mcp.md: >-
+ - specification/shopping/order/mcp.md: >-
Model Context Protocol (MCP) transport binding for the Order
Capability, detailing the JSON-RPC tool interface and parameters
for fetching order states.
- - specification/identity-linking.md: >-
- User authentication via the Identity Linking Capability,
- specifying direct B2C/B2B OAuth 2.0 flows (with PKCE and
- RFC 9207) to unlock personalized commerce data.
- - specification/payment-handler-guide.md: >-
+ Payment:
+ - specification/payment/authentication.md: >-
+ Payment Authentication Extension, defining negotiation,
+ payment-handler association, lifecycle, trust, and embedded
+ notifications for standard payment authentication Actions.
+ - specification/payment/actions/device-data-collection.md: >-
+ Standard Action type for running invisible device-data collection
+ surfaces during payment processing.
+ - specification/payment/actions/three-ds-challenge.md: >-
+ Standard Action type for presenting buyer-facing 3DS challenges.
+ - specification/payment/split-payments.md: >-
+ Split Payments Extension, defining multiple payment instrument
+ allocation, settlement rules, and amount distribution across
+ payment handlers.
+ - specification/payment/guide.md: >-
Architectural framework and standard vocabulary for specifying UCP
payment handlers, covering configuration declarations and
transaction execution.
- - specification/payment-handler-template.md: >-
+ - specification/payment/template.md: >-
Standard Markdown template and integration checklist
when authoring new UCP payment handler specifications.
- - specification/tokenization-guide.md: >-
+ - specification/payment/tokenization.md: >-
Shared API, security requirements, and lifecycle policies
(single-use, TTL, session-scoped) for building compliant
tokenization payment handlers.
- - specification/examples/processor-tokenizer-payment-handler.md: >-
+ - specification/payment/examples/processor-tokenizer-payment-handler.md: >-
Concrete payment handler example utilizing a 'Tokenize to Process'
flow, where a single enterprise vault or PSP tokenizes
credentials and resolves them internally.
- - specification/examples/platform-tokenizer-payment-handler.md: >-
+ - specification/payment/examples/platform-tokenizer-payment-handler.md: >-
Concrete payment handler example utilizing a
'Platform-as-Tokenizer' flow, where a platform's wallet
generates tokens and hosts a secure detokenization endpoint.
- - specification/examples/encrypted-credential-handler.md: >-
+ - specification/payment/examples/encrypted-credential-payment-handler.md: >-
Concrete payment handler example utilizing a 'Direct Encryption'
flow, where a platform encrypts payment data with a business's
public key for local decryption.
+ Reference & Tooling:
- specification/reference.md: >-
Complete reference directory of all core UCP, type, and extension
JSON schemas, including platform/business profiles and metadata
objects.
- - specification/playground.md: >-
+ - specification/shopping/playground.md: >-
Interactive, browser-based UCP Playground simulator for walking
through step-by-step checkout sessions, payment handling, and
backend webhooks.
diff --git a/scripts/build_local.sh b/scripts/build_local.sh
index b154043af..c81104caf 100755
--- a/scripts/build_local.sh
+++ b/scripts/build_local.sh
@@ -147,6 +147,10 @@ echo ">>> Merging Spec Versions"
echo "Extracting: $EXTRACT_LIST"
git archive "$GH_PAGES_BRANCH" $EXTRACT_LIST | tar -x -C "$OUTPUT_DIR"
+# Add redirects for all specification files (mirroring .github/workflows/docs.yml)
+rm -rf "$OUTPUT_DIR/specification"
+(cd "$OUTPUT_DIR" && ln -s latest/specification specification)
+
echo "=== Build Complete! ==="
echo "To serve the fully built site (with versioning):"
echo " python3 -m http.server 8000 -d $OUTPUT_DIR"