# How Universal Commerce Protocol Achieves Dynamic Discovery via /.well-known/ucp

> Discover how Universal Commerce Protocol enables permissionless platform onboarding via /.well-known/ucp. Dynamically find services, capabilities, and credentials without pre-configuration.

- Repository: [Universal Commerce Protocol (UCP)/ucp](https://github.com/Universal-Commerce-Protocol/ucp)
- Tags: how-to-guide
- Published: 2026-04-26

---

**Universal Commerce Protocol enables permissionless platform onboarding by publishing a JSON discovery document at `https://<business-domain>/.well-known/ucp`, allowing any platform to dynamically discover services, capabilities, and security credentials without pre-configuration.**

The **Universal Commerce Protocol (UCP)** eliminates manual integration setup by mandating that every business host a machine-readable discovery profile at a standardized well-known URL. According to the `Universal-Commerce-Protocol/ucp` source code, this design allows platforms to fetch service endpoints, negotiate protocol versions, and retrieve public signing keys through a single HTTP request.

## The Discovery Document Structure

Every UCP-compliant business must serve a **business discovery profile** at `/.well-known/ucp` that conforms to the JSON-Schema defined in [`source/discovery/profile_schema.json`](https://github.com/Universal-Commerce-Protocol/ucp/blob/main/source/discovery/profile_schema.json).

### Required Fields and Schema

The document structure follows the top-level definitions in [`source/schemas/ucp.json`](https://github.com/Universal-Commerce-Protocol/ucp/blob/main/source/schemas/ucp.json) and contains these critical sections:

- **ucp.version** – The protocol version supported by the business
- **services** – Advertised services (REST, MCP, A2A, Embedded) with their **endpoint URLs** and transport types
- **capabilities** – Names, versions, and optional extensions available for negotiation
- **payment_handlers** – Optional registry of supported payment handlers
- **signing_keys** – JWK public keys used for **HTTP-Message-Signature** verification and key discovery

## The Dynamic Discovery Flow

When initiating UCP operations, platforms must fetch and process the business profile following the sequence documented in [`docs/specification/overview.md`](https://github.com/Universal-Commerce-Protocol/ucp/blob/main/docs/specification/overview.md).

### Fetch and Validation Steps

1. **Fetch** the document via `GET https://<business-domain>/.well-known/ucp` using HTTPS only (redirects forbidden)
2. **Validate** the response against [`profile_schema.json`](https://github.com/Universal-Commerce-Protocol/ucp/blob/main/profile_schema.json) to ensure schema compliance
3. **Cache** the document respecting the `Cache-Control: public, max-age>=60` header (the spec mandates a minimum 60-second TTL)
4. **Extract** endpoint URLs from `services[<service-id>][transport].endpoint` for subsequent API calls
5. **Compute** capability intersection between the platform's advertised features and the business's `capabilities` list using the *Intersection Algorithm*
6. **Compose** request/response schemas by fetching base schemas and any active extensions found in the negotiated intersection

## Versioning and Extension Mechanisms

The discovery mechanism supports graceful protocol evolution through version-specific profiles and capability extensions.

### Version-Specific Profiles

Businesses may expose multiple dated profiles at paths like `/.well-known/ucp/2026-01-11` and advertise them in the `supported_versions` map. This allows platforms to request exactly the version they understand, ensuring backward compatibility while enabling protocol upgrades.

### Extension-Driven Evolution

New capabilities are added via the `extends` field within the capabilities object. Platforms only load extensions whose parent capabilities appear in the negotiated intersection, preventing breaking changes while supporting feature expansion.

## Security and Caching Requirements

The specification enforces strict security controls for the discovery process:

- **HTTPS-only transport** with no redirects permitted
- **Mandatory caching directives** requiring `Cache-Control: public` with a minimum max-age of 60 seconds
- **In-band key discovery** via the `signing_keys` array, enabling platforms to verify HTTP-Message-Signatures using the same profile
- **Graceful error handling** with defined error codes `profile_unreachable` and `profile_malformed` when discovery fails

## Implementation Example

Below is a complete Python implementation demonstrating profile fetching, validation, and endpoint extraction:

```python
import requests
import json
import jsonschema

# URL of the discovery document (must be HTTPS)

DISCOVERY_URL = "https://example-business.com/.well-known/ucp"

# 1. Fetch the profile

resp = requests.get(DISCOVERY_URL, timeout=5)
resp.raise_for_status()                # 2xx → OK

profile = resp.json()

# 3. Validate against the JSON-Schema (downloaded once, cached)

schema_url = "https://raw.githubusercontent.com/Universal-Commerce-Protocol/ucp/main/source/discovery/profile_schema.json"
schema = requests.get(schema_url).json()
jsonschema.validate(instance=profile, schema=schema)

# 4. Extract endpoint for the Shopping REST service

shopping = profile["ucp"]["services"]["dev.ucp.shopping"]
rest_entry = next(s for s in shopping if s["transport"] == "rest")
api_base = rest_entry["endpoint"]       # e.g. https://biz.example.com/api/v2

# 5. Use the endpoint to call a Checkout operation

checkout_url = f"{api_base}/checkout-sessions"
checkout_resp = requests.post(
    checkout_url,
    json={"line_items": [{"price_id": "sku_123", "quantity": 1}]},
    headers={"UCP-Agent": f'profile="{DISCOVERY_URL}"'}
)
checkout_resp.raise_for_status()
print(json.dumps(checkout_resp.json(), indent=2))

```

### Sample Discovery Document

The following JSON illustrates the structure defined in [`source/schemas/ucp.json`](https://github.com/Universal-Commerce-Protocol/ucp/blob/main/source/schemas/ucp.json) and [`source/discovery/profile_schema.json`](https://github.com/Universal-Commerce-Protocol/ucp/blob/main/source/discovery/profile_schema.json):

```json
{
  "ucp": {
    "version": "2026-01-23",
    "services": {
      "dev.ucp.shopping": [
        {
          "version": "2026-01-23",
          "transport": "rest",
          "endpoint": "https://biz.example.com/api/v2",
          "schema": "https://ucp.dev/2026-01-23/services/shopping/rest.openapi.json"
        },
        {
          "version": "2026-01-23",
          "transport": "mcp",
          "endpoint": "https://biz.example.com/mcp",
          "schema": "https://ucp.dev/2026-01-23/services/shopping/mcp.openrpc.json"
        }
      ]
    },
    "capabilities": {
      "dev.ucp.shopping.checkout": [{ "version": "2026-01-23" }],
      "dev.ucp.shopping.fulfillment": [{ "version": "2026-01-23", "extends": "dev.ucp.shopping.checkout" }]
    },
    "signing_keys": [{ "kid": "biz2025", "kty": "EC", "crv": "P-256", "...": "..." }]
  }
}

```

## Summary

- **Dynamic discovery** occurs via `GET /.well-known/ucp`, returning a JSON document defined by [`source/discovery/profile_schema.json`](https://github.com/Universal-Commerce-Protocol/ucp/blob/main/source/discovery/profile_schema.json)
- **No pre-configuration** is required—platforms learn service endpoints, protocol versions, and signing keys directly from the business domain
- **Capability negotiation** uses the Intersection Algorithm to determine compatible features between platform and business
- **Mandatory caching** requires `Cache-Control: public, max-age>=60` to reduce load while maintaining freshness
- **Security** combines HTTPS-only transport with in-band key discovery via the `signing_keys` array for HTTP-Message-Signature verification

## Frequently Asked Questions

### What is the exact URL path for UCP discovery?

The discovery document must be hosted at `/.well-known/ucp` on the business's primary domain, accessed via `https://<business-domain>/.well-known/ucp`. The specification mandates HTTPS-only transport with no redirects permitted, as documented in [`docs/specification/overview.md`](https://github.com/Universal-Commerce-Protocol/ucp/blob/main/docs/specification/overview.md) and demonstrated in [`docs/specification/playground.md`](https://github.com/Universal-Commerce-Protocol/ucp/blob/main/docs/specification/playground.md).

### How does UCP handle protocol version negotiation?

Businesses advertise supported versions in the `supported_versions` map and may host version-specific profiles at dated paths like `/.well-known/ucp/2026-01-11`. Platforms compute the intersection of their supported versions with the business's advertised versions, then fetch the appropriate schema definitions from the endpoints specified in the discovery document.

### What security mechanisms protect the discovery process?

UCP enforces HTTPS-only transport with strict `Cache-Control` requirements (public, minimum 60-second TTL). The `signing_keys` array within the discovery profile provides JWK public keys for **HTTP-Message-Signature** verification, enabling platforms to authenticate subsequent API calls using credentials discovered in-band. The specification also defines error codes `profile_unreachable` and `profile_malformed` for handling discovery failures gracefully.

### How long should platforms cache the discovery document?

The specification mandates a minimum cache duration of 60 seconds via the `Cache-Control: public, max-age>=60` header. Platforms should respect the actual `max-age` value provided by the server while maintaining a local cache to avoid repeated requests during high-frequency operations, as detailed in [`docs/specification/overview.md`](https://github.com/Universal-Commerce-Protocol/ucp/blob/main/docs/specification/overview.md).