Skip to main content

Merchant Integration Guide

7.1 Prerequisites

RequirementDescriptionRequired / Recommended
HTTPSAll endpoints must use HTTPS; Profile endpoint must not redirect (no 3xx)Required
DomainOwn a domain where you can deploy /.well-known/ucpRequired
Product dataAbility to return product data in JSON formatRequired
Signing keysGenerate an ES256 (P-256) key pair for Webhook signaturesRecommended
OAuth 2.0Required for identity linking; needs an OAuth authorization serverAs needed
Payment processorAt least one UCP-compatible payment processorAs needed

7.2 Step 1: Deploy the UCP Profile

The UCP Profile is the entry point through which AI agents discover your capabilities. It is served at the /.well-known/ucp path.

Profile Requirements

  • HTTPS only: Must be served over HTTPS. HTTP requests should return a 301 redirect to HTTPS.
  • No redirects: HTTPS requests to /.well-known/ucp must not return 3xx redirects. The response must be a direct 200.
  • Cache-Control: Must include Cache-Control: public, max-age=N where N is at least 60 seconds.
  • Content-Type: application/json

Minimal Profile (Product Discovery Only)

{
  "supported_versions": ["2026-04-08"],
  "services": {
    "dev.ucp.shopping": {
      "base_url": "https://mystore.com/ucp"
    }
  },
  "capabilities": {
    "dev.ucp.shopping.checkout": {
      "version": "2026-04-08",
      "supported_operations": ["create", "get", "update", "complete", "cancel"]
    }
  },
  "signing_keys": []
}

Full Profile (All Capabilities)

{
  "supported_versions": ["2026-04-08"],
  "services": {
    "dev.ucp.shopping": {
      "base_url": "https://mystore.com/ucp"
    },
    "dev.ucp.common": {
      "base_url": "https://mystore.com/ucp"
    }
  },
  "capabilities": {
    "dev.ucp.shopping.checkout": {
      "version": "2026-04-08",
      "supported_operations": ["create", "get", "update", "complete", "cancel"]
    },
    "dev.ucp.common.identity_linking": {
      "version": "2026-04-08"
    },
    "dev.ucp.shopping.order": {
      "version": "2026-04-08"
    }
  },
  "payment_handlers": [
    "com.stripe.payment",
    "com.adyen.payment"
  ],
  "signing_keys": [
    {
      "kid": "key-2026-04",
      "kty": "EC",
      "crv": "P-256",
      "x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
      "y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0",
      "use": "sig",
      "alg": "ES256"
    }
  ]
}

7.3 Generating Signing Keys

Generate an ES256 (P-256) key pair using OpenSSL:
# Generate private key
openssl ecparam -genkey -name prime256v1 -noout -out ucp-signing-key.pem

# Extract public key
openssl ec -in ucp-signing-key.pem -pubout -out ucp-signing-key-pub.pem

# Export as JWK format (requires a jose tool or programmatic conversion)
# Choose a kid that includes a date, e.g., key-2026-04
Security reminder: The private key (ucp-signing-key.pem) must be stored securely on the server. It must never appear in the Profile, source code repositories, or logs. Only the public key information (x and y coordinates) is published in the Profile’s signing_keys array.

7.4 Four-Phase Integration Path

Phase 1: Profile + Product Catalog (1 day)

The minimum viable integration. Deploy the /.well-known/ucp Profile and a product search API:
const express = require("express");
const app = express();

// UCP Profile
app.get("/.well-known/ucp", (req, res) => {
  res.set("Cache-Control", "public, max-age=3600");
  res.json({
    supported_versions: ["2026-04-08"],
    services: {
      "dev.ucp.shopping": {
        base_url: "https://mystore.com/ucp"
      }
    },
    capabilities: {
      "dev.ucp.shopping.checkout": {
        version: "2026-04-08",
        supported_operations: ["create", "get", "update", "complete", "cancel"]
      }
    },
    signing_keys: []
  });
});

// Product search
app.get("/ucp/catalog/products", async (req, res) => {
  const { query, category, limit = 10, offset = 0 } = req.query;

  const products = await db.products.search({
    query, category,
    limit: Math.min(parseInt(limit), 50),
    offset: parseInt(offset)
  });

  res.json({
    products: products.map(p => ({
      id: p.id,
      name: p.name,
      description: p.description,
      brand: p.brand,
      price: { amount: p.priceInCents, currency_code: "USD" },
      availability: p.stock > 0 ? "in_stock" : "out_of_stock",
      images: [{ url: p.imageUrl, alt: p.name }],
      url: `https://mystore.com/product/${p.slug}`
    })),
    total: products.totalCount,
    limit: parseInt(limit),
    offset: parseInt(offset)
  });
});

app.listen(3000);
Value of this phase: AI agents can discover your UCP Profile, search your catalog, and display your products to users.

Phase 2: Checkout Capability (2-3 days)

Build on Phase 1 by implementing the checkout API — five operations (Create / Get / Update / Complete / Cancel) and a six-state state machine. Requires payment processor integration. Key implementation points:
  • CRUD endpoints for checkout sessions
  • State machine transition logic
  • Payment processor integration (declare supported processors via payment_handlers)
  • ISO 4217 monetary amount handling

Phase 3: Identity Linking (2-3 days)

Implement an OAuth 2.0 authorization server:
  • /.well-known/oauth-authorization-server metadata endpoint
  • Authorization endpoint (/oauth/authorize)
  • Token endpoint (/oauth/token)
  • Revocation endpoint (/oauth/revoke), following RFC 7009
  • PKCE (S256) support

Phase 4: Order Management + Webhooks (2-3 days)

  • Order query API
  • Fulfillment event tracking
  • Adjustment operations (returns / refunds)
  • Webhook notifications using RFC 9421 signatures (requires publishing JWK signing keys in the Profile)

7.5 Declaring Payment Handlers in the UCP Profile

The payment_handlers array lists the payment processors you accept, using reverse-DNS naming:
{
  "payment_handlers": [
    "com.stripe.payment",
    "com.adyen.payment",
    "com.paypal.payment",
    "com.square.payment"
  ]
}
AI agents perform capability negotiation to determine mutually supported payment processors, then complete payment token exchange through a three-step lifecycle: negotiate, acquire, and complete.

7.6 HTTP Response Header Requirements

UCP endpoints should return the following HTTP headers:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Cache-Control: public, max-age=3600
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
For the Profile endpoint (/.well-known/ucp), the Cache-Control max-age must be at least 60 seconds. A value of 3600 seconds (1 hour) is recommended.
Next chapter: Platform Integration Guide — Capability negotiation algorithm, extension mechanisms, and multi-platform strategies