diff --git a/docs/specification/cart.md b/docs/specification/cart.md new file mode 100644 index 000000000..d146db965 --- /dev/null +++ b/docs/specification/cart.md @@ -0,0 +1,52 @@ + + +# Cart Capability + +* **Capability Name:** `dev.ucp.shopping.cart` +* **Version:** `2026-01-11` + +## Overview + +The Cart capability provides a first-class basket for multi-item shopping before +checkout. It allows platforms to build, validate, and update carts without +collecting payment details. + +A cart can be converted into a checkout session by sending the cart's +`line_items` to the Checkout create endpoint. + +## Endpoints + +### Create Cart + +{{ method_fields('create_cart', 'rest.openapi.json', 'cart') }} + +### Get Cart + +{{ method_fields('get_cart', 'rest.openapi.json', 'cart') }} + +### Update Cart + +{{ method_fields('update_cart', 'rest.openapi.json', 'cart') }} + +## Schema + +{{ schema_fields('cart_resp', 'cart') }} + +## Related Specs + +* [Checkout Capability](checkout.md) +* [HTTP/REST Binding](checkout-rest.md) diff --git a/docs/specification/loyalty.md b/docs/specification/loyalty.md new file mode 100644 index 000000000..1e93c5e06 --- /dev/null +++ b/docs/specification/loyalty.md @@ -0,0 +1,93 @@ + + +# Loyalty Extension + +* **Capability Name:** `dev.ucp.shopping.loyalty` +* **Version:** `2026-01-11` +* **Extends:** `dev.ucp.shopping.checkout` + +## Overview + +The Loyalty extension lets platforms link a shopper's membership and apply +eligible benefits during checkout. It pairs with Identity Linking for account +connection and uses standard checkout updates to apply benefits or redeem +points. + +## Discovery + +Businesses advertise loyalty support in their discovery profile: + +```json +{ + "name": "dev.ucp.shopping.loyalty", + "version": "2026-01-11", + "spec": "https://ucp.dev/specification/loyalty", + "schema": "https://ucp.dev/schemas/shopping/loyalty.json", + "extends": "dev.ucp.shopping.checkout" +} +``` + +## Account Linking Flow + +1. The platform links the user's account using the Identity Linking capability. +2. The business returns a loyalty `member_id` or indicates linking is required. + +See [Identity Linking Capability](identity-linking.md) for OAuth requirements. + +## Benefit Application Flow + +1. Platform submits `loyalty` details in a checkout update. +2. Business applies benefits and returns `benefits_applied` with updated totals. + +### Example checkout update + +```json +{ + "id": "chk_123", + "loyalty": { + "program_id": "loyalty_prime", + "member_id": "member_456", + "redemption": { "points": 1200 } + } +} +``` + +### Example checkout response + +```json +{ + "id": "chk_123", + "loyalty": { + "program_id": "loyalty_prime", + "member_id": "member_456", + "status": "linked", + "tier": "gold", + "points_balance": 4200, + "benefits_applied": [ + { + "type": "points_redemption", + "amount": 1200, + "description": "Redeemed 1,200 points" + } + ] + } +} +``` + +## Schema + +{{ extension_schema_fields('loyalty.json#/$defs/loyalty_object', 'checkout') }} diff --git a/docs/specification/order.md b/docs/specification/order.md index 1f5fdd2f5..a9fa70c07 100644 --- a/docs/specification/order.md +++ b/docs/specification/order.md @@ -95,6 +95,11 @@ fulfillment: - Include amount when relevant - Can happen at any time regardless of fulfillment status +### Post-Order Management Extension + +For structured return, exchange, and refund events, see the +[Post-Order Management Extension](post-order.md). + ## Schema ### Order diff --git a/docs/specification/overview.md b/docs/specification/overview.md index 803784b95..6ce7e931e 100644 --- a/docs/specification/overview.md +++ b/docs/specification/overview.md @@ -181,6 +181,9 @@ Extensions can be: - **Official**: `dev.ucp.shopping.fulfillment` extends `dev.ucp.shopping.checkout` - **Vendor**: `com.example.installments` extends `dev.ucp.shopping.checkout` +Common extensions include `dev.ucp.shopping.discount`, `dev.ucp.shopping.fulfillment`, +`dev.ucp.shopping.loyalty`, and `dev.ucp.shopping.post_order`. + ### Schema Composition Extensions can add new fields and modify shared structures (e.g., discounts @@ -976,6 +979,7 @@ UCP defines a set of standard capabilities: | Capability Name | ID (URI) | Description | | :------------------- | :----------------------------------------------- | :----------------------------------------------------------------------------------------------------------- | +| **Cart** | `{{ ucp_url }}/schemas/shopping/cart.json` | Provides a first-class basket for multi-item shopping prior to checkout. | | **Checkout** | `{{ ucp_url }}/schemas/shopping/checkout.json` | Facilitates the creation and management of checkout sessions, including cart management and tax calculation. | | **Identity Linking** | - | Enables platforms to obtain authorization via OAuth 2.0 to perform actions on a user's behalf. | | **Order** | `{{ ucp_url }}/schemas/shopping/order.json` | Allows businesses to push asynchronous updates about an order's lifecycle (shipping, delivery, returns). | @@ -1168,4 +1172,4 @@ Vendors control their own release schedules and versioning strategy. | **Payment Service Provider** | PSP | The financial infrastructure provider that processes payments, authorizations, and settlements on behalf of the business. | | **Platform** | - | The consumer-facing surface (AI agent, app, website) acting on behalf of the user to discover businesses and facilitate commerce. | | **Verifiable Digital Credential** | VDC | An Issuer-signed credential (set of claims) whose authenticity can be verified cryptographically. Used in UCP for secure payment authorizations. | -| **Verifiable Presentation** | VP | A presentation of one or more VDCs that includes a cryptographic proof of binding, used to prove authorization to a business or PSP. | \ No newline at end of file +| **Verifiable Presentation** | VP | A presentation of one or more VDCs that includes a cryptographic proof of binding, used to prove authorization to a business or PSP. | diff --git a/docs/specification/post-order.md b/docs/specification/post-order.md new file mode 100644 index 000000000..0516d319e --- /dev/null +++ b/docs/specification/post-order.md @@ -0,0 +1,78 @@ + + +# Post-Order Management Extension + +* **Capability Name:** `dev.ucp.shopping.post_order` +* **Version:** `2026-01-11` +* **Extends:** `dev.ucp.shopping.order` + +## Overview + +The Post-Order Management extension standardizes how businesses report returns, +exchanges, and refunds after a checkout completes. These events supplement the +base `adjustments` and fulfillment logs with explicit, structured post-order +signals. + +## Return Flow + +1. Platform initiates a return with the business (outside the core UCP flow). +2. Business appends a return event to the order response. + +## Exchange Flow + +1. Platform requests an exchange with desired replacements. +2. Business appends an exchange event to the order response. + +## Refund Flow + +1. Business issues a refund after return approval or cancellation. +2. Business appends a refund event to the order response. + +## Example Order Response + +```json +{ + "id": "order_123", + "post_order": { + "returns": [ + { + "id": "ret_1", + "status": "approved", + "occurred_at": "2026-01-11T14:30:00Z", + "line_items": [{ "id": "li_1", "quantity": 1 }], + "reason_code": "defective", + "description": "Defective item" + } + ], + "refunds": [ + { + "id": "ref_1", + "status": "completed", + "occurred_at": "2026-01-12T10:15:00Z", + "amount": 26550, + "line_items": [{ "id": "li_1", "quantity": 1 }], + "reason_code": "return_completed", + "description": "Refund after return" + } + ] + } +} +``` + +## Schema + +{{ extension_schema_fields('post_order.json#/$defs/post_order_object', 'order') }} diff --git a/mkdocs.yml b/mkdocs.yml index e39f3880f..16d3b13b2 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -30,6 +30,8 @@ nav: - Playground: playground.md - Specification: - Overview: specification/overview.md + - Cart Capability: + - Overview: specification/cart.md - Checkout Capability: - Overview: specification/checkout.md - HTTP/REST Binding: specification/checkout-rest.md @@ -40,7 +42,10 @@ nav: - Buyer Consent Extension: specification/buyer-consent.md - Discounts Extension: specification/discount.md - Fulfillment Extension: specification/fulfillment.md - - Order Capability: specification/order.md + - Loyalty Extension: specification/loyalty.md + - Order Capability: + - Overview: specification/order.md + - Post-Order Extension: specification/post-order.md - Identity Linking Capability: specification/identity-linking.md - Payment Handlers: - Guide: specification/payment-handler-guide.md @@ -187,6 +192,8 @@ plugins: - documentation/roadmap.md Specification Overview: - specification/overview.md + Cart Capability: + - specification/cart.md Checkout Capability: - specification/checkout.md - specification/checkout-rest.md @@ -198,8 +205,10 @@ plugins: - specification/discount.md - specification/embedded-checkout.md - specification/fulfillment.md + - specification/loyalty.md Order Capability: - specification/order.md + - specification/post-order.md Identity Linking Capability: - specification/identity-linking.md Payment Handlers: diff --git a/source/schemas/shopping/cart.json b/source/schemas/shopping/cart.json new file mode 100644 index 000000000..5ee9ef65d --- /dev/null +++ b/source/schemas/shopping/cart.json @@ -0,0 +1,94 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/cart.json", + "name": "dev.ucp.shopping.cart", + "version": "2026-01-11", + "title": "Cart", + "description": "Cart schema for multi-item baskets prior to checkout.", + "type": "object", + "required": [ + "ucp", + "id", + "line_items", + "status", + "currency", + "totals" + ], + "additionalProperties": true, + "properties": { + "ucp": { + "$ref": "../ucp.json#/$defs/response_cart", + "ucp_request": "omit" + }, + "id": { + "type": "string", + "description": "Unique cart identifier.", + "ucp_request": { + "create": "omit", + "update": "required" + } + }, + "line_items": { + "type": "array", + "items": { + "$ref": "types/line_item.json" + }, + "description": "List of line items in the cart." + }, + "buyer": { + "$ref": "types/buyer.json", + "description": "Representation of the buyer." + }, + "status": { + "type": "string", + "enum": [ + "active", + "ready_for_checkout", + "converted", + "abandoned", + "expired" + ], + "description": "Cart lifecycle status.", + "ucp_request": "omit" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code." + }, + "totals": { + "type": "array", + "items": { + "$ref": "types/total.json" + }, + "description": "Different cart totals.", + "ucp_request": "omit" + }, + "messages": { + "type": "array", + "items": { + "$ref": "types/message.json" + }, + "description": "Messages about cart state.", + "ucp_request": "omit" + }, + "links": { + "type": "array", + "items": { + "$ref": "types/link.json" + }, + "description": "Links to policies and terms.", + "ucp_request": "omit" + }, + "expires_at": { + "type": "string", + "format": "date-time", + "description": "RFC 3339 expiry timestamp.", + "ucp_request": "omit" + }, + "checkout_id": { + "type": "string", + "description": "Checkout session created from this cart, if converted.", + "ucp_request": "omit" + } + } +} diff --git a/source/schemas/shopping/loyalty.json b/source/schemas/shopping/loyalty.json new file mode 100644 index 000000000..f8eb4270e --- /dev/null +++ b/source/schemas/shopping/loyalty.json @@ -0,0 +1,102 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/loyalty.json", + "name": "dev.ucp.shopping.loyalty", + "version": "2026-01-11", + "title": "Loyalty Extension", + "description": "Extends Checkout with loyalty program linkage and benefit application.", + "$defs": { + "benefit": { + "type": "object", + "description": "A loyalty benefit applied to the checkout.", + "required": ["type", "amount"], + "properties": { + "type": { + "type": "string", + "description": "Benefit type (e.g., points_redemption, member_discount, free_shipping)." + }, + "amount": { + "type": "integer", + "minimum": 0, + "description": "Benefit value in minor (cents) currency units or points, depending on type." + }, + "description": { + "type": "string", + "description": "Human-readable description of the applied benefit." + } + } + }, + "redemption": { + "type": "object", + "description": "Requested redemption inputs from the platform.", + "properties": { + "points": { + "type": "integer", + "minimum": 0, + "description": "Number of points to redeem.", + "ucp_request": "optional" + } + } + }, + "loyalty_object": { + "type": "object", + "description": "Loyalty program linkage and benefit application state.", + "required": ["program_id"], + "properties": { + "program_id": { + "type": "string", + "description": "Identifier for the loyalty program." + }, + "member_id": { + "type": "string", + "description": "Member identifier for the linked account.", + "ucp_request": "optional" + }, + "status": { + "type": "string", + "enum": ["linked", "unlinked", "pending", "ineligible"], + "description": "Loyalty linkage status for this checkout.", + "ucp_request": "omit" + }, + "tier": { + "type": "string", + "description": "Member tier or segment label.", + "ucp_request": "omit" + }, + "points_balance": { + "type": "integer", + "minimum": 0, + "description": "Member points balance at the time of checkout.", + "ucp_request": "omit" + }, + "benefits_applied": { + "type": "array", + "items": { "$ref": "#/$defs/benefit" }, + "description": "Benefits applied to the checkout by the business.", + "ucp_request": "omit" + }, + "redemption": { + "$ref": "#/$defs/redemption", + "description": "Requested redemptions submitted by the platform.", + "ucp_request": "optional" + } + } + }, + "checkout": { + "title": "Checkout with Loyalty", + "description": "Checkout extended with loyalty capability.", + "allOf": [ + { "$ref": "checkout.json" }, + { + "type": "object", + "properties": { + "loyalty": { + "$ref": "#/$defs/loyalty_object", + "ucp_request": "optional" + } + } + } + ] + } + } +} diff --git a/source/schemas/shopping/post_order.json b/source/schemas/shopping/post_order.json new file mode 100644 index 000000000..c96ae7b1b --- /dev/null +++ b/source/schemas/shopping/post_order.json @@ -0,0 +1,173 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/post_order.json", + "name": "dev.ucp.shopping.post_order", + "version": "2026-01-11", + "title": "Post-Order Extension", + "description": "Extends Order with standardized return, exchange, and refund events.", + "$defs": { + "line_item_reference": { + "type": "object", + "required": ["id", "quantity"], + "properties": { + "id": { + "type": "string", + "description": "Line item ID reference." + }, + "quantity": { + "type": "integer", + "minimum": 1, + "description": "Quantity affected by this event." + } + } + }, + "return_event": { + "type": "object", + "description": "Return event for items after purchase.", + "required": ["id", "status", "occurred_at"], + "properties": { + "id": { + "type": "string", + "description": "Return event identifier." + }, + "status": { + "type": "string", + "enum": ["requested", "approved", "rejected", "in_progress", "completed", "canceled"], + "description": "Return status." + }, + "occurred_at": { + "type": "string", + "format": "date-time", + "description": "RFC 3339 timestamp when this event occurred." + }, + "line_items": { + "type": "array", + "items": { "$ref": "#/$defs/line_item_reference" }, + "description": "Line items and quantities included in the return." + }, + "reason_code": { + "type": "string", + "description": "Machine-readable return reason (e.g., defective, wrong_size)." + }, + "description": { + "type": "string", + "description": "Human-readable return reason." + } + } + }, + "exchange_event": { + "type": "object", + "description": "Exchange event for swapping items post-purchase.", + "required": ["id", "status", "occurred_at"], + "properties": { + "id": { + "type": "string", + "description": "Exchange event identifier." + }, + "status": { + "type": "string", + "enum": ["requested", "approved", "rejected", "in_progress", "completed", "canceled"], + "description": "Exchange status." + }, + "occurred_at": { + "type": "string", + "format": "date-time", + "description": "RFC 3339 timestamp when this event occurred." + }, + "line_items": { + "type": "array", + "items": { "$ref": "#/$defs/line_item_reference" }, + "description": "Line items and quantities being exchanged." + }, + "replacement_items": { + "type": "array", + "items": { "$ref": "#/$defs/line_item_reference" }, + "description": "Replacement line items and quantities." + }, + "reason_code": { + "type": "string", + "description": "Machine-readable exchange reason (e.g., wrong_size, color_change)." + }, + "description": { + "type": "string", + "description": "Human-readable exchange reason." + } + } + }, + "refund_event": { + "type": "object", + "description": "Refund event for returned or canceled items.", + "required": ["id", "status", "occurred_at", "amount"], + "properties": { + "id": { + "type": "string", + "description": "Refund event identifier." + }, + "status": { + "type": "string", + "enum": ["pending", "completed", "failed"], + "description": "Refund status." + }, + "occurred_at": { + "type": "string", + "format": "date-time", + "description": "RFC 3339 timestamp when this refund occurred." + }, + "amount": { + "type": "integer", + "description": "Refund amount in minor (cents) currency units." + }, + "line_items": { + "type": "array", + "items": { "$ref": "#/$defs/line_item_reference" }, + "description": "Line items and quantities included in the refund." + }, + "reason_code": { + "type": "string", + "description": "Machine-readable refund reason (e.g., return_completed)." + }, + "description": { + "type": "string", + "description": "Human-readable refund reason." + } + } + }, + "post_order_object": { + "type": "object", + "description": "Structured post-order events for returns, exchanges, and refunds.", + "properties": { + "returns": { + "type": "array", + "items": { "$ref": "#/$defs/return_event" }, + "description": "Return events for the order." + }, + "exchanges": { + "type": "array", + "items": { "$ref": "#/$defs/exchange_event" }, + "description": "Exchange events for the order." + }, + "refunds": { + "type": "array", + "items": { "$ref": "#/$defs/refund_event" }, + "description": "Refund events for the order." + } + } + }, + "order": { + "title": "Order with Post-Order Events", + "description": "Order extended with post-order management data.", + "allOf": [ + { "$ref": "order.json" }, + { + "type": "object", + "properties": { + "post_order": { + "$ref": "#/$defs/post_order_object", + "ucp_request": "omit" + } + } + } + ] + } + } +} diff --git a/source/schemas/ucp.json b/source/schemas/ucp.json index b532a1045..b98d732be 100644 --- a/source/schemas/ucp.json +++ b/source/schemas/ucp.json @@ -48,6 +48,21 @@ } }, + "response_cart": { + "title": "UCP Cart Response", + "description": "UCP metadata for cart responses.", + "type": "object", + "required": ["version", "capabilities"], + "properties": { + "version": {"$ref": "#/$defs/version"}, + "capabilities": { + "type": "array", + "description": "Active capabilities for this response.", + "items": {"$ref": "capability.json#/$defs/response"} + } + } + }, + "response_order": { "title": "UCP Order Response", "description": "UCP metadata for order responses. No payment handlers needed post-purchase.", diff --git a/source/services/shopping/openapi.json b/source/services/shopping/openapi.json index 2d7bfacf4..fabf0ead5 100644 --- a/source/services/shopping/openapi.json +++ b/source/services/shopping/openapi.json @@ -18,6 +18,188 @@ } ], "paths": { + "/carts": { + "post": { + "operationId": "create_cart", + "summary": "Create Cart", + "description": "Create a cart session. Called when a user begins building a basket.", + "parameters": [ + { + "$ref": "#/components/parameters/authorization" + }, + { + "$ref": "#/components/parameters/x_api_key" + }, + { + "$ref": "#/components/parameters/request_signature" + }, + { + "$ref": "#/components/parameters/idempotency_key" + }, + { + "$ref": "#/components/parameters/request_id" + }, + { + "$ref": "#/components/parameters/user_agent" + }, + { + "$ref": "#/components/parameters/content_type" + }, + { + "$ref": "#/components/parameters/accept" + }, + { + "$ref": "#/components/parameters/accept_language" + }, + { + "$ref": "#/components/parameters/accept_encoding" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/cart" } + } + } + }, + "responses": { + "201": { + "description": "Cart created", + "headers": { + "X-Detached-JWT": { + "$ref": "#/components/headers/x_detached_jwt" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/cart" + } + } + } + } + } + } + }, + "/carts/{id}": { + "parameters": [ + { "$ref": "#/components/parameters/cart_id_path" } + ], + "get": { + "operationId": "get_cart", + "summary": "Get Cart", + "description": "Get the latest state of a cart session.", + "parameters": [ + { + "$ref": "#/components/parameters/authorization" + }, + { + "$ref": "#/components/parameters/x_api_key" + }, + { + "$ref": "#/components/parameters/request_signature" + }, + { + "$ref": "#/components/parameters/request_id" + }, + { + "$ref": "#/components/parameters/user_agent" + }, + { + "$ref": "#/components/parameters/content_type" + }, + { + "$ref": "#/components/parameters/accept" + }, + { + "$ref": "#/components/parameters/accept_language" + }, + { + "$ref": "#/components/parameters/accept_encoding" + } + ], + "responses": { + "200": { + "description": "Cart retrieved", + "headers": { + "X-Detached-JWT": { + "$ref": "#/components/headers/x_detached_jwt" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/cart" + } + } + } + } + } + }, + "put": { + "operationId": "update_cart", + "summary": "Update Cart", + "description": "If an optional field is provided in the request body, its value is treated as a complete replacement for the corresponding data. If optional field is omitted, then current cart session is unchanged.", + "parameters": [ + { + "$ref": "#/components/parameters/authorization" + }, + { + "$ref": "#/components/parameters/x_api_key" + }, + { + "$ref": "#/components/parameters/request_signature" + }, + { + "$ref": "#/components/parameters/idempotency_key" + }, + { + "$ref": "#/components/parameters/request_id" + }, + { + "$ref": "#/components/parameters/user_agent" + }, + { + "$ref": "#/components/parameters/content_type" + }, + { + "$ref": "#/components/parameters/accept" + }, + { + "$ref": "#/components/parameters/accept_language" + }, + { + "$ref": "#/components/parameters/accept_encoding" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/cart" } + } + } + }, + "responses": { + "200": { + "description": "Cart updated", + "headers": { + "X-Detached-JWT": { + "$ref": "#/components/headers/x_detached_jwt" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/cart" + } + } + } + } + } + } + }, "/checkout-sessions": { "post": { "operationId": "create_checkout", @@ -400,6 +582,15 @@ }, "components": { "parameters": { + "cart_id_path": { + "name": "id", + "in": "path", + "required": true, + "description": "The unique identifier of the cart.", + "schema": { + "type": "string" + } + }, "checkout_session_id_path": { "name": "id", "in": "path", @@ -512,6 +703,9 @@ } }, "schemas": { + "cart": { + "$ref": "https://ucp.dev/schemas/shopping/cart.json" + }, "checkout": { "$ref": "https://ucp.dev/schemas/shopping/checkout.json" }, diff --git a/spec/schemas/shopping/cart.create_req.json b/spec/schemas/shopping/cart.create_req.json new file mode 100644 index 000000000..1317399b3 --- /dev/null +++ b/spec/schemas/shopping/cart.create_req.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/cart.create_req.json", + "name": "dev.ucp.shopping.cart", + "version": "2026-01-11", + "title": "Cart Create Request", + "description": "Cart schema for multi-item baskets prior to checkout.", + "type": "object", + "required": [ + "line_items", + "currency" + ], + "additionalProperties": true, + "properties": { + "line_items": { + "type": "array", + "items": { + "$ref": "types/line_item.create_req.json" + }, + "description": "List of line items in the cart." + }, + "buyer": { + "$ref": "types/buyer.json", + "description": "Representation of the buyer." + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code." + } + } +} diff --git a/spec/schemas/shopping/cart.update_req.json b/spec/schemas/shopping/cart.update_req.json new file mode 100644 index 000000000..7b08ab25b --- /dev/null +++ b/spec/schemas/shopping/cart.update_req.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/cart.update_req.json", + "name": "dev.ucp.shopping.cart", + "version": "2026-01-11", + "title": "Cart Update Request", + "description": "Cart schema for multi-item baskets prior to checkout.", + "type": "object", + "required": [ + "id", + "line_items", + "currency" + ], + "additionalProperties": true, + "properties": { + "id": { + "type": "string", + "description": "Unique cart identifier." + }, + "line_items": { + "type": "array", + "items": { + "$ref": "types/line_item.update_req.json" + }, + "description": "List of line items in the cart." + }, + "buyer": { + "$ref": "types/buyer.json", + "description": "Representation of the buyer." + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code." + } + } +} diff --git a/spec/schemas/shopping/cart_resp.json b/spec/schemas/shopping/cart_resp.json new file mode 100644 index 000000000..de2f7f7ea --- /dev/null +++ b/spec/schemas/shopping/cart_resp.json @@ -0,0 +1,83 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/cart.json", + "name": "dev.ucp.shopping.cart", + "version": "2026-01-11", + "title": "Cart Response", + "description": "Cart schema for multi-item baskets prior to checkout.", + "type": "object", + "required": [ + "ucp", + "id", + "line_items", + "status", + "currency", + "totals" + ], + "additionalProperties": true, + "properties": { + "ucp": { + "$ref": "../ucp.json#/$defs/response_cart" + }, + "id": { + "type": "string", + "description": "Unique cart identifier." + }, + "line_items": { + "type": "array", + "items": { + "$ref": "types/line_item_resp.json" + }, + "description": "List of line items in the cart." + }, + "buyer": { + "$ref": "types/buyer.json", + "description": "Representation of the buyer." + }, + "status": { + "type": "string", + "enum": [ + "active", + "ready_for_checkout", + "converted", + "abandoned", + "expired" + ], + "description": "Cart lifecycle status." + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code." + }, + "totals": { + "type": "array", + "items": { + "$ref": "types/total_resp.json" + }, + "description": "Different cart totals." + }, + "messages": { + "type": "array", + "items": { + "$ref": "types/message.json" + }, + "description": "Messages about cart state." + }, + "links": { + "type": "array", + "items": { + "$ref": "types/link.json" + }, + "description": "Links to policies and terms." + }, + "expires_at": { + "type": "string", + "format": "date-time", + "description": "RFC 3339 expiry timestamp." + }, + "checkout_id": { + "type": "string", + "description": "Checkout session created from this cart, if converted." + } + } +} diff --git a/spec/schemas/shopping/loyalty.create_req.json b/spec/schemas/shopping/loyalty.create_req.json new file mode 100644 index 000000000..2e68f1fe0 --- /dev/null +++ b/spec/schemas/shopping/loyalty.create_req.json @@ -0,0 +1,82 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/loyalty.create_req.json", + "name": "dev.ucp.shopping.loyalty", + "version": "2026-01-11", + "title": "Loyalty Extension Create Request", + "description": "Extends Checkout with loyalty program linkage and benefit application.", + "$defs": { + "benefit": { + "type": "object", + "description": "A loyalty benefit applied to the checkout.", + "required": [ + "type", + "amount" + ], + "properties": { + "type": { + "type": "string", + "description": "Benefit type (e.g., points_redemption, member_discount, free_shipping)." + }, + "amount": { + "type": "integer", + "minimum": 0, + "description": "Benefit value in minor (cents) currency units or points, depending on type." + }, + "description": { + "type": "string", + "description": "Human-readable description of the applied benefit." + } + } + }, + "redemption": { + "type": "object", + "description": "Requested redemption inputs from the platform.", + "properties": { + "points": { + "type": "integer", + "minimum": 0, + "description": "Number of points to redeem." + } + } + }, + "loyalty_object": { + "type": "object", + "description": "Loyalty program linkage and benefit application state.", + "required": [ + "program_id" + ], + "properties": { + "program_id": { + "type": "string", + "description": "Identifier for the loyalty program." + }, + "member_id": { + "type": "string", + "description": "Member identifier for the linked account." + }, + "redemption": { + "$ref": "#/$defs/redemption", + "description": "Requested redemptions submitted by the platform." + } + } + }, + "checkout": { + "title": "Checkout with Loyalty Create Request", + "description": "Checkout extended with loyalty capability.", + "allOf": [ + { + "$ref": "checkout.create_req.json" + }, + { + "type": "object", + "properties": { + "loyalty": { + "$ref": "#/$defs/loyalty_object" + } + } + } + ] + } + } +} diff --git a/spec/schemas/shopping/loyalty.update_req.json b/spec/schemas/shopping/loyalty.update_req.json new file mode 100644 index 000000000..9df5db36f --- /dev/null +++ b/spec/schemas/shopping/loyalty.update_req.json @@ -0,0 +1,82 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/loyalty.update_req.json", + "name": "dev.ucp.shopping.loyalty", + "version": "2026-01-11", + "title": "Loyalty Extension Update Request", + "description": "Extends Checkout with loyalty program linkage and benefit application.", + "$defs": { + "benefit": { + "type": "object", + "description": "A loyalty benefit applied to the checkout.", + "required": [ + "type", + "amount" + ], + "properties": { + "type": { + "type": "string", + "description": "Benefit type (e.g., points_redemption, member_discount, free_shipping)." + }, + "amount": { + "type": "integer", + "minimum": 0, + "description": "Benefit value in minor (cents) currency units or points, depending on type." + }, + "description": { + "type": "string", + "description": "Human-readable description of the applied benefit." + } + } + }, + "redemption": { + "type": "object", + "description": "Requested redemption inputs from the platform.", + "properties": { + "points": { + "type": "integer", + "minimum": 0, + "description": "Number of points to redeem." + } + } + }, + "loyalty_object": { + "type": "object", + "description": "Loyalty program linkage and benefit application state.", + "required": [ + "program_id" + ], + "properties": { + "program_id": { + "type": "string", + "description": "Identifier for the loyalty program." + }, + "member_id": { + "type": "string", + "description": "Member identifier for the linked account." + }, + "redemption": { + "$ref": "#/$defs/redemption", + "description": "Requested redemptions submitted by the platform." + } + } + }, + "checkout": { + "title": "Checkout with Loyalty Update Request", + "description": "Checkout extended with loyalty capability.", + "allOf": [ + { + "$ref": "checkout.update_req.json" + }, + { + "type": "object", + "properties": { + "loyalty": { + "$ref": "#/$defs/loyalty_object" + } + } + } + ] + } + } +} diff --git a/spec/schemas/shopping/loyalty_resp.json b/spec/schemas/shopping/loyalty_resp.json new file mode 100644 index 000000000..d8b06ab87 --- /dev/null +++ b/spec/schemas/shopping/loyalty_resp.json @@ -0,0 +1,108 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/loyalty.json", + "name": "dev.ucp.shopping.loyalty", + "version": "2026-01-11", + "title": "Loyalty Extension Response", + "description": "Extends Checkout with loyalty program linkage and benefit application.", + "$defs": { + "benefit": { + "type": "object", + "description": "A loyalty benefit applied to the checkout.", + "required": [ + "type", + "amount" + ], + "properties": { + "type": { + "type": "string", + "description": "Benefit type (e.g., points_redemption, member_discount, free_shipping)." + }, + "amount": { + "type": "integer", + "minimum": 0, + "description": "Benefit value in minor (cents) currency units or points, depending on type." + }, + "description": { + "type": "string", + "description": "Human-readable description of the applied benefit." + } + } + }, + "redemption": { + "type": "object", + "description": "Requested redemption inputs from the platform.", + "properties": { + "points": { + "type": "integer", + "minimum": 0, + "description": "Number of points to redeem." + } + } + }, + "loyalty_object": { + "type": "object", + "description": "Loyalty program linkage and benefit application state.", + "required": [ + "program_id" + ], + "properties": { + "program_id": { + "type": "string", + "description": "Identifier for the loyalty program." + }, + "member_id": { + "type": "string", + "description": "Member identifier for the linked account." + }, + "status": { + "type": "string", + "enum": [ + "linked", + "unlinked", + "pending", + "ineligible" + ], + "description": "Loyalty linkage status for this checkout." + }, + "tier": { + "type": "string", + "description": "Member tier or segment label." + }, + "points_balance": { + "type": "integer", + "minimum": 0, + "description": "Member points balance at the time of checkout." + }, + "benefits_applied": { + "type": "array", + "items": { + "$ref": "#/$defs/benefit" + }, + "description": "Benefits applied to the checkout by the business." + }, + "redemption": { + "$ref": "#/$defs/redemption", + "description": "Requested redemptions submitted by the platform." + } + } + }, + "checkout": { + "title": "Checkout with Loyalty Response", + "description": "Checkout extended with loyalty capability.", + "allOf": [ + { + "$ref": "checkout_resp.json" + }, + { + "type": "object", + "properties": { + "loyalty": { + "$ref": "#/$defs/loyalty_object" + } + } + } + ] + } + } +} diff --git a/spec/schemas/shopping/post_order.create_req.json b/spec/schemas/shopping/post_order.create_req.json new file mode 100644 index 000000000..081096e74 --- /dev/null +++ b/spec/schemas/shopping/post_order.create_req.json @@ -0,0 +1,218 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/post_order.create_req.json", + "name": "dev.ucp.shopping.post_order", + "version": "2026-01-11", + "title": "Post-Order Extension Create Request", + "description": "Extends Order with standardized return, exchange, and refund events.", + "$defs": { + "line_item_reference": { + "type": "object", + "required": [ + "id", + "quantity" + ], + "properties": { + "id": { + "type": "string", + "description": "Line item ID reference." + }, + "quantity": { + "type": "integer", + "minimum": 1, + "description": "Quantity affected by this event." + } + } + }, + "return_event": { + "type": "object", + "description": "Return event for items after purchase.", + "required": [ + "id", + "status", + "occurred_at" + ], + "properties": { + "id": { + "type": "string", + "description": "Return event identifier." + }, + "status": { + "type": "string", + "enum": [ + "requested", + "approved", + "rejected", + "in_progress", + "completed", + "canceled" + ], + "description": "Return status." + }, + "occurred_at": { + "type": "string", + "format": "date-time", + "description": "RFC 3339 timestamp when this event occurred." + }, + "line_items": { + "type": "array", + "items": { + "$ref": "#/$defs/line_item_reference" + }, + "description": "Line items and quantities included in the return." + }, + "reason_code": { + "type": "string", + "description": "Machine-readable return reason (e.g., defective, wrong_size)." + }, + "description": { + "type": "string", + "description": "Human-readable return reason." + } + } + }, + "exchange_event": { + "type": "object", + "description": "Exchange event for swapping items post-purchase.", + "required": [ + "id", + "status", + "occurred_at" + ], + "properties": { + "id": { + "type": "string", + "description": "Exchange event identifier." + }, + "status": { + "type": "string", + "enum": [ + "requested", + "approved", + "rejected", + "in_progress", + "completed", + "canceled" + ], + "description": "Exchange status." + }, + "occurred_at": { + "type": "string", + "format": "date-time", + "description": "RFC 3339 timestamp when this event occurred." + }, + "line_items": { + "type": "array", + "items": { + "$ref": "#/$defs/line_item_reference" + }, + "description": "Line items and quantities being exchanged." + }, + "replacement_items": { + "type": "array", + "items": { + "$ref": "#/$defs/line_item_reference" + }, + "description": "Replacement line items and quantities." + }, + "reason_code": { + "type": "string", + "description": "Machine-readable exchange reason (e.g., wrong_size, color_change)." + }, + "description": { + "type": "string", + "description": "Human-readable exchange reason." + } + } + }, + "refund_event": { + "type": "object", + "description": "Refund event for returned or canceled items.", + "required": [ + "id", + "status", + "occurred_at", + "amount" + ], + "properties": { + "id": { + "type": "string", + "description": "Refund event identifier." + }, + "status": { + "type": "string", + "enum": [ + "pending", + "completed", + "failed" + ], + "description": "Refund status." + }, + "occurred_at": { + "type": "string", + "format": "date-time", + "description": "RFC 3339 timestamp when this refund occurred." + }, + "amount": { + "type": "integer", + "description": "Refund amount in minor (cents) currency units." + }, + "line_items": { + "type": "array", + "items": { + "$ref": "#/$defs/line_item_reference" + }, + "description": "Line items and quantities included in the refund." + }, + "reason_code": { + "type": "string", + "description": "Machine-readable refund reason (e.g., return_completed)." + }, + "description": { + "type": "string", + "description": "Human-readable refund reason." + } + } + }, + "post_order_object": { + "type": "object", + "description": "Structured post-order events for returns, exchanges, and refunds.", + "properties": { + "returns": { + "type": "array", + "items": { + "$ref": "#/$defs/return_event" + }, + "description": "Return events for the order." + }, + "exchanges": { + "type": "array", + "items": { + "$ref": "#/$defs/exchange_event" + }, + "description": "Exchange events for the order." + }, + "refunds": { + "type": "array", + "items": { + "$ref": "#/$defs/refund_event" + }, + "description": "Refund events for the order." + } + } + }, + "order": { + "title": "Order with Post-Order Events Create Request", + "description": "Order extended with post-order management data.", + "allOf": [ + { + "$ref": "order.json" + }, + { + "type": "object", + "properties": {} + } + ] + } + } +} diff --git a/spec/schemas/shopping/post_order.update_req.json b/spec/schemas/shopping/post_order.update_req.json new file mode 100644 index 000000000..81799dcb7 --- /dev/null +++ b/spec/schemas/shopping/post_order.update_req.json @@ -0,0 +1,218 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/post_order.update_req.json", + "name": "dev.ucp.shopping.post_order", + "version": "2026-01-11", + "title": "Post-Order Extension Update Request", + "description": "Extends Order with standardized return, exchange, and refund events.", + "$defs": { + "line_item_reference": { + "type": "object", + "required": [ + "id", + "quantity" + ], + "properties": { + "id": { + "type": "string", + "description": "Line item ID reference." + }, + "quantity": { + "type": "integer", + "minimum": 1, + "description": "Quantity affected by this event." + } + } + }, + "return_event": { + "type": "object", + "description": "Return event for items after purchase.", + "required": [ + "id", + "status", + "occurred_at" + ], + "properties": { + "id": { + "type": "string", + "description": "Return event identifier." + }, + "status": { + "type": "string", + "enum": [ + "requested", + "approved", + "rejected", + "in_progress", + "completed", + "canceled" + ], + "description": "Return status." + }, + "occurred_at": { + "type": "string", + "format": "date-time", + "description": "RFC 3339 timestamp when this event occurred." + }, + "line_items": { + "type": "array", + "items": { + "$ref": "#/$defs/line_item_reference" + }, + "description": "Line items and quantities included in the return." + }, + "reason_code": { + "type": "string", + "description": "Machine-readable return reason (e.g., defective, wrong_size)." + }, + "description": { + "type": "string", + "description": "Human-readable return reason." + } + } + }, + "exchange_event": { + "type": "object", + "description": "Exchange event for swapping items post-purchase.", + "required": [ + "id", + "status", + "occurred_at" + ], + "properties": { + "id": { + "type": "string", + "description": "Exchange event identifier." + }, + "status": { + "type": "string", + "enum": [ + "requested", + "approved", + "rejected", + "in_progress", + "completed", + "canceled" + ], + "description": "Exchange status." + }, + "occurred_at": { + "type": "string", + "format": "date-time", + "description": "RFC 3339 timestamp when this event occurred." + }, + "line_items": { + "type": "array", + "items": { + "$ref": "#/$defs/line_item_reference" + }, + "description": "Line items and quantities being exchanged." + }, + "replacement_items": { + "type": "array", + "items": { + "$ref": "#/$defs/line_item_reference" + }, + "description": "Replacement line items and quantities." + }, + "reason_code": { + "type": "string", + "description": "Machine-readable exchange reason (e.g., wrong_size, color_change)." + }, + "description": { + "type": "string", + "description": "Human-readable exchange reason." + } + } + }, + "refund_event": { + "type": "object", + "description": "Refund event for returned or canceled items.", + "required": [ + "id", + "status", + "occurred_at", + "amount" + ], + "properties": { + "id": { + "type": "string", + "description": "Refund event identifier." + }, + "status": { + "type": "string", + "enum": [ + "pending", + "completed", + "failed" + ], + "description": "Refund status." + }, + "occurred_at": { + "type": "string", + "format": "date-time", + "description": "RFC 3339 timestamp when this refund occurred." + }, + "amount": { + "type": "integer", + "description": "Refund amount in minor (cents) currency units." + }, + "line_items": { + "type": "array", + "items": { + "$ref": "#/$defs/line_item_reference" + }, + "description": "Line items and quantities included in the refund." + }, + "reason_code": { + "type": "string", + "description": "Machine-readable refund reason (e.g., return_completed)." + }, + "description": { + "type": "string", + "description": "Human-readable refund reason." + } + } + }, + "post_order_object": { + "type": "object", + "description": "Structured post-order events for returns, exchanges, and refunds.", + "properties": { + "returns": { + "type": "array", + "items": { + "$ref": "#/$defs/return_event" + }, + "description": "Return events for the order." + }, + "exchanges": { + "type": "array", + "items": { + "$ref": "#/$defs/exchange_event" + }, + "description": "Exchange events for the order." + }, + "refunds": { + "type": "array", + "items": { + "$ref": "#/$defs/refund_event" + }, + "description": "Refund events for the order." + } + } + }, + "order": { + "title": "Order with Post-Order Events Update Request", + "description": "Order extended with post-order management data.", + "allOf": [ + { + "$ref": "order.json" + }, + { + "type": "object", + "properties": {} + } + ] + } + } +} diff --git a/spec/schemas/shopping/post_order_resp.json b/spec/schemas/shopping/post_order_resp.json new file mode 100644 index 000000000..11117201d --- /dev/null +++ b/spec/schemas/shopping/post_order_resp.json @@ -0,0 +1,222 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/post_order.json", + "name": "dev.ucp.shopping.post_order", + "version": "2026-01-11", + "title": "Post-Order Extension Response", + "description": "Extends Order with standardized return, exchange, and refund events.", + "$defs": { + "line_item_reference": { + "type": "object", + "required": [ + "id", + "quantity" + ], + "properties": { + "id": { + "type": "string", + "description": "Line item ID reference." + }, + "quantity": { + "type": "integer", + "minimum": 1, + "description": "Quantity affected by this event." + } + } + }, + "return_event": { + "type": "object", + "description": "Return event for items after purchase.", + "required": [ + "id", + "status", + "occurred_at" + ], + "properties": { + "id": { + "type": "string", + "description": "Return event identifier." + }, + "status": { + "type": "string", + "enum": [ + "requested", + "approved", + "rejected", + "in_progress", + "completed", + "canceled" + ], + "description": "Return status." + }, + "occurred_at": { + "type": "string", + "format": "date-time", + "description": "RFC 3339 timestamp when this event occurred." + }, + "line_items": { + "type": "array", + "items": { + "$ref": "#/$defs/line_item_reference" + }, + "description": "Line items and quantities included in the return." + }, + "reason_code": { + "type": "string", + "description": "Machine-readable return reason (e.g., defective, wrong_size)." + }, + "description": { + "type": "string", + "description": "Human-readable return reason." + } + } + }, + "exchange_event": { + "type": "object", + "description": "Exchange event for swapping items post-purchase.", + "required": [ + "id", + "status", + "occurred_at" + ], + "properties": { + "id": { + "type": "string", + "description": "Exchange event identifier." + }, + "status": { + "type": "string", + "enum": [ + "requested", + "approved", + "rejected", + "in_progress", + "completed", + "canceled" + ], + "description": "Exchange status." + }, + "occurred_at": { + "type": "string", + "format": "date-time", + "description": "RFC 3339 timestamp when this event occurred." + }, + "line_items": { + "type": "array", + "items": { + "$ref": "#/$defs/line_item_reference" + }, + "description": "Line items and quantities being exchanged." + }, + "replacement_items": { + "type": "array", + "items": { + "$ref": "#/$defs/line_item_reference" + }, + "description": "Replacement line items and quantities." + }, + "reason_code": { + "type": "string", + "description": "Machine-readable exchange reason (e.g., wrong_size, color_change)." + }, + "description": { + "type": "string", + "description": "Human-readable exchange reason." + } + } + }, + "refund_event": { + "type": "object", + "description": "Refund event for returned or canceled items.", + "required": [ + "id", + "status", + "occurred_at", + "amount" + ], + "properties": { + "id": { + "type": "string", + "description": "Refund event identifier." + }, + "status": { + "type": "string", + "enum": [ + "pending", + "completed", + "failed" + ], + "description": "Refund status." + }, + "occurred_at": { + "type": "string", + "format": "date-time", + "description": "RFC 3339 timestamp when this refund occurred." + }, + "amount": { + "type": "integer", + "description": "Refund amount in minor (cents) currency units." + }, + "line_items": { + "type": "array", + "items": { + "$ref": "#/$defs/line_item_reference" + }, + "description": "Line items and quantities included in the refund." + }, + "reason_code": { + "type": "string", + "description": "Machine-readable refund reason (e.g., return_completed)." + }, + "description": { + "type": "string", + "description": "Human-readable refund reason." + } + } + }, + "post_order_object": { + "type": "object", + "description": "Structured post-order events for returns, exchanges, and refunds.", + "properties": { + "returns": { + "type": "array", + "items": { + "$ref": "#/$defs/return_event" + }, + "description": "Return events for the order." + }, + "exchanges": { + "type": "array", + "items": { + "$ref": "#/$defs/exchange_event" + }, + "description": "Exchange events for the order." + }, + "refunds": { + "type": "array", + "items": { + "$ref": "#/$defs/refund_event" + }, + "description": "Refund events for the order." + } + } + }, + "order": { + "title": "Order with Post-Order Events Response", + "description": "Order extended with post-order management data.", + "allOf": [ + { + "$ref": "order.json" + }, + { + "type": "object", + "properties": { + "post_order": { + "$ref": "#/$defs/post_order_object" + } + } + } + ] + } + } +} diff --git a/spec/schemas/ucp.json b/spec/schemas/ucp.json index 0067c8a85..0e4134dc9 100644 --- a/spec/schemas/ucp.json +++ b/spec/schemas/ucp.json @@ -62,6 +62,27 @@ } } }, + "response_cart": { + "title": "UCP Cart Response", + "description": "UCP metadata for cart responses.", + "type": "object", + "required": [ + "version", + "capabilities" + ], + "properties": { + "version": { + "$ref": "#/$defs/version" + }, + "capabilities": { + "type": "array", + "description": "Active capabilities for this response.", + "items": { + "$ref": "capability.json#/$defs/response" + } + } + } + }, "response_order": { "title": "UCP Order Response", "description": "UCP metadata for order responses. No payment handlers needed post-purchase.", diff --git a/spec/services/shopping/rest.openapi.json b/spec/services/shopping/rest.openapi.json index 83b92f6d6..4c5728156 100644 --- a/spec/services/shopping/rest.openapi.json +++ b/spec/services/shopping/rest.openapi.json @@ -18,6 +18,194 @@ } ], "paths": { + "/carts": { + "post": { + "operationId": "create_cart", + "summary": "Create Cart", + "description": "Create a cart session. Called when a user begins building a basket.", + "parameters": [ + { + "$ref": "#/components/parameters/authorization" + }, + { + "$ref": "#/components/parameters/x_api_key" + }, + { + "$ref": "#/components/parameters/request_signature" + }, + { + "$ref": "#/components/parameters/idempotency_key" + }, + { + "$ref": "#/components/parameters/request_id" + }, + { + "$ref": "#/components/parameters/user_agent" + }, + { + "$ref": "#/components/parameters/content_type" + }, + { + "$ref": "#/components/parameters/accept" + }, + { + "$ref": "#/components/parameters/accept_language" + }, + { + "$ref": "#/components/parameters/accept_encoding" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/cart_create_request" + } + } + } + }, + "responses": { + "201": { + "description": "Cart created", + "headers": { + "X-Detached-JWT": { + "$ref": "#/components/headers/x_detached_jwt" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/cart_response" + } + } + } + } + } + } + }, + "/carts/{id}": { + "parameters": [ + { + "$ref": "#/components/parameters/cart_id_path" + } + ], + "get": { + "operationId": "get_cart", + "summary": "Get Cart", + "description": "Get the latest state of a cart session.", + "parameters": [ + { + "$ref": "#/components/parameters/authorization" + }, + { + "$ref": "#/components/parameters/x_api_key" + }, + { + "$ref": "#/components/parameters/request_signature" + }, + { + "$ref": "#/components/parameters/request_id" + }, + { + "$ref": "#/components/parameters/user_agent" + }, + { + "$ref": "#/components/parameters/content_type" + }, + { + "$ref": "#/components/parameters/accept" + }, + { + "$ref": "#/components/parameters/accept_language" + }, + { + "$ref": "#/components/parameters/accept_encoding" + } + ], + "responses": { + "200": { + "description": "Cart retrieved", + "headers": { + "X-Detached-JWT": { + "$ref": "#/components/headers/x_detached_jwt" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/cart_response" + } + } + } + } + } + }, + "put": { + "operationId": "update_cart", + "summary": "Update Cart", + "description": "If an optional field is provided in the request body, its value is treated as a complete replacement for the corresponding data. If optional field is omitted, then current cart session is unchanged.", + "parameters": [ + { + "$ref": "#/components/parameters/authorization" + }, + { + "$ref": "#/components/parameters/x_api_key" + }, + { + "$ref": "#/components/parameters/request_signature" + }, + { + "$ref": "#/components/parameters/idempotency_key" + }, + { + "$ref": "#/components/parameters/request_id" + }, + { + "$ref": "#/components/parameters/user_agent" + }, + { + "$ref": "#/components/parameters/content_type" + }, + { + "$ref": "#/components/parameters/accept" + }, + { + "$ref": "#/components/parameters/accept_language" + }, + { + "$ref": "#/components/parameters/accept_encoding" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/cart_update_request" + } + } + } + }, + "responses": { + "200": { + "description": "Cart updated", + "headers": { + "X-Detached-JWT": { + "$ref": "#/components/headers/x_detached_jwt" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/cart_response" + } + } + } + } + } + } + }, "/checkout-sessions": { "post": { "operationId": "create_checkout", @@ -425,6 +613,15 @@ }, "components": { "parameters": { + "cart_id_path": { + "name": "id", + "in": "path", + "required": true, + "description": "The unique identifier of the cart.", + "schema": { + "type": "string" + } + }, "checkout_session_id_path": { "name": "id", "in": "path", @@ -546,6 +743,15 @@ "ucp": { "$ref": "https://ucp.dev/schemas/ucp.json" }, + "cart_response": { + "$ref": "https://ucp.dev/schemas/shopping/cart_resp.json" + }, + "cart_create_request": { + "$ref": "https://ucp.dev/schemas/shopping/cart.create_req.json" + }, + "cart_update_request": { + "$ref": "https://ucp.dev/schemas/shopping/cart.update_req.json" + }, "checkout_response": { "$ref": "https://ucp.dev/schemas/shopping/checkout_resp.json" },