Skip to content

feat: add per-seller offer attribution to catalog variants - #811

Open
proshoumma wants to merge 1 commit into
Universal-Commerce-Protocol:mainfrom
proshoumma:feat/catalog-offers
Open

feat: add per-seller offer attribution to catalog variants#811
proshoumma wants to merge 1 commit into
Universal-Commerce-Protocol:mainfrom
proshoumma:feat/catalog-offers

Conversation

@proshoumma

Copy link
Copy Markdown

Adds an optional offers[] array to the catalog variant, so one catalog can list a product sold by several different merchants and send each to the right seller's checkout.

Description

Today the business serving a catalog is assumed to be the only seller and Merchant of Record (MoR): variant.id is the checkout item ID and variant.price is the price checkout honors. That doesn't fit a marketplace or shopping agent that lists the same product from many merchants, each with its own checkout. offers[] fixes that. A variant without offers[] is unchanged.

Each offer names the seller (seller.domain, the MoR), that seller's own checkout item ID (item_id), and the price. This affects the catalog capabilities dev.ucp.shopping.catalog.search and dev.ucp.shopping.catalog.lookup, which share the variant type.

New type source/schemas/shopping/types/offer.json — required: seller (with seller.domain), item_id, price. Optional: list_price, unit_price, availability, url, sku, seller.name, seller.links.

{
  "id": "gid://shop/variant/123",
  "title": "Wireless Headphones",
  "price": { "amount": "19.99", "currency": "USD" },
  "offers": [
    { "seller": { "domain": "shop-a.example" }, "item_id": "A-item-1", "price": { "amount": "19.99", "currency": "USD" } },
    { "seller": { "domain": "shop-b.example" }, "item_id": "B-item-9", "price": { "amount": "21.50", "currency": "USD" } }
  ]
}

When offers is present (Business response → Platform), the Platform:

  • checks out with the chosen offers[].item_idMUST NOT use variant.id
  • treats offers[].price as the real price — variant.price is display-only
  • resolves offers[].seller.domain and checks out at that seller, after verifying it via authority binding

Also aligns the Business / MoR wording in glossary.md and core-concepts.md so a business need not be the MoR for everything it lists.

Category (Required)

  • Core Protocol: Changes to the base communication layer, global context, or breaking refactors. (Requires Technical Council approval)
  • Governance/Contributing: Updates to GOVERNANCE.md, CONTRIBUTING.md, or CODEOWNERS. (Requires Governance Council approval)
  • Capability: New schemas (Discovery, Cart, etc.) or extensions. (Requires Maintainer approval)
  • Documentation: Updates to README, or documentations regarding schema or capabilities. (Requires Maintainer approval)
  • Infrastructure: CI/CD, Linters, or build scripts. (Requires DevOps Maintainer approval)
  • Maintenance: Version bumps, lockfile updates, or minor bug fixes. (Requires DevOps Maintainer approval)
  • SDK: Language-specific SDK updates and releases. (Requires DevOps Maintainer approval)
  • Samples / Conformance: Maintaining samples and the conformance suite. (Requires Maintainer approval)
  • UCP Schema: Changes to the ucp-schema tool (resolver, linter, validator). (Requires Maintainer approval)
  • Community Health (.github): Updates to templates, workflows, or org-level configs. (Requires DevOps Maintainer approval)

Related Issues

Checklist

  • I have followed the Contributing Guide (including Conventional Commits title requirements and ! for breaking changes).
  • I have updated the documentation (if applicable).
  • My changes pass all local linting and formatting checks.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • (For Core/Capability) I have included/updated the relevant JSON schemas.
  • I have regenerated Python Pydantic models by running generate_models.sh under python_sdk.

Screenshots / Logs (if applicable)

Not applicable.

Add an optional `offers[]` array to the catalog variant so one catalog can list
a product sold by several merchants, each routed to its own checkout.

- offer.json: new type — seller.domain (the MoR), item_id, price (plus optional
  list_price, unit_price, availability, url, sku).
- variant.json: optional offers[]; variant.id is the checkout id only when
  offers is absent; seller clarified as display-only.
- catalog/index.md: offers-aware checkout rule, an Offer section, and a
  two-merchant example.
- glossary.md / core-concepts.md: a Business is typically, not always, the MoR.

Additive and fail-safe: responses without offers[] are unchanged, and an
offer-unaware checkout at a non-MoR business errors rather than mis-charging.
@damaz91 damaz91 added the status:needs-triage Signal that the PR is ready for human triage label Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status:needs-triage Signal that the PR is ready for human triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants