Skip to content

feat: add Return Extension to UCP specification#257

Open
venkatesh-ucp wants to merge 1 commit intoUniversal-Commerce-Protocol:mainfrom
venkatesh-ucp:returns-extension
Open

feat: add Return Extension to UCP specification#257
venkatesh-ucp wants to merge 1 commit intoUniversal-Commerce-Protocol:mainfrom
venkatesh-ucp:returns-extension

Conversation

@venkatesh-ucp
Copy link

@venkatesh-ucp venkatesh-ucp commented Mar 11, 2026

Summary

This proposal introduces a Return Extension to the UCP Checkout capability. It allows businesses to communicate the conditions, methods, timelines, and costs associated with returning physical items directly to the platform and the buyer, mirroring real-world commerce requirements.

Motivation

Currently, the UCP Fulfillment Extension only handles how physical goods get to a buyer (shipping, pickup, and associated options). However, returning items is a core primitive of physical commerce.

By exposing the return policy natively in the UCP schema, AI agents and platforms can intelligently answer user queries like "Can I return this in-store?" or "How many days do I have to return this?" without forcing the user to leave the platform to hunt for a policy on the merchant's website.

Use Cases

This schema addition is designed to support the following agentic and platform use cases:

  • Pre-Purchase Assurance: An AI agent proactively answers questions like "Can I return this if it doesn't fit?" before the user commits to a transaction.
  • Return Cost Transparency: A platform calculates the true financial risk of a purchase by exposing fixed restocking fees or making it clear when the buyer is responsible for return shipping costs.
  • Omnichannel Return Routing: A buyer wants to verify if an item bought online can be returned in-store to avoid the hassle of printing labels and mailing packages.
  • Exception Handling (Final Sale): Automatically warning buyers when specific items in a mixed cart (e.g., custom engraved jewelry, clearance apparel) are strictly non-returnable, preventing post-purchase disputes.

Detailed Design

Architectural Discussion: Fulfillment Extension vs. Standalone Extension

One of the main questions to answer before adding return policy support is around whether to embed return_policies within the existing Fulfillment Extension. Specifically, the question is whether returns are a subset of physical fulfillment, or if they represent a broader conceptual primitive (a "policy") that applies to line items independent of logistics.

Pros of Adding to the Fulfillment Extension

  1. Logistical Cohesion (Reverse Logistics): Fulfillment represents the physical lifecycle of a product. Returns are effectively reverse-fulfillment. Both domains deal with shipping methods, carriers, physical locations (in-store drop-offs), and transit fees. Grouping outbound delivery and inbound returns keeps all physical logistics data in one conceptual domain.
  2. Schema Pattern Reuse: The Fulfillment Extension already solves the complex problem of mapping logistical realities to specific parts of a cart via line_item_ids. Reusing this extension avoids duplicating the boilerplate required to map rules to specific items.
  3. Destination Dependency: While rare, return policies can sometimes depend on the fulfillment destination (e.g., domestic returns might be free, while cross-border returns are strictly "customer responsibility" or final sale). Tying returns to the fulfillment block acknowledges that where an item is shipped can dictate how it must be returned.

Cons of Adding to the Fulfillment Extension (The Case for a Standalone Extension - Preferred approach)

  1. Asymmetry of User Choice: The core behavior of the Fulfillment Extension is interactive: it presents a list of methods (Standard, Express, Pickup) and the buyer selects one. Return policies do not behave this way; they are immutable rules assigned by the merchant. The user does not select a return policy, but rather, they are forced into it based on the merchant or the items in their cart. Mixing selectable options with static rules in the same extension creates a semantically confused model.
  2. Limited Reusability Across Capabilities: UCP is designed to be highly composable. If return_policy is tightly coupled to the Fulfillment Extension, it becomes much harder to reuse the returns spec in other contexts. For example, a post-purchase Order capability or a simple product discovery agent might need to display return policies without carrying the irrelevant baggage of forward-fulfillment routing and shipping rate calculations.
  3. Lack of Cross-Shopping in Checkout: In the context of the UCP Checkout Capability, the user is already locked into completing the transaction with a specific merchant; there is no opportunity to cross-shop and compare fulfillment/return options against other merchants at this stage. Therefore, optimizing the schema for logistical comparison might be less valuable than optimizing it for clear, policy-based disclosure.

Proposed Entities

Return Policy Response

Name Type Required Description
id string Yes Unique identifier for the return policy.
line_item_ids Array[string] Yes Line items governed by this return policy, allowing distinct policies per item.
return_window_type string Yes The type of return window.

Enum:
• lifetime: Returns are accepted at any time, with no expiration.
• no_returns: Refunds are not allowed, but exchanges or store credit might be permitted depending on the `exchanges_allowed` flag.
• final_sale: Strictly no refunds and no exchanges under any circumstances.
• finite_window: Returns are only accepted within a set number of days.
return_days integer No Number of days allowed for a return, typically starting from the date of delivery. Required if category is finite_window.
exchanges_allowed boolean No Indicates whether the buyer can exchange the item. If omitted, the platform should assume false unless specified otherwise by the merchant.
methods Array[Return Method] No Permitted physical methods for returning the item, along with their associated fee structures.

Return Method Object

Name Type Required Description
type string Yes The physical method through which the buyer can return the item.

Enum:
• in_store: The buyer returns the item physically at a retail store location.
• by_mail: The buyer packages and ships the item back to the merchant via a carrier.
• kiosk: The buyer drops the item off at a designated self-service kiosk or drop-off point.
fee Return Fee Yes The cost structure associated with this specific return method.

Return Fee Object

Name Type Required Description
type string Yes The cost structure for the return method.

Enum:
• free: The merchant covers return costs (e.g., provides a prepaid shipping label or processes in-store drop-offs for free).
• fixed_fee: The merchant charges a flat fee (e.g., a restocking fee or a deducted return shipping fee).
• customer_responsibility: The buyer is entirely responsible for organizing, paying for, and delivering the item back to the business (e.g., paying for their own postage).
amount integer No Fixed return fee charged by the merchant, represented in minor currency units (e.g., cents). Required if type is fixed_fee.
display_text string No Human-readable text to display against the fee to provide context to the buyer (e.g., "Restocking Fee", "Return Shipping Label").

Example Payload

{
  "return_policies": [
    {
      "id": "rp_apparel",
      "line_item_ids": [
        "shirt",
        "pants"
      ],
      "category": "finite_window",
      "return_days": 30,
      "exchanges_allowed": true,
      "methods": [
        {
          "type": "in_store",
          "fee": {
            "type": "free",
            "display_text": "Free In-Store Return"
          }
        },
        {
          "type": "by_mail",
          "fee": {
            "type": "fixed_fee",
            "amount": 500,
            "display_text": "Return Shipping Fee"
          }
        }
      ]
    },
    {
      "id": "rp_final_sale",
      "line_item_ids": [
        "custom_engraved_watch"
      ],
      "category": "final_sale",
      "exchanges_allowed": false
    }
  ]
}

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • 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
  • Any dependent changes have been merged and published in downstream modules

This change introduces the Return Extension, allowing businesses to
communicate return conditions, methods, timelines, and costs.

Key changes:
- Added JSON schemas for Return Policy, Method, and Fee.
- Extended Checkout and Order with return policies.
- Renamed Return Policy 'category' to 'return_window_type'.
- Added specification documentation and updated site navigation.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant