Skip to content

Universal Commerce Protocol Adapter (UCP)

Status: Implemented (Phase 1: Checkout, Phase 2: Order Webhooks, Phase 3: Identity Linking).

Purpose

UCP is the external commerce adapter. It implements the Universal Commerce Protocol (UCP spec v2026-01-11) so that external platforms — AI agents, apps, search engines, and marketplaces — can transact with g3nretailstack merchants through a single standardized API. UCP translates protocol-level calls into internal service operations, primarily SCM for order creation and CRM for customer identity.

The UCP specification is an open standard backed by Google, Shopify, Walmart, Target, Etsy, Wayfair, Visa, Mastercard, PayPal, and others. It defines a common API contract between platforms (the consumer-facing surface) and businesses (the merchant of record).

Goals

  • Give any UCP-compliant platform a zero-integration path to transact with a merchant.
  • Support capability negotiation so merchants control what is exposed (checkout, order webhooks, identity linking).
  • Provide signed webhook delivery so platforms receive real-time order lifecycle events.
  • Enable identity linking so platforms can associate their users with merchant customer records.

Non-goals

  • UCP does not own product truth (owned by PVM/PMC).
  • UCP does not own pricing (owned by PPM).
  • UCP does not own inventory (owned by ICS).
  • UCP does not own the sales order after creation (owned by SCM).
  • UCP does not own customer records (owned by CRM).
  • UCP does not process payments. Payment handlers are declared in the capability profile but are currently stubbed; payment_status is always none.

System-of-record boundaries

  • UCP owns platform credentials, checkout sessions, webhook delivery records, and identity links (tokens + auth codes).
  • SCM owns the sales order once checkout/complete succeeds. UCP holds a reference (scm_order_guid) but does not modify the order after creation.
  • CRM owns customer records. UCP reads customer data for identity linking but does not write to CRM.
  • OFM is referenced for orgcode-to-org resolution during capability discovery.

Capability negotiation

Every organization publishes a UCP profile at GET /.well-known/ucp?orgcode=X. The profile declares which capabilities are enabled and what currencies are supported. A platform reads this profile to know what operations are available before making any calls.

Capabilities are set by the merchant admin via POST /config/set:

  • checkout — cart-to-order session model.
  • order — HMAC-signed webhook delivery for 20 order lifecycle event types.
  • identity — OAuth 2.0 identity linking between platform users and CRM customers.

When identity linking is enabled, the profile includes the OAuth Authorization Server Metadata URL (RFC 8414) so platforms can discover token and revocation endpoints automatically.

Auth model

UCP uses three auth modes, each for a different caller type:

  • Admin auth — standard session/API key auth (same as all other services). Used for platform CRUD, config, webhook configuration, and identity link management. Requires ucp_admin or owner role.
  • Platform authclient_id + client_secret in the request body. Used for checkout operations, token exchange, and token revocation. Credentials are issued by admins via /platform/register; the secret is shown once and stored as a SHA-256 hash.
  • Bearer authAuthorization: Bearer <token> header. Used for identity-linked operations (userinfo). Tokens are opaque strings; the system SHA-256 hashes them for DDB lookup.

Core business entities

  • Platform — a registered external platform with credentials, scopes, and webhook configuration.
  • Checkout session — a temporary cart-to-order session with line items, buyer info, pricing, and a finite-state lifecycle.
  • Webhook delivery — a record of an outbound HMAC-signed event delivered (or pending retry) to a platform's callback URL.
  • Identity link — a binding between a platform and a CRM customer, with scopes and active/revoked status.
  • Auth code — a short-lived (10-minute) authorization code for the OAuth identity linking flow.
  • Access token — a 1-hour opaque token that grants bearer access to identity-linked customer data.
  • Refresh token — a 30-day opaque token that can be exchanged for a new access token.

Lifecycle and status models

Checkout session FSM

incomplete → requires_escalation → ready_for_complete → complete_in_progress → completed
     │              │                      │
     └── canceled ←─┘──────────────────────┘
  • A session starts as incomplete until buyer info and line items are present.
  • ready_for_complete means the session can be finalized.
  • complete_in_progress is set while the SCM order is being created.
  • completed is terminal — the SCM order exists.
  • canceled is terminal — can be reached from any non-terminal state.
  • A link is created as active when a platform exchanges an auth code for tokens.
  • An admin can revoke a link, setting status to revoked with a revoked_at timestamp.
  • Tokens associated with a revoked link will fail on the next validation attempt.

Webhook delivery lifecycle

  • A delivery starts as pending with attempt_count=0.
  • On successful HTTP delivery (2xx), status moves to delivered.
  • On failure, the delivery is re-queued with exponential backoff (30s base, 900s max, up to 5 attempts).
  • After 10 consecutive failures across all deliveries for a platform, the platform's webhook_status is set to paused.
  • dead is terminal — maximum attempts exhausted.

End-to-end workflows

Platform onboarding

  1. Merchant admin registers a platform: POST /platform/register with caption and scopes.
  2. System returns client_id and client_secret — the secret is shown once only.
  3. Admin configures capabilities: POST /config/set with capabilities: ["checkout", "order", "identity"].
  4. Admin sets webhook config: POST /webhook/config/set with event types and callback URL.
  5. Admin tests webhook delivery: POST /webhook/test sends a test event to the callback URL.
  6. Platform verifies profile: GET /.well-known/ucp?orgcode=X returns enabled capabilities.

Checkout flow (platform-initiated)

  1. Platform creates a checkout session with line items and optional buyer: POST /checkout/create.
  2. Platform updates the session as needed (full cart replacement): POST /checkout/update.
  3. When the session status is ready_for_complete, the platform finalizes: POST /checkout/complete.
  4. UCP calls SCM to create the sales order. On success, scm_order_guid is returned and the session is completed.
  5. On failure, the session reverts to ready_for_complete with an error message.
  6. The platform can cancel at any time: POST /checkout/cancel.

Order webhook delivery

  1. SCM emits order lifecycle events to the scm-events EventBridge bus (e.g., order-placed, shipment-created, return-requested).
  2. UCP's event ingest Lambda receives events filtered by channel_code === 'ucp'.
  3. For each registered platform with matching webhook event subscriptions, a signed delivery is created.
  4. The delivery is sent as an HTTP POST to the platform's callback_url with HMAC-SHA256 signature headers.
  5. Failed deliveries are retried with exponential backoff via a scheduled retry Lambda (every 2 minutes).
  6. After 10 consecutive failures, the platform is auto-paused. Admins can re-enable via /webhook/config/set.

Identity linking (admin-mediated OAuth 2.0)

  1. Admin issues an authorization code: POST /identity/authorize with {platform_guid, customer_guid}.
    • Validates the platform is active and the customer exists in CRM.
    • Returns a 10-minute authorization code. Optionally accepts a PKCE code_challenge (S256).
  2. Admin provides the code to the platform out-of-band (email, dashboard, API).
  3. Platform exchanges the code for tokens: POST /identity/token with grant_type: authorization_code.
    • Validates client credentials, verifies PKCE if code_challenge was set, consumes the code (single use).
    • Creates the identity link and returns access_token (1h) + refresh_token (30d).
  4. Platform accesses customer info: POST /identity/userinfo with Authorization: Bearer <token>.
    • Returns customer fields (email, phone, name, customer_code) scoped by the token's scopes.
  5. Platform refreshes expired tokens: POST /identity/token with grant_type: refresh_token.
    • Issues a new access token; old access token is invalidated.
  6. Platform revokes tokens: POST /identity/revoke with the token value (RFC 7009 — always returns 200).
  7. Admin can list links (POST /identity/link/list) or revoke a link (POST /identity/link/revoke).

Webhook event types (20)

Order lifecycle events delivered to platforms:

CategoryEvents
Orderorder.created, order.placed, order.fulfilled, order.cancelled, order.closed, order.line_cancelled
Fulfillmentfulfillment.shipment_created, fulfillment.shipment_updated, fulfillment.shipment_cancelled, fulfillment.delivered
Returnreturn.requested, return.authorized, return.received, return.inspected, return.resolved
Adjustmentadjustment.refund
Promisepromise.quoted, promise.reserved, promise.allocated, promise.committed

Webhook headers: x-ucp-event-type, x-ucp-event-id, x-ucp-signature, x-ucp-signature-alg: hmac-sha256, x-ucp-timestamp.

Identity scopes

ScopeGrants
ucp:checkout_sessionAccess to checkout session data for the linked customer
ucp:order_readRead access to order data for the linked customer
ucp:customer_readRead access to customer profile (email, phone, name, customer_code)

Cross-service dependencies

ServiceDirectionPurpose
USM/UAS/OFMReadAdmin auth (session validation, member resolution)
OPSReadMaintenance mode check
SCMWriteOrder creation on checkout/complete (via internal-invoke)
SCMRead (EventBridge)Subscribe to scm-events bus for order lifecycle webhooks
OFMRead (GSI2)orgcode → org_guid resolution for capability profile
CRMRead (DDB)Customer lookup for identity linking

Events emitted

UCP emits events to the ucp-events EventBridge bus:

EventTrigger
platform-registeredNew platform created
platform-secret-rotatedClient secret rotated
platform-revokedPlatform revoked
checkout-session-createdNew checkout session
checkout-session-updatedCart/buyer updated
checkout-session-completedSCM order created
checkout-session-canceledSession canceled
webhook-config-updatedWebhook configuration changed
webhook-fanout-completedWebhook delivery batch finished
identity-code-issuedAuthorization code created
identity-linkedToken exchange completed (identity linked)
identity-token-revokedAccess/refresh token revoked
identity-link-revokedIdentity link revoked by admin

Performance posture

  • Checkout CRUD: p95 < 500ms (Tier B).
  • Checkout complete (includes SCM call): p95 < 2s (Tier C).
  • Profile/discovery: p95 < 200ms (Tier A, cached 5 min / 1 hour).
  • Identity authorize/token: p95 < 500ms (Tier C).
  • Identity userinfo: p95 < 300ms (Tier B).
  • Webhook delivery: 6-second timeout per attempt.

Failure posture

  • Checkout complete failure: session reverts to ready_for_complete with error_message; platform can retry.
  • Webhook delivery failure: exponential backoff retry (30s → 900s, 5 attempts); auto-pause after 10 consecutive failures.
  • Identity code expiry: 10-minute TTL; platform must request a new code from the admin.
  • Access token expiry: 1-hour TTL; use refresh token to obtain a new access token.
  • Refresh token expiry: 30-day TTL; admin must re-authorize (new code flow).
  • Auth code replay: codes are single-use; replaying a consumed code returns an error.
  • PKCE mismatch: wrong code_verifier is rejected; a new code must be issued.

Stubs (future)

  • Payment handlers — the capability profile declares payment_methods as an empty array and payment_status is always none. Payment processing will be added when a PSP integration is defined.