{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://ucp.dev/draft/schemas/shopping/purchase_options.json",
  "name": "dev.ucp.shopping.purchase_options",
  "title": "Purchase Options Extension",
  "description": "Extends Catalog, Cart, Checkout, and Order with the ways a variant can be bought: a Business lists `purchase_options`, a Platform selects one by `id`, and the Order preserves the selection. Also defines the `dev.ucp.shopping.policy.subscription` policy type.",
  "$defs": {
    "purchase_option": {
      "$ref": "https://ucp.dev/draft/schemas/shopping/types/purchase_option.json"
    },
    "variant_purchase_options": {
      "title": "Variant Purchase Options",
      "description": "The purchase option fields added to a catalog variant.",
      "type": "object",
      "properties": {
        "purchase_options": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/purchase_option"
          },
          "minItems": 1,
          "description": "The ways this variant can be bought, in the Business's order of preference. The first is the default, and the variant's `price` is its `price`. Absent when the variant is bought the ordinary way.",
          "ucp_request": "omit"
        }
      }
    },
    "purchase_options_variant": {
      "description": "A catalog variant carrying purchase options.",
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/shopping/types/variant.json"
        },
        {
          "$ref": "#/$defs/variant_purchase_options"
        }
      ]
    },
    "purchase_options_lookup_variant": {
      "description": "A lookup variant (carrying input correlation) carrying purchase options.",
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/shopping/catalog_lookup.json#/$defs/lookup_variant"
        },
        {
          "$ref": "#/$defs/variant_purchase_options"
        }
      ]
    },
    "purchase_options_product": {
      "description": "A catalog product whose variants carry purchase options. Used by search.",
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/shopping/types/product.json"
        },
        {
          "type": "object",
          "properties": {
            "variants": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/purchase_options_variant"
              }
            }
          }
        }
      ]
    },
    "purchase_options_lookup_product": {
      "description": "A lookup product whose variants carry purchase options, preserving input correlation. Used by lookup.",
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/shopping/types/product.json"
        },
        {
          "type": "object",
          "properties": {
            "variants": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/purchase_options_lookup_variant"
              }
            }
          }
        }
      ]
    },
    "purchase_options_detail_product": {
      "description": "A get_product detail product whose variants carry purchase options. Used by get_product.",
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/shopping/catalog_lookup.json#/$defs/detail_product"
        },
        {
          "type": "object",
          "properties": {
            "variants": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/purchase_options_variant"
              }
            }
          }
        }
      ]
    },
    "search_response": {
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/shopping/catalog_search.json#/$defs/search_response"
        },
        {
          "type": "object",
          "properties": {
            "products": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/purchase_options_product"
              }
            },
            "policies": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/policies_item"
              }
            }
          }
        }
      ]
    },
    "lookup_response": {
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/shopping/catalog_lookup.json#/$defs/lookup_response"
        },
        {
          "type": "object",
          "properties": {
            "products": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/purchase_options_lookup_product"
              }
            },
            "policies": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/policies_item"
              }
            }
          }
        }
      ]
    },
    "get_product_response": {
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/shopping/catalog_lookup.json#/$defs/get_product_response"
        },
        {
          "type": "object",
          "properties": {
            "product": {
              "$ref": "#/$defs/purchase_options_detail_product"
            },
            "policies": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/policies_item"
              }
            }
          }
        }
      ]
    },
    "line_item": {
      "title": "Line Item with Purchase Options",
      "description": "Line item extended with the options its variant can be bought through and the one selected.",
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/shopping/types/line_item.json"
        },
        {
          "type": "object",
          "properties": {
            "purchase_options": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/purchase_option"
              },
              "minItems": 1,
              "description": "The ways this line's variant can be bought, priced for this cart or checkout. The selected option's price is the line's `item.price`; the others are indicative.",
              "ucp_request": "omit"
            },
            "selected_purchase_option_id": {
              "type": "string",
              "description": "ID of the selected purchase option, one of `purchase_options[].id`. The Business selects the default where the Platform made no choice, and reports any change it makes with a `purchase_option_changed` warning.",
              "ucp_request": {
                "create": "optional",
                "update": "optional"
              },
              "ucp_response": "optional"
            }
          },
          "dependentRequired": {
            "purchase_options": [
              "selected_purchase_option_id"
            ]
          }
        }
      ]
    },
    "order_line_item": {
      "title": "Order Line Item with Purchase Option",
      "description": "Order line extended with the purchase option it was bought through.",
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/shopping/types/order_line_item.json"
        },
        {
          "type": "object",
          "properties": {
            "purchase_option": {
              "$ref": "#/$defs/purchase_option",
              "description": "The purchase option selected for this line, as it stood at checkout: a historical record, unchanged if the catalog option later changes, whose `id` need not still resolve. Its `price` is the line's `item.price`; its `schedules` are the recurring orders agreed to. Absent when the variant carried none.",
              "ucp_response": "optional"
            }
          }
        }
      ]
    },
    "subscription_policy": {
      "title": "Subscription Policy",
      "description": "A policy of type `dev.ucp.shopping.policy.subscription`: the terms of the recurring orders a line results in — until when, how the buyer cancels, and where they manage it. Targets the line items it governs. Adds no fields to the base policy.",
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/common/types/policy.json"
        },
        {
          "type": "object",
          "required": [
            "type"
          ],
          "properties": {
            "type": {
              "type": "string",
              "const": "dev.ucp.shopping.policy.subscription",
              "description": "Policy discriminator for subscription terms."
            }
          }
        }
      ]
    },
    "policies_item": {
      "description": "A `policies[]` entry; validates against `subscription_policy` when `type` is `dev.ucp.shopping.policy.subscription`.",
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/common/types/policy.json"
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "dev.ucp.shopping.policy.subscription"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "$ref": "#/$defs/subscription_policy"
          }
        }
      ]
    },
    "dev.ucp.shopping.catalog.search": {
      "description": "Catalog search composition with purchase options (extends dev.ucp.shopping.catalog.search).",
      "$defs": {
        "search_response": {
          "$ref": "#/$defs/search_response"
        }
      }
    },
    "dev.ucp.shopping.catalog.lookup": {
      "description": "Catalog lookup composition with purchase options (extends dev.ucp.shopping.catalog.lookup).",
      "$defs": {
        "lookup_response": {
          "$ref": "#/$defs/lookup_response"
        },
        "get_product_response": {
          "$ref": "#/$defs/get_product_response"
        }
      }
    },
    "dev.ucp.shopping.cart": {
      "title": "Cart with Purchase Options",
      "description": "Cart extended so each line can carry its variant's purchase options and the one selected, with subscription policies on `policies[]`.",
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/shopping/cart.json"
        },
        {
          "type": "object",
          "properties": {
            "line_items": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/line_item"
              },
              "ucp_request": "required"
            },
            "policies": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/policies_item"
              },
              "ucp_request": "omit"
            }
          }
        }
      ]
    },
    "dev.ucp.shopping.checkout": {
      "title": "Checkout with Purchase Options",
      "description": "Checkout extended so each line can carry its variant's purchase options and the one selected, with subscription policies on `policies[]`.",
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/shopping/checkout.json"
        },
        {
          "type": "object",
          "properties": {
            "line_items": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/line_item"
              },
              "ucp_request": {
                "create": "optional",
                "update": "required",
                "complete": "omit"
              }
            },
            "policies": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/policies_item"
              },
              "ucp_request": "omit"
            }
          }
        }
      ]
    },
    "dev.ucp.shopping.order": {
      "title": "Order with Purchase Options",
      "description": "Order extended so each line preserves the purchase option it was bought through, with the subscription policies agreed to on `policies[]`.",
      "allOf": [
        {
          "$ref": "https://ucp.dev/draft/schemas/shopping/order.json"
        },
        {
          "type": "object",
          "properties": {
            "line_items": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/order_line_item"
              }
            },
            "policies": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/policies_item"
              },
              "ucp_request": "omit"
            }
          }
        }
      ]
    }
  },
  "version": "2026-11-10"
}