Summary
Add an optional, response-only list_price to the shared Item schema used by Cart, Checkout, and Order. The field carries the Catalog Variant.list_price semantic into those item responses.
Cart and Checkout may return the current Business-authoritative value. When returned in an Order, the field represents the value captured at order creation. Platform Cart and Checkout requests omit it, and price and totals remain authoritative for transaction amounts.
This proposal asks the Shopping Tech Council (TC) whether propagating an existing core Catalog semantic into the shared Item is appropriate for direct inclusion in the core protocol. If the TC requires extension-first validation, the proposal can be revised to use a vendor-specific extension before later core consideration.
Motivation
UCP Catalog already defines Variant.list_price, but the shared Item embedded in Cart, Checkout, and Order contains the current unit price without the list price used for price comparison.
A Platform that needs the current list price cannot obtain it from a Cart or Checkout response. It must omit the value or retrieve it from another source, such as Catalog Lookup. For Order, a later Catalog Lookup cannot reconstruct the value that applied when the order was created.
Carrying the existing Catalog semantic in the shared response makes each item snapshot self-contained for price comparison. Cart and Checkout return the current Business value, while Order may preserve the value captured at order creation. Transaction amounts remain defined by price, line-item totals, and resource totals.
Non-normative Cart item-row example. The strikethrough price represents list_price. All other UI elements and displayed values are illustrative and do not define protocol behavior or required UI.
Goals
- The shared
Item schema defines an optional, response-only list_price.
- Resolved Cart, Checkout, and Order response schemas validate with and without
list_price.
- Resolved Platform request schemas for Cart and Checkout omit
list_price; the Business remains authoritative for the returned value.
- Cart and Checkout define when the response value matches Catalog
Variant.list_price. An Order value is the snapshot captured at order creation and is not refreshed from later Catalog state.
- A paired Catalog, Cart, Checkout, and Order fixture verifies the current Catalog mapping and the Order snapshot.
- At least one Business–Platform integration demonstrates that Cart or Checkout can return
list_price without a Catalog request made solely for that value.
Non-Goals
- Standardizing how discounts or savings percentages are calculated.
- Requiring a user interface to display a strikethrough price.
- Introducing platform-specific names such as
compare_at_price.
- Requiring every Business to provide a list price.
- Changing Cart totals, discount allocation, or checkout pricing authority.
- Reconstructing or updating an Order list-price snapshot from later Catalog data.
Detailed Design
The proposal adds one optional property to source/schemas/shopping/types/item.json. Cart and Checkout line items reference types/line_item.json, and Order line items reference types/order_line_item.json; both paths compose the shared Item. The field therefore propagates to Cart, Checkout, Order, and extensions that reuse those schemas without adding a new operation or transport behavior.
Schema Placement
The preferred core option adds list_price to the shared Item because it reuses an existing Catalog semantic and gives Cart, Checkout, and Order one portable field without extension negotiation. If the TC requires extension-first validation, the same response-only field can be composed through a vendor-specific extension before later core consideration.
Alternatives Considered and Decision Requested
| Alternative |
Assessment |
| Shared Item.list_price in core — preferred |
Reuses the existing Catalog Variant.list_price semantic in the shared item snapshot. Cart, Checkout, and Order use one portable field, and no extension negotiation is required. |
| Vendor-specific extension |
Allows limited integration validation, but requires negotiation and does not establish a portable field for Cart, Checkout, and Order. Namespace and schema composition will be defined only if the TC selects this path. |
| Catalog Lookup only |
Platforms continue using Catalog Lookup when they need the current list price. Cart and Checkout cannot return it in their standard responses, and Order has no standard field for the value captured at order creation. |
| Decision requested |
Does the TC agree that propagating the existing core Variant.list_price semantic into the shared Item is appropriate, or should this first be validated as a vendor-specific extension? |
Resource and Request Scope
| Response or request |
Required behavior |
| Cart response |
A Business MAY return the current list_price for an item. A Platform MUST accept omission. |
| Checkout response |
A Business MAY return the current list_price for an item. A Platform MUST accept omission. |
| Order response |
A Business MAY return list_price when it retained the value at order creation. When present, the field MUST represent that snapshot and MUST NOT be refreshed from later Catalog state. A Platform MUST accept omission. |
| Platform Cart or Checkout request |
A Platform MUST omit list_price. The Business remains authoritative for the returned value. |
Proposed Schema
The core proposal adds the optional response-only field below. If the TC selects extension-first validation, a follow-up revision will compose an equivalent field into Cart, Checkout, and Order response schemas.
{
"properties": {
"list_price": {
"$ref": "../../common/types/amount.json",
"description": "List price before discounts. In an Order response, this is the snapshot captured at order creation.",
"ucp_request": "omit"
}
}
}
Simplified Catalog → Cart → Checkout → Order Mapping Example
This abbreviated example shows the same Variant in Catalog, Cart, and Checkout, followed by the list-price snapshot retained when the Order is created. Unrelated required fields are omitted.
{
"catalog_variant": {
"id": "variant_123",
"price": { "amount": 3999, "currency": "USD" },
"list_price": { "amount": 4200, "currency": "USD" }
},
"cart": {
"currency": "USD",
"line_items": [{
"item": {
"id": "variant_123",
"price": 3999,
"list_price": 4200
}
}]
},
"checkout": {
"currency": "USD",
"line_items": [{
"item": {
"id": "variant_123",
"price": 3999,
"list_price": 4200
}
}]
},
"order": {
"currency": "USD",
"line_items": [{
"item": {
"id": "variant_123",
"price": 3999,
"list_price": 4200
}
}]
}
}
Protocol Behavior
list_price is optional and response-only in Cart, Checkout, and Order. A Platform MUST omit it from Cart and Checkout requests.
- Within the same market, buyer context, and sale basis, unchanged Business pricing MUST produce the same list-price amount in Catalog and Cart or Checkout.
item.list_price MUST equal Catalog Variant.list_price.amount, and the enclosing resource currency MUST equal Catalog Variant.list_price.currency.
- When present in an Order response,
list_price MUST be the snapshot captured at order creation and MUST NOT be refreshed from later Catalog state. A Business MAY omit the field if it did not retain that snapshot.
list_price is for price-comparison display. It MUST NOT change price, line-item totals, resource totals, or structured discount attribution. The protocol does not require list_price to be greater than price.
Risks and Mitigations
| Risk |
Mitigation |
Security: A Platform could treat list_price as an amount authorized for payment or settlement. |
list_price contains no executable content or sensitive data. It is display-only and MUST NOT drive authorization, payment, settlement, or totals. price and totals remain authoritative. |
| Data integrity: The value may not match the current Variant, or an Order snapshot may change after order creation. |
Cart and Checkout follow the Catalog comparison rules defined above. An Order value, when present, preserves the value captured at order creation and is not refreshed from later Catalog state. |
| Performance: The field increases response size and may require one stored amount for an Order snapshot. |
The change adds one optional amount to each affected item. It may avoid a Catalog Lookup made solely to retrieve list price. |
| Backward compatibility: Older Businesses omit the field, and older Platforms may receive it as an unknown property. |
The field is optional and request-omitted. New Platforms accept omission. Under the core option, Businesses emit it only for a negotiated UCP version that defines it; under the extension option, both parties negotiate the extension. |
Complexity: The shared Item propagates into Cart, Checkout, Order, and composed extensions. |
Revalidate every affected response schema, example, and generated model. The change adds no new operation or lifecycle state. |
| Core growth: The field duplicates data available from Catalog. |
Limit the proposal to the existing Catalog semantic needed in a self-contained item response. If the TC does not consider that broadly applicable, validate it as a vendor-specific extension first. |
Test Plan
- Run
ucp-schema lint source/ to validate schema syntax and references.
- Resolve Cart and Checkout operation-specific request schemas and confirm that
ucp_request: "omit" removes list_price. If the TC selects an extension, also verify negotiation and field absence when the extension is not negotiated.
- Validate Cart, Checkout, and Order responses with and without
list_price.
- Validate an Order response that omits the field and a positive Order case that preserves the value captured at order creation after Catalog pricing changes.
- Validate a paired Catalog, Cart, Checkout, and Order fixture with the same Variant ID, currency, market, buyer context, and sale basis.
- Validate values greater than, equal to, and lower than
price; currency inheritance from the enclosing resource; sale-basis behavior; and matching Cart or Checkout and Catalog values when Business pricing data has not changed.
- Verify that
list_price does not change price, line-item totals, resource totals, or structured discount attribution.
- Revalidate affected response schemas, specification examples, and generated models.
- Demonstrate one end-to-end Business–Platform integration in which Cart or Checkout returns
list_price, order creation retains the value, and a later Order response returns the same snapshot without a Catalog Lookup made solely for that value.
Graduation Criteria
Working Draft → Candidate
Candidate → Stable
Implementation History
Code of Conduct
Summary
Add an optional, response-only
list_priceto the sharedItemschema used by Cart, Checkout, and Order. The field carries the CatalogVariant.list_pricesemantic into those item responses.Cart and Checkout may return the current Business-authoritative value. When returned in an Order, the field represents the value captured at order creation. Platform Cart and Checkout requests omit it, and
priceand totals remain authoritative for transaction amounts.This proposal asks the Shopping Tech Council (TC) whether propagating an existing core Catalog semantic into the shared
Itemis appropriate for direct inclusion in the core protocol. If the TC requires extension-first validation, the proposal can be revised to use a vendor-specific extension before later core consideration.Motivation
UCP Catalog already defines
Variant.list_price, but the sharedItemembedded in Cart, Checkout, and Order contains the current unit price without the list price used for price comparison.A Platform that needs the current list price cannot obtain it from a Cart or Checkout response. It must omit the value or retrieve it from another source, such as Catalog Lookup. For Order, a later Catalog Lookup cannot reconstruct the value that applied when the order was created.
Carrying the existing Catalog semantic in the shared response makes each item snapshot self-contained for price comparison. Cart and Checkout return the current Business value, while Order may preserve the value captured at order creation. Transaction amounts remain defined by
price, line-item totals, and resource totals.Non-normative Cart item-row example. The strikethrough price represents
list_price. All other UI elements and displayed values are illustrative and do not define protocol behavior or required UI.Goals
Itemschema defines an optional, response-onlylist_price.list_price.list_price; the Business remains authoritative for the returned value.Variant.list_price. An Order value is the snapshot captured at order creation and is not refreshed from later Catalog state.list_pricewithout a Catalog request made solely for that value.Non-Goals
compare_at_price.Detailed Design
The proposal adds one optional property to
source/schemas/shopping/types/item.json. Cart and Checkout line items referencetypes/line_item.json, and Order line items referencetypes/order_line_item.json; both paths compose the sharedItem. The field therefore propagates to Cart, Checkout, Order, and extensions that reuse those schemas without adding a new operation or transport behavior.Schema Placement
The preferred core option adds
list_priceto the sharedItembecause it reuses an existing Catalog semantic and gives Cart, Checkout, and Order one portable field without extension negotiation. If the TC requires extension-first validation, the same response-only field can be composed through a vendor-specific extension before later core consideration.Alternatives Considered and Decision Requested
Variant.list_pricesemantic in the shared item snapshot. Cart, Checkout, and Order use one portable field, and no extension negotiation is required.Variant.list_pricesemantic into the sharedItemis appropriate, or should this first be validated as a vendor-specific extension?Resource and Request Scope
list_pricefor an item. A Platform MUST accept omission.list_pricefor an item. A Platform MUST accept omission.list_pricewhen it retained the value at order creation. When present, the field MUST represent that snapshot and MUST NOT be refreshed from later Catalog state. A Platform MUST accept omission.list_price. The Business remains authoritative for the returned value.Proposed Schema
The core proposal adds the optional response-only field below. If the TC selects extension-first validation, a follow-up revision will compose an equivalent field into Cart, Checkout, and Order response schemas.
{ "properties": { "list_price": { "$ref": "../../common/types/amount.json", "description": "List price before discounts. In an Order response, this is the snapshot captured at order creation.", "ucp_request": "omit" } } }Simplified Catalog → Cart → Checkout → Order Mapping Example
This abbreviated example shows the same Variant in Catalog, Cart, and Checkout, followed by the list-price snapshot retained when the Order is created. Unrelated required fields are omitted.
{ "catalog_variant": { "id": "variant_123", "price": { "amount": 3999, "currency": "USD" }, "list_price": { "amount": 4200, "currency": "USD" } }, "cart": { "currency": "USD", "line_items": [{ "item": { "id": "variant_123", "price": 3999, "list_price": 4200 } }] }, "checkout": { "currency": "USD", "line_items": [{ "item": { "id": "variant_123", "price": 3999, "list_price": 4200 } }] }, "order": { "currency": "USD", "line_items": [{ "item": { "id": "variant_123", "price": 3999, "list_price": 4200 } }] } }Protocol Behavior
list_priceis optional and response-only in Cart, Checkout, and Order. A Platform MUST omit it from Cart and Checkout requests.item.list_priceMUST equal CatalogVariant.list_price.amount, and the enclosing resource currency MUST equal CatalogVariant.list_price.currency.list_priceMUST be the snapshot captured at order creation and MUST NOT be refreshed from later Catalog state. A Business MAY omit the field if it did not retain that snapshot.list_priceis for price-comparison display. It MUST NOT changeprice, line-item totals, resource totals, or structured discount attribution. The protocol does not requirelist_priceto be greater thanprice.Risks and Mitigations
list_priceas an amount authorized for payment or settlement.list_pricecontains no executable content or sensitive data. It is display-only and MUST NOT drive authorization, payment, settlement, or totals.priceand totals remain authoritative.Itempropagates into Cart, Checkout, Order, and composed extensions.Test Plan
ucp-schema lint source/to validate schema syntax and references.ucp_request: "omit"removeslist_price. If the TC selects an extension, also verify negotiation and field absence when the extension is not negotiated.list_price.price; currency inheritance from the enclosing resource; sale-basis behavior; and matching Cart or Checkout and Catalog values when Business pricing data has not changed.list_pricedoes not changeprice, line-item totals, resource totals, or structured discount attribution.list_price, order creation retains the value, and a later Order response returns the same snapshot without a Catalog Lookup made solely for that value.Graduation Criteria
Working Draft → Candidate
ucp-schema lint source/passes.list_price, including an Order snapshot that remains unchanged after Catalog pricing changes.list_price, and at least one Platform consumes it without a Catalog Lookup made solely for that value. The integration also demonstrates Order omission or snapshot behavior.Candidate → Stable
Itemplacement, backward compatibility, Cart and Checkout consistency with Catalog, and Order snapshot behavior are documented.list_priceas a transaction amount or uses it to changepriceor totals.Implementation History
Code of Conduct