Skip to content

[Proposal]: Return list_price in Cart, Checkout, and Order item responses #751

Description

@qinyingran-TT

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.

Cart item row showing the current price and a strikethrough list price

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

  • The TC-selected schema placement and specification are merged with the Working Draft disclaimer, and ucp-schema lint source/ passes.
  • Schema-validated examples cover Cart, Checkout, and Order responses with and without list_price, including an Order snapshot that remains unchanged after Catalog pricing changes.
  • Resolved Platform request schemas for Cart and Checkout prove that the field is Business-provided and response-only.
  • At least one Business implementation returns 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.
  • TC majority vote to advance.

Candidate → Stable

  • Feedback from at least two independent integrations, including at least one Business and one Platform, has been collected and addressed.
  • The shared Item placement, backward compatibility, Cart and Checkout consistency with Catalog, and Order snapshot behavior are documented.
  • No implementation treats list_price as a transaction amount or uses it to change price or totals.
  • TC majority vote to advance.

Implementation History

  • [2026-08-19]: Proposal submitted.
  • TC approved "Provisional"; capability enters "Working Draft".
  • TC approved advancement to "Candidate".
  • TC approved "Implemented"; capability enters "Stable".

Code of Conduct

  • I agree to follow this project's Code of Conduct

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions