portage-ucp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +15 -0
  3. data/LICENSE +21 -0
  4. data/README.md +97 -0
  5. data/exe/portage-ucp-check +25 -0
  6. data/lib/portage/ucp/adapter.rb +58 -0
  7. data/lib/portage/ucp/authenticator.rb +26 -0
  8. data/lib/portage/ucp/capabilities/cart.rb +16 -0
  9. data/lib/portage/ucp/capabilities/catalog.rb +11 -0
  10. data/lib/portage/ucp/capabilities/checkout.rb +17 -0
  11. data/lib/portage/ucp/capabilities/identity_linking.rb +13 -0
  12. data/lib/portage/ucp/capabilities/order.rb +11 -0
  13. data/lib/portage/ucp/capability.rb +27 -0
  14. data/lib/portage/ucp/capability_negotiator.rb +40 -0
  15. data/lib/portage/ucp/capability_registry.rb +21 -0
  16. data/lib/portage/ucp/check.rb +96 -0
  17. data/lib/portage/ucp/configuration.rb +35 -0
  18. data/lib/portage/ucp/dispatcher.rb +39 -0
  19. data/lib/portage/ucp/errors.rb +12 -0
  20. data/lib/portage/ucp/manifest.rb +58 -0
  21. data/lib/portage/ucp/mcp/server.rb +83 -0
  22. data/lib/portage/ucp/observability.rb +31 -0
  23. data/lib/portage/ucp/payment_token_guard.rb +41 -0
  24. data/lib/portage/ucp/rack/manifest_endpoint.rb +49 -0
  25. data/lib/portage/ucp/rack/webhook_endpoint.rb +54 -0
  26. data/lib/portage/ucp/rate_limiter.rb +27 -0
  27. data/lib/portage/ucp/resolver.rb +133 -0
  28. data/lib/portage/ucp/schema_validator.rb +53 -0
  29. data/lib/portage/ucp/support/amounts.rb +43 -0
  30. data/lib/portage/ucp/support/api_error.rb +39 -0
  31. data/lib/portage/ucp/support/checkout_state.rb +42 -0
  32. data/lib/portage/ucp/support/http_client.rb +54 -0
  33. data/lib/portage/ucp/support/idempotency.rb +26 -0
  34. data/lib/portage/ucp/support/line_item_status.rb +44 -0
  35. data/lib/portage/ucp/support/not_found.rb +25 -0
  36. data/lib/portage/ucp/support/token_exchange.rb +43 -0
  37. data/lib/portage/ucp/support/totals.rb +31 -0
  38. data/lib/portage/ucp/value_objects.rb +186 -0
  39. data/lib/portage/ucp/version.rb +5 -0
  40. data/lib/portage/ucp/wire_envelope.rb +25 -0
  41. data/lib/portage/ucp.rb +44 -0
  42. data/schemas/2026-04-08/schemas/capability.json +70 -0
  43. data/schemas/2026-04-08/schemas/payment_handler.json +67 -0
  44. data/schemas/2026-04-08/schemas/service.json +190 -0
  45. data/schemas/2026-04-08/schemas/shopping/cart.json +134 -0
  46. data/schemas/2026-04-08/schemas/shopping/catalog_lookup.json +207 -0
  47. data/schemas/2026-04-08/schemas/shopping/catalog_search.json +64 -0
  48. data/schemas/2026-04-08/schemas/shopping/checkout.json +131 -0
  49. data/schemas/2026-04-08/schemas/shopping/discount.json +148 -0
  50. data/schemas/2026-04-08/schemas/shopping/fulfillment.json +154 -0
  51. data/schemas/2026-04-08/schemas/shopping/order.json +113 -0
  52. data/schemas/2026-04-08/schemas/shopping/payment.json +16 -0
  53. data/schemas/2026-04-08/schemas/shopping/types/adjustment.json +69 -0
  54. data/schemas/2026-04-08/schemas/shopping/types/amount.json +8 -0
  55. data/schemas/2026-04-08/schemas/shopping/types/attribution.json +11 -0
  56. data/schemas/2026-04-08/schemas/shopping/types/available_payment_instrument.json +22 -0
  57. data/schemas/2026-04-08/schemas/shopping/types/business_fulfillment_config.json +38 -0
  58. data/schemas/2026-04-08/schemas/shopping/types/buyer.json +25 -0
  59. data/schemas/2026-04-08/schemas/shopping/types/category.json +20 -0
  60. data/schemas/2026-04-08/schemas/shopping/types/context.json +42 -0
  61. data/schemas/2026-04-08/schemas/shopping/types/description.json +22 -0
  62. data/schemas/2026-04-08/schemas/shopping/types/detail_option_value.json +22 -0
  63. data/schemas/2026-04-08/schemas/shopping/types/error_code.json +17 -0
  64. data/schemas/2026-04-08/schemas/shopping/types/error_response.json +31 -0
  65. data/schemas/2026-04-08/schemas/shopping/types/expectation.json +62 -0
  66. data/schemas/2026-04-08/schemas/shopping/types/fulfillment.json +25 -0
  67. data/schemas/2026-04-08/schemas/shopping/types/fulfillment_available_method.json +45 -0
  68. data/schemas/2026-04-08/schemas/shopping/types/fulfillment_destination.json +16 -0
  69. data/schemas/2026-04-08/schemas/shopping/types/fulfillment_event.json +67 -0
  70. data/schemas/2026-04-08/schemas/shopping/types/fulfillment_group.json +45 -0
  71. data/schemas/2026-04-08/schemas/shopping/types/fulfillment_method.json +67 -0
  72. data/schemas/2026-04-08/schemas/shopping/types/fulfillment_option.json +56 -0
  73. data/schemas/2026-04-08/schemas/shopping/types/info_code.json +13 -0
  74. data/schemas/2026-04-08/schemas/shopping/types/input_correlation.json +24 -0
  75. data/schemas/2026-04-08/schemas/shopping/types/item.json +33 -0
  76. data/schemas/2026-04-08/schemas/shopping/types/line_item.json +46 -0
  77. data/schemas/2026-04-08/schemas/shopping/types/link.json +25 -0
  78. data/schemas/2026-04-08/schemas/shopping/types/media.json +36 -0
  79. data/schemas/2026-04-08/schemas/shopping/types/message.json +18 -0
  80. data/schemas/2026-04-08/schemas/shopping/types/message_error.json +49 -0
  81. data/schemas/2026-04-08/schemas/shopping/types/message_info.json +37 -0
  82. data/schemas/2026-04-08/schemas/shopping/types/message_warning.json +53 -0
  83. data/schemas/2026-04-08/schemas/shopping/types/option_value.json +20 -0
  84. data/schemas/2026-04-08/schemas/shopping/types/order_confirmation.json +26 -0
  85. data/schemas/2026-04-08/schemas/shopping/types/order_line_item.json +69 -0
  86. data/schemas/2026-04-08/schemas/shopping/types/pagination.json +62 -0
  87. data/schemas/2026-04-08/schemas/shopping/types/payment_credential.json +17 -0
  88. data/schemas/2026-04-08/schemas/shopping/types/payment_instrument.json +58 -0
  89. data/schemas/2026-04-08/schemas/shopping/types/platform_fulfillment_config.json +14 -0
  90. data/schemas/2026-04-08/schemas/shopping/types/postal_address.json +44 -0
  91. data/schemas/2026-04-08/schemas/shopping/types/price.json +22 -0
  92. data/schemas/2026-04-08/schemas/shopping/types/price_filter.json +17 -0
  93. data/schemas/2026-04-08/schemas/shopping/types/price_range.json +21 -0
  94. data/schemas/2026-04-08/schemas/shopping/types/product.json +89 -0
  95. data/schemas/2026-04-08/schemas/shopping/types/product_option.json +25 -0
  96. data/schemas/2026-04-08/schemas/shopping/types/rating.json +34 -0
  97. data/schemas/2026-04-08/schemas/shopping/types/retail_location.json +28 -0
  98. data/schemas/2026-04-08/schemas/shopping/types/reverse_domain_name.json +8 -0
  99. data/schemas/2026-04-08/schemas/shopping/types/search_filters.json +20 -0
  100. data/schemas/2026-04-08/schemas/shopping/types/selected_option.json +25 -0
  101. data/schemas/2026-04-08/schemas/shopping/types/shipping_destination.json +26 -0
  102. data/schemas/2026-04-08/schemas/shopping/types/signals.json +22 -0
  103. data/schemas/2026-04-08/schemas/shopping/types/signed_amount.json +7 -0
  104. data/schemas/2026-04-08/schemas/shopping/types/total.json +75 -0
  105. data/schemas/2026-04-08/schemas/shopping/types/totals.json +98 -0
  106. data/schemas/2026-04-08/schemas/shopping/types/variant.json +193 -0
  107. data/schemas/2026-04-08/schemas/shopping/types/warning_code.json +13 -0
  108. data/schemas/2026-04-08/schemas/transports/embedded_config.json +27 -0
  109. data/schemas/2026-04-08/schemas/ucp.json +364 -0
  110. data/schemas/2026-04-08/services/shopping/embedded.openrpc.json +634 -0
  111. data/schemas/2026-04-08/services/shopping/mcp.openrpc.json +492 -0
  112. metadata +283 -0
@@ -0,0 +1,24 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/input_correlation.json",
4
+ "title": "Input Correlation",
5
+ "description": "Maps a request identifier to the variant it resolved to, with match semantics.",
6
+ "type": "object",
7
+ "required": [
8
+ "id"
9
+ ],
10
+ "properties": {
11
+ "id": {
12
+ "type": "string",
13
+ "description": "The identifier from the lookup request that resolved to this variant."
14
+ },
15
+ "match": {
16
+ "type": "string",
17
+ "description": "How the request identifier resolved to this variant. Well-known values: `exact` (input directly identifies this variant, e.g., variant ID, SKU), `featured` (server selected this variant as representative, e.g., product ID resolved to best match). Businesses MAY implement and provide additional resolution strategies.",
18
+ "examples": [
19
+ "exact",
20
+ "featured"
21
+ ]
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/item.json",
4
+ "title": "Item",
5
+ "type": "object",
6
+ "required": [
7
+ "id",
8
+ "title",
9
+ "price"
10
+ ],
11
+ "properties": {
12
+ "id": {
13
+ "type": "string",
14
+ "description": "The product identifier, often the SKU, required to resolve the product details associated with this line item. Should be recognized by both the Platform, and the Business."
15
+ },
16
+ "title": {
17
+ "type": "string",
18
+ "description": "Product title.",
19
+ "ucp_request": "omit"
20
+ },
21
+ "price": {
22
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/amount.json",
23
+ "description": "Unit price in ISO 4217 minor units.",
24
+ "ucp_request": "omit"
25
+ },
26
+ "image_url": {
27
+ "type": "string",
28
+ "description": "Product image URI.",
29
+ "format": "uri",
30
+ "ucp_request": "omit"
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/line_item.json",
4
+ "title": "Line Item",
5
+ "type": "object",
6
+ "description": "Line item object. Expected to use the currency of the parent object.",
7
+ "required": [
8
+ "id",
9
+ "item",
10
+ "quantity",
11
+ "totals"
12
+ ],
13
+ "properties": {
14
+ "id": {
15
+ "type": "string",
16
+ "ucp_request": {
17
+ "create": "omit",
18
+ "update": "optional"
19
+ }
20
+ },
21
+ "item": {
22
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/item.json"
23
+ },
24
+ "quantity": {
25
+ "type": "integer",
26
+ "description": "Quantity of the item being purchased.",
27
+ "minimum": 1
28
+ },
29
+ "totals": {
30
+ "type": "array",
31
+ "items": {
32
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/total.json"
33
+ },
34
+ "description": "Line item totals breakdown.",
35
+ "ucp_request": "omit"
36
+ },
37
+ "parent_id": {
38
+ "type": "string",
39
+ "description": "Parent line item identifier for any nested structures.",
40
+ "ucp_request": {
41
+ "create": "omit",
42
+ "update": "optional"
43
+ }
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/link.json",
4
+ "title": "Link",
5
+ "type": "object",
6
+ "required": [
7
+ "type",
8
+ "url"
9
+ ],
10
+ "properties": {
11
+ "type": {
12
+ "type": "string",
13
+ "description": "Type of link. Well-known values: `privacy_policy`, `terms_of_service`, `refund_policy`, `shipping_policy`, `faq`. Consumers SHOULD handle unknown values gracefully by displaying them using the `title` field or omitting the link."
14
+ },
15
+ "url": {
16
+ "type": "string",
17
+ "description": "The actual URL pointing to the content to be displayed.",
18
+ "format": "uri"
19
+ },
20
+ "title": {
21
+ "type": "string",
22
+ "description": "Optional display text for the link. When provided, use this instead of generating from type."
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/media.json",
4
+ "title": "Media",
5
+ "description": "Product media item (image, video, etc.).",
6
+ "type": "object",
7
+ "required": [
8
+ "type",
9
+ "url"
10
+ ],
11
+ "properties": {
12
+ "type": {
13
+ "type": "string",
14
+ "description": "Media type. Well-known values: `image`, `video`, `model_3d`."
15
+ },
16
+ "url": {
17
+ "type": "string",
18
+ "format": "uri",
19
+ "description": "URL to the media resource."
20
+ },
21
+ "alt_text": {
22
+ "type": "string",
23
+ "description": "Accessibility text describing the media."
24
+ },
25
+ "width": {
26
+ "type": "integer",
27
+ "minimum": 1,
28
+ "description": "Width in pixels (for images/video)."
29
+ },
30
+ "height": {
31
+ "type": "integer",
32
+ "minimum": 1,
33
+ "description": "Height in pixels (for images/video)."
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/message.json",
4
+ "title": "Message",
5
+ "type": "object",
6
+ "description": "Container for error, warning, or info messages.",
7
+ "oneOf": [
8
+ {
9
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/message_error.json"
10
+ },
11
+ {
12
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/message_warning.json"
13
+ },
14
+ {
15
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/message_info.json"
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,49 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/message_error.json",
4
+ "title": "Message Error",
5
+ "type": "object",
6
+ "required": [
7
+ "type",
8
+ "code",
9
+ "content",
10
+ "severity"
11
+ ],
12
+ "properties": {
13
+ "type": {
14
+ "type": "string",
15
+ "const": "error",
16
+ "description": "Message type discriminator."
17
+ },
18
+ "code": {
19
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/error_code.json"
20
+ },
21
+ "path": {
22
+ "type": "string",
23
+ "description": "RFC 9535 JSONPath to the component the message refers to (e.g., $.items[1])."
24
+ },
25
+ "content_type": {
26
+ "type": "string",
27
+ "enum": [
28
+ "plain",
29
+ "markdown"
30
+ ],
31
+ "default": "plain",
32
+ "description": "Content format, default = plain."
33
+ },
34
+ "content": {
35
+ "type": "string",
36
+ "description": "Human-readable message."
37
+ },
38
+ "severity": {
39
+ "type": "string",
40
+ "enum": [
41
+ "recoverable",
42
+ "requires_buyer_input",
43
+ "requires_buyer_review",
44
+ "unrecoverable"
45
+ ],
46
+ "description": "Reflects the resource state and recommended action. 'recoverable': platform can resolve by modifying inputs and retrying via API. 'requires_buyer_input': merchant requires information their API doesn't support collecting programmatically (checkout incomplete). 'requires_buyer_review': buyer must authorize before order placement due to policy, regulatory, or entitlement rules. 'unrecoverable': no valid resource exists to act on, retry with new resource or inputs. Errors with 'requires_*' severity contribute to 'status: requires_escalation'."
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/message_info.json",
4
+ "title": "Message Info",
5
+ "type": "object",
6
+ "required": [
7
+ "type",
8
+ "content"
9
+ ],
10
+ "properties": {
11
+ "type": {
12
+ "type": "string",
13
+ "const": "info",
14
+ "description": "Message type discriminator."
15
+ },
16
+ "path": {
17
+ "type": "string",
18
+ "description": "RFC 9535 JSONPath to the component the message refers to."
19
+ },
20
+ "code": {
21
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/info_code.json"
22
+ },
23
+ "content_type": {
24
+ "type": "string",
25
+ "enum": [
26
+ "plain",
27
+ "markdown"
28
+ ],
29
+ "default": "plain",
30
+ "description": "Content format, default = plain."
31
+ },
32
+ "content": {
33
+ "type": "string",
34
+ "description": "Human-readable message."
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,53 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/message_warning.json",
4
+ "title": "Message Warning",
5
+ "type": "object",
6
+ "required": [
7
+ "type",
8
+ "code",
9
+ "content"
10
+ ],
11
+ "properties": {
12
+ "type": {
13
+ "type": "string",
14
+ "const": "warning",
15
+ "description": "Message type discriminator."
16
+ },
17
+ "path": {
18
+ "type": "string",
19
+ "description": "JSONPath (RFC 9535) to related field (e.g., $.line_items[0])."
20
+ },
21
+ "code": {
22
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/warning_code.json"
23
+ },
24
+ "content": {
25
+ "type": "string",
26
+ "description": "Human-readable warning message that MUST be displayed."
27
+ },
28
+ "content_type": {
29
+ "type": "string",
30
+ "enum": [
31
+ "plain",
32
+ "markdown"
33
+ ],
34
+ "default": "plain",
35
+ "description": "Content format, default = plain."
36
+ },
37
+ "presentation": {
38
+ "type": "string",
39
+ "default": "notice",
40
+ "description": "Rendering contract for this warning. 'notice' (default): platform MUST display, MAY dismiss. 'disclosure': platform MUST display in proximity to the path-referenced component, MUST NOT hide or auto-dismiss. See specification for full contract."
41
+ },
42
+ "image_url": {
43
+ "type": "string",
44
+ "format": "uri",
45
+ "description": "URL to a required visual element (e.g., warning symbol, energy class label)."
46
+ },
47
+ "url": {
48
+ "type": "string",
49
+ "format": "uri",
50
+ "description": "Reference URL for more information (e.g., regulatory site, registry entry, policy page)."
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/option_value.json",
4
+ "title": "Option Value",
5
+ "description": "A selectable value for a product option.",
6
+ "type": "object",
7
+ "required": [
8
+ "label"
9
+ ],
10
+ "properties": {
11
+ "id": {
12
+ "type": "string",
13
+ "description": "Optional server-assigned identifier for this option value. When present in a selected_option, the server SHOULD use it for matching instead of label."
14
+ },
15
+ "label": {
16
+ "type": "string",
17
+ "description": "Display text for this option value (e.g., 'Small', 'Blue')."
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/order_confirmation.json",
4
+ "title": "Order Confirmation",
5
+ "description": "Order details available at the time of checkout completion.",
6
+ "type": "object",
7
+ "required": [
8
+ "id",
9
+ "permalink_url"
10
+ ],
11
+ "properties": {
12
+ "id": {
13
+ "type": "string",
14
+ "description": "Unique order identifier."
15
+ },
16
+ "label": {
17
+ "type": "string",
18
+ "description": "Human-readable label for identifying the order. MUST only be provided by the business."
19
+ },
20
+ "permalink_url": {
21
+ "type": "string",
22
+ "format": "uri",
23
+ "description": "Permalink to access the order on merchant site."
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,69 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/order_line_item.json",
4
+ "title": "Order Line Item",
5
+ "type": "object",
6
+ "required": [
7
+ "id",
8
+ "item",
9
+ "quantity",
10
+ "totals",
11
+ "status"
12
+ ],
13
+ "properties": {
14
+ "id": {
15
+ "type": "string",
16
+ "description": "Line item identifier."
17
+ },
18
+ "item": {
19
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/item.json",
20
+ "description": "Product data (id, title, price, image_url)."
21
+ },
22
+ "quantity": {
23
+ "type": "object",
24
+ "required": [
25
+ "total",
26
+ "fulfilled"
27
+ ],
28
+ "properties": {
29
+ "original": {
30
+ "type": "integer",
31
+ "minimum": 0,
32
+ "description": "Quantity from the original checkout."
33
+ },
34
+ "total": {
35
+ "type": "integer",
36
+ "minimum": 0,
37
+ "description": "Current total active quantity. May differ from original due to post-order modifications (e.g., returns or cancellations)."
38
+ },
39
+ "fulfilled": {
40
+ "type": "integer",
41
+ "minimum": 0,
42
+ "description": "Quantity fulfilled so far."
43
+ }
44
+ },
45
+ "description": "Quantity tracking for the line item."
46
+ },
47
+ "totals": {
48
+ "type": "array",
49
+ "items": {
50
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/total.json"
51
+ },
52
+ "description": "Line item totals breakdown."
53
+ },
54
+ "status": {
55
+ "type": "string",
56
+ "enum": [
57
+ "processing",
58
+ "partial",
59
+ "fulfilled",
60
+ "removed"
61
+ ],
62
+ "description": "Derived status: removed if quantity.total == 0, fulfilled if quantity.total > 0 and quantity.fulfilled == quantity.total, partial if quantity.total > 0 and quantity.fulfilled > 0, otherwise processing."
63
+ },
64
+ "parent_id": {
65
+ "type": "string",
66
+ "description": "Parent line item identifier for any nested structures."
67
+ }
68
+ }
69
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/pagination.json",
4
+ "title": "Pagination",
5
+ "description": "Cursor-based pagination for list operations.",
6
+ "type": "object",
7
+ "$defs": {
8
+ "request": {
9
+ "type": "object",
10
+ "description": "Pagination parameters for requests.",
11
+ "properties": {
12
+ "cursor": {
13
+ "type": "string",
14
+ "description": "Opaque cursor from previous response."
15
+ },
16
+ "limit": {
17
+ "type": "integer",
18
+ "minimum": 1,
19
+ "default": 10,
20
+ "description": "Requested page size. Implementations MAY clamp to a lower maximum."
21
+ }
22
+ }
23
+ },
24
+ "response": {
25
+ "type": "object",
26
+ "description": "Pagination information in responses.",
27
+ "properties": {
28
+ "cursor": {
29
+ "type": "string",
30
+ "description": "Cursor to fetch the next page of results. MUST be present when has_next_page is true."
31
+ },
32
+ "has_next_page": {
33
+ "type": "boolean",
34
+ "description": "Whether more results are available."
35
+ },
36
+ "total_count": {
37
+ "type": "integer",
38
+ "minimum": 0,
39
+ "description": "Total number of matching items, if available."
40
+ }
41
+ },
42
+ "required": [
43
+ "has_next_page"
44
+ ],
45
+ "if": {
46
+ "properties": {
47
+ "has_next_page": {
48
+ "const": true
49
+ }
50
+ },
51
+ "required": [
52
+ "has_next_page"
53
+ ]
54
+ },
55
+ "then": {
56
+ "required": [
57
+ "cursor"
58
+ ]
59
+ }
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/payment_credential.json",
4
+ "title": "Payment Credential",
5
+ "description": "The base definition for any payment credential. Handlers define specific credential types.",
6
+ "type": "object",
7
+ "required": [
8
+ "type"
9
+ ],
10
+ "properties": {
11
+ "type": {
12
+ "type": "string",
13
+ "description": "The credential type discriminator. Specific schemas will constrain this to a constant value."
14
+ }
15
+ },
16
+ "additionalProperties": true
17
+ }
@@ -0,0 +1,58 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/payment_instrument.json",
4
+ "title": "Payment Instrument",
5
+ "description": "The base definition for any payment instrument. It links the instrument to a specific payment handler.",
6
+ "type": "object",
7
+ "required": [
8
+ "id",
9
+ "handler_id",
10
+ "type"
11
+ ],
12
+ "properties": {
13
+ "id": {
14
+ "type": "string",
15
+ "description": "A unique identifier for this instrument instance, assigned by the platform."
16
+ },
17
+ "handler_id": {
18
+ "type": "string",
19
+ "description": "The unique identifier for the handler instance that produced this instrument. This corresponds to the 'id' field in the Payment Handler definition."
20
+ },
21
+ "type": {
22
+ "type": "string",
23
+ "description": "The broad category of the instrument (e.g., 'card', 'tokenized_card'). Specific schemas will constrain this to a constant value."
24
+ },
25
+ "billing_address": {
26
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/postal_address.json",
27
+ "description": "The billing address associated with this payment method."
28
+ },
29
+ "credential": {
30
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/payment_credential.json"
31
+ },
32
+ "display": {
33
+ "type": "object",
34
+ "description": "Display information for this payment instrument. Each payment instrument schema defines its specific display properties, as outlined by the payment handler."
35
+ }
36
+ },
37
+ "additionalProperties": true,
38
+ "$defs": {
39
+ "selected_payment_instrument": {
40
+ "title": "Selected Payment Instrument",
41
+ "description": "A payment instrument with selection state.",
42
+ "allOf": [
43
+ {
44
+ "$ref": "#"
45
+ },
46
+ {
47
+ "type": "object",
48
+ "properties": {
49
+ "selected": {
50
+ "type": "boolean",
51
+ "description": "Whether this instrument is selected by the user."
52
+ }
53
+ }
54
+ }
55
+ ]
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/platform_fulfillment_config.json",
4
+ "title": "Platform Fulfillment Config",
5
+ "description": "Platform's fulfillment configuration.",
6
+ "type": "object",
7
+ "properties": {
8
+ "supports_multi_group": {
9
+ "type": "boolean",
10
+ "default": false,
11
+ "description": "Enables multiple groups per method."
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/postal_address.json",
4
+ "title": "Postal Address",
5
+ "type": "object",
6
+ "properties": {
7
+ "extended_address": {
8
+ "type": "string",
9
+ "description": "An address extension such as an apartment number, C/O or alternative name."
10
+ },
11
+ "street_address": {
12
+ "type": "string",
13
+ "description": "The street address."
14
+ },
15
+ "address_locality": {
16
+ "type": "string",
17
+ "description": "The locality in which the street address is, and which is in the region. For example, Mountain View."
18
+ },
19
+ "address_region": {
20
+ "type": "string",
21
+ "description": "The region in which the locality is, and which is in the country. Required for applicable countries (i.e. state in US, province in CA). For example, California or another appropriate first-level Administrative division."
22
+ },
23
+ "address_country": {
24
+ "type": "string",
25
+ "description": "The country. Recommended to be in 2-letter ISO 3166-1 alpha-2 format, for example \"US\". For backward compatibility, a 3-letter ISO 3166-1 alpha-3 country code such as \"SGP\" or a full country name such as \"Singapore\" can also be used."
26
+ },
27
+ "postal_code": {
28
+ "type": "string",
29
+ "description": "The postal code. For example, 94043."
30
+ },
31
+ "first_name": {
32
+ "type": "string",
33
+ "description": "Optional. First name of the contact associated with the address."
34
+ },
35
+ "last_name": {
36
+ "type": "string",
37
+ "description": "Optional. Last name of the contact associated with the address."
38
+ },
39
+ "phone_number": {
40
+ "type": "string",
41
+ "description": "Optional. Phone number of the contact associated with the address."
42
+ }
43
+ }
44
+ }