diff --git a/docs/documentation/schema-authoring.md b/docs/documentation/schema-authoring.md index aa226d97..47e32f3c 100644 --- a/docs/documentation/schema-authoring.md +++ b/docs/documentation/schema-authoring.md @@ -145,7 +145,6 @@ independently negotiated. Examples: - `schemas/shopping/payment.json` — Payment configuration (part of checkout) -- `schemas/shopping/payment_data.json` — Payment submission data ### Type Schemas diff --git a/docs/index.md b/docs/index.md index 18cbc0a8..d33b048b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -230,7 +230,8 @@ image: assets/banner.png "destinations": [ { "id": "dest_1", - "full_name": "Elisa Beckett", + "first_name": "Elisa", + "last_name": "Beckett", "street_address": "1600 Amphitheatre Pkwy", "address_locality": "Mountain View", "address_region": "CA", @@ -335,7 +336,8 @@ image: assets/banner.png "line_items": [{ "id": "li_1", "quantity": 1 }], "method_type": "shipping", "destination": { - "full_name": "Elisa Beckett", + "first_name": "Elisa", + "last_name": "Beckett", "street_address": "1600 Amphitheatre Pkwy", "address_locality": "Mountain View", "address_region": "CA", diff --git a/docs/specification/ap2-mandates.md b/docs/specification/ap2-mandates.md index 7f26b27a..13fc4c0f 100644 --- a/docs/specification/ap2-mandates.md +++ b/docs/specification/ap2-mandates.md @@ -198,7 +198,7 @@ Mandates are **SD-JWT** credentials with Key Binding (`+kb`). The platform | Mandate | UCP Placement | Purpose | | :------ | :------------ | :------ | | **checkout_mandate** | `ap2.checkout_mandate` | Proof bound to checkout terms, protects business | -| **payment_mandate** | `payment_data.token` | Proof bound to payment authorization, protects funds | +| **payment_mandate** | `payment.instruments[*].credential.token` | Proof bound to payment authorization, protects funds | The checkout mandate **MUST** contain the full checkout response including the `ap2.merchant_authorization` field. This creates a nested cryptographic binding @@ -235,7 +235,7 @@ a completion request without mandates **MUST** result in a session failure. The platform initiates the session. The business returns the `Checkout` object with `ap2.merchant_authorization` embedded in the response body. -{{ extension_schema_fields('ap2_mandate.json#/$defs/checkout_response_with_ap2', 'ap2-mandates') }} +{{ extension_schema_fields('ap2_mandate.json#/$defs/checkout', 'ap2-mandates') }} **Example Response:** ```json @@ -321,36 +321,40 @@ Binding (+kb) signature. Once the mandates are generated, the platform submits them in the completion request: -{{ extension_schema_fields('ap2_mandate.json#/$defs/complete_request_with_ap2', 'ap2-mandates') }} +{{ extension_schema_fields('ap2_mandate.json#/$defs/ap2_with_checkout_mandate', 'ap2-mandates') }} ```json { - "payment_data": { - "id": "instr_1", - "handler_id": "gpay", - "type": "card", - "description": "Visa •••• 1234", - "billing_address": { - "street_address": "123 Main St", - "address_locality": "Anytown", - "address_region": "CA", - "address_country": "US", - "postal_code": "12345" - }, - "credential": { - "type": "PAYMENT_GATEWAY", - "token": "examplePaymentMethodToken" + "payment": { + "instruments": [ + { + "id": "instr_1", + "handler_id": "gpay", + "type": "card", + "rich_text_description": "Visa •••• 1234", + "billing_address": { + "street_address": "123 Main St", + "address_locality": "Anytown", + "address_region": "CA", + "address_country": "US", + "postal_code": "12345" + }, + "credential": { + "type": "PAYMENT_GATEWAY", + "token": "examplePaymentMethodToken" + } } + ] }, "ap2": { - "checkout_mandate": "eyJhbGciOiJFUzI1NiIsInR5cCI6InZjK3NkLWp3dCJ9..." // The User-Signed SD-JWT+kb / platform provider signed SD-JWT / delegated SD-JWT-KB + "checkout_mandate": "eyJhbGciOiJFUzI1NiIsInR5cCI6InZjK3NkLWp3dCJ9..." // The User-Signed SD-JWT+kb / platform provider signed SD-JWT / delegated SD-JWT-KB } } ``` * `ap2.checkout_mandate`: The SD-JWT+kb checkout mandate containing the full checkout (with `ap2.merchant_authorization`) -* `payment_data.token`: Contains the payment mandate (composite token) +* `payment.instruments[*].credential.token`: Contains the payment mandate (composite token) ## Verification & Processing @@ -405,19 +409,19 @@ checkout. ### AP2 Checkout Response -The `ap2` object included in CREATE / UPDATE checkout responses. +The `ap2` object included in checkout responses. -{{ extension_schema_fields('ap2_mandate.json#/$defs/ap2_checkout_response', 'ap2-mandates') }} +{{ extension_schema_fields('ap2_mandate.json#/$defs/ap2_with_merchant_authorization', 'ap2-mandates') }} -### AP2 Complete Request +### Checkout Mandate -The `ap2` object included in COMPLETE checkout requests. +{{ extension_schema_fields('ap2_mandate.json#/$defs/checkout_mandate', 'ap2-mandates') }} -{{ extension_schema_fields('ap2_mandate.json#/$defs/ap2_complete_request', 'ap2-mandates') }} +### AP2 Complete Request -### Checkout Mandate +The `ap2` object included in COMPLETE checkout requests. -{{ extension_schema_fields('ap2_mandate.json#/$defs/checkout_mandate', 'ap2-mandates') }} +{{ extension_schema_fields('ap2_mandate.json#/$defs/ap2_with_checkout_mandate', 'ap2-mandates') }} ### Error Codes diff --git a/docs/specification/checkout-mcp.md b/docs/specification/checkout-mcp.md index 3f61b170..db38d479 100644 --- a/docs/specification/checkout-mcp.md +++ b/docs/specification/checkout-mcp.md @@ -111,7 +111,8 @@ Maps to the [Create Checkout](checkout.md#create-checkout) operation. #### Input Schema -* [Checkout](checkout.md#create-checkout) object. +* `checkout` ([Checkout](checkout.md#create-checkout)): **Required**. Contains + the initial checkout session data and optional extensions. * Extensions (Optional): * `dev.ucp.shopping.buyer_consent`: [Buyer Consent](buyer-consent.md) * `dev.ucp.shopping.fulfillment`: [Fulfillment](fulfillment.md) @@ -319,7 +320,7 @@ Maps to the [Get Checkout](checkout.md#get-checkout) operation. #### Input Schema -* `id` (String): The ID of the checkout session. +* `id` (String): **Required**. The ID of the checkout session. #### Output Schema @@ -331,8 +332,9 @@ Maps to the [Update Checkout](checkout.md#update-checkout) operation. #### Input Schema -* `id` (String): The ID of the checkout session to update. -* [Checkout](checkout.md#update-checkout) object. +* `id` (String): **Required**. The ID of the checkout session to update. +* `checkout` ([Checkout](checkout.md#update-checkout)): **Required**. + Contains the updated checkout session data. * Extensions (Optional): * `dev.ucp.shopping.buyer_consent`: [Buyer Consent](buyer-consent.md) * `dev.ucp.shopping.fulfillment`: [Fulfillment](fulfillment.md) @@ -538,10 +540,10 @@ Maps to the [Complete Checkout](checkout.md#complete-checkout) operation. #### Input Schema -* `id` (String): The ID of the checkout session. -* `payment` ([Payment](checkout.md#payment), Optional): Payment instrument instance submitted - by the buyer. -* `idempotency_key` (String, UUID): **Required**. Unique key for retry +* `id` (String): **Required**. The ID of the checkout session. +* `checkout` ([Checkout](checkout.md#complete-checkout)): **Required**. + Contains payment credentials and other finalization data to execute the transaction. + * `idempotency_key` (String, UUID): **Required**. Unique key for retry safety. #### Output Schema diff --git a/docs/specification/checkout-rest.md b/docs/specification/checkout-rest.md index 38cff117..c5d05278 100644 --- a/docs/specification/checkout-rest.md +++ b/docs/specification/checkout-rest.md @@ -761,25 +761,29 @@ place to set these expectations via `messages`. Content-Type: application/json { - "payment_data": { - "id": "pi_gpay_5678", - "handler_id": "com.google.pay", - "type": "card", - "brand": "mastercard", - "last_digits": "5678", - "rich_card_art": "https://cart-art-1.html", - "rich_text_description": "Google Pay •••• 5678", - "billing_address": { - "street_address": "123 Main St", - "address_locality": "Anytown", - "address_region": "CA", - "address_country": "US", - "postal_code": "12345" - }, - "credential": { - "type": "PAYMENT_GATEWAY", - "token": "examplePaymentMethodToken" - } + "payment": { + "instruments": [ + { + "id": "pi_gpay_5678", + "handler_id": "com.google.pay", + "type": "card", + "brand": "mastercard", + "last_digits": "5678", + "rich_card_art": "https://cart-art-1.html", + "rich_text_description": "Google Pay •••• 5678", + "billing_address": { + "street_address": "123 Main St", + "address_locality": "Anytown", + "address_region": "CA", + "address_country": "US", + "postal_code": "12345" + }, + "credential": { + "type": "PAYMENT_GATEWAY", + "token": "examplePaymentMethodToken" + } + } + ] }, "risk_signals": { //... risk signal related data (device fingerprint / risk token) diff --git a/docs/specification/examples/business-tokenizer-payment-handler.md b/docs/specification/examples/business-tokenizer-payment-handler.md index 5402f230..41b369b5 100644 --- a/docs/specification/examples/business-tokenizer-payment-handler.md +++ b/docs/specification/examples/business-tokenizer-payment-handler.md @@ -186,17 +186,22 @@ UCP-Agent: profile="https://platform.example/profile" Content-Type: application/json { - "payment_data": { - "handler_id": "processor_tokenizer", - "type": "card", - "brand": "visa", - "last_digits": "1111", - "expiry_month": 12, - "expiry_year": 2026, - "credential": { - "type": "token", - "token": "tok_a1b2c3d4e5f6" - } + "payment": { + "instruments": [ + { + "id": "instr_1", + "handler_id": "processor_tokenizer", + "type": "card", + "brand": "visa", + "last_digits": "1111", + "expiry_month": 12, + "expiry_year": 2026, + "credential": { + "type": "token", + "token": "tok_a1b2c3d4e5f6" + } + } + ] }, "risk_signal": { // ... the key value pair for potential risk signal data diff --git a/docs/specification/examples/encrypted-credential-handler.md b/docs/specification/examples/encrypted-credential-handler.md index a8723681..5d827130 100644 --- a/docs/specification/examples/encrypted-credential-handler.md +++ b/docs/specification/examples/encrypted-credential-handler.md @@ -208,20 +208,24 @@ UCP-Agent: profile="https://platform.example/profile" Content-Type: application/json { - "payment_data": { - "id": "instr_1", - "handler_id": "platform_encrypted", - "type": "card", - "brand": "visa", - "last_digits": "1111", - "expiry_month": 12, - "expiry_year": 2026, - "credential": { - "type": "encrypted", - "encrypted_data": "base64-encoded-encrypted-payload..." - } + "payment": { + "instruments": [ + { + "id": "instr_1", + "handler_id": "platform_encrypted", + "type": "card", + "brand": "visa", + "last_digits": "1111", + "expiry_month": 12, + "expiry_year": 2026, + "credential": { + "type": "encrypted", + "encrypted_data": "base64-encoded-encrypted-payload..." + } + } + ] }, - "risk_signal": { + "risk_signals": { // ... the key value pair for potential risk signal data } } diff --git a/docs/specification/examples/platform-tokenizer-payment-handler.md b/docs/specification/examples/platform-tokenizer-payment-handler.md index aefe9d56..98288584 100644 --- a/docs/specification/examples/platform-tokenizer-payment-handler.md +++ b/docs/specification/examples/platform-tokenizer-payment-handler.md @@ -280,18 +280,22 @@ POST /checkout-sessions/{checkout_id}/complete Content-Type: application/json { - "payment_data": { - "id": "instr_1", - "handler_id": "platform_wallet", - "type": "card", - "brand": "visa", - "last_digits": "4242", - "credential": { - "type": "token", - "token": "ptok_x9y8z7w6v5u4" - } + "payment": { + "instruments": [ + { + "id": "instr_1", + "handler_id": "platform_wallet", + "type": "card", + "brand": "visa", + "last_digits": "4242", + "credential": { + "type": "token", + "token": "ptok_x9y8z7w6v5u4" + } + } + ] }, - "risk_signal": { + "risk_signals": { // ... the key value pair for potential risk signal data } } diff --git a/docs/specification/overview.md b/docs/specification/overview.md index 803784b9..e66368aa 100644 --- a/docs/specification/overview.md +++ b/docs/specification/overview.md @@ -689,26 +689,30 @@ The Platform wraps the Google Pay response into a payment instrument. POST /checkout-sessions/{id}/complete { - "payment_data": { - "id": "pm_1234567890abc", - "handler_id": "8c9202bd-63cc-4241-8d24-d57ce69ea31c", - "type": "card", - "brand": "visa", - "last_digits": "4242", - "billing_address": { - "street_address": "123 Main Street", - "extended_address": "Suite 400", - "address_locality": "Charleston", - "address_region": "SC", - "postal_code": "29401", - "address_country": "US", - "first_name": "Jane", - "last_name": "Smith" - }, - "credential": { - "type": "PAYMENT_GATEWAY", - "token": "{\"signature\":\"...\",\"protocolVersion\":\"ECv2\"...}" - } + "payment": { + "instruments": [ + { + "id": "pm_1234567890abc", + "handler_id": "8c9202bd-63cc-4241-8d24-d57ce69ea31c", + "type": "card", + "brand": "visa", + "last_digits": "4242", + "billing_address": { + "street_address": "123 Main Street", + "extended_address": "Suite 400", + "address_locality": "Charleston", + "address_region": "SC", + "postal_code": "29401", + "address_country": "US", + "first_name": "Jane", + "last_name": "Smith" + }, + "credential": { + "type": "PAYMENT_GATEWAY", + "token": "{\"signature\":\"...\",\"protocolVersion\":\"ECv2\"...}" + } + } + ] }, "risk_signals": { // ... @@ -751,10 +755,14 @@ previous legal binding connection with them and receives `tok_visa_123` POST /checkout-sessions/{id}/complete { - "payment_data": { - "handler_id": "merchant_tokenizer", - // ... more instrument required field - "credential": { "token": "tok_visa_123" } + "payment": { + "instruments": [ + { + "handler_id": "merchant_tokenizer", + // ... more instrument required field + "credential": { "token": "tok_visa_123" } + } + ] }, "risk_signals": { // ... host could send risk_signals here @@ -812,13 +820,17 @@ non-agentic surface. POST /checkout-sessions/{id}/complete { - "payment_data": { - "handler_id": "ap2_234352", - // other required instruments fields - "credential": { - "type": "card", - "token": "eyJhbGciOiJ...", // Token would contain payment_mandate, the signed proof of funds auth - } + "payment": { + "instruments": [ + { + "handler_id": "ap2_234352", + // other required instruments fields + "credential": { + "type": "card", + "token": "eyJhbGciOiJ...", // Token would contain payment_mandate, the signed proof of funds auth + } + } + ] }, "risk_signals": { "session_id": "abc_123_xyz", diff --git a/docs/specification/payment-handler-template.md b/docs/specification/payment-handler-template.md index 848be3d8..a162ba25 100644 --- a/docs/specification/payment-handler-template.md +++ b/docs/specification/payment-handler-template.md @@ -211,17 +211,22 @@ POST /checkout-sessions/{checkout_id}/complete Content-Type: application/json { - "payment_data": { - "id": "{instrument_id}", - "handler_name": "{handler_name}", - "type": "{instrument_type}", - "credential": { - "type": "{credential_type}", - // Credential fields - } - // Additional instrument fields + "payment": { + "instruments": [ + { + "id": "{instrument_id}", + "handler_id": "{handler_id}", + "type": "{instrument_type}", + "credential": { + "type": "{credential_type}", + "token": "{credential_token}", + // Credential fields + } + // Additional instrument fields + } + ] }, - "risk_signal": { + "risk_signals": { // risk signal objects here } } diff --git a/generate_schemas.py b/generate_schemas.py index b024581f..5722ef23 100644 --- a/generate_schemas.py +++ b/generate_schemas.py @@ -38,7 +38,7 @@ SOURCE_DIR = "source" SPEC_DIR = "spec" -REQUEST_OPERATIONS = ["create", "update"] +REQUEST_OPERATIONS = ["create", "update", "complete"] UCP_ANNOTATIONS = {"ucp_request", "ucp_response", "ucp_shared_request"} # Valid annotation values @@ -66,6 +66,49 @@ def get_visibility(prop: Any, operation: str | None) -> tuple[str, bool]: else: # Response return ("omit" if prop.get("ucp_response") == "omit" else "include"), False +def has_node_schema(schema: Any) -> bool: + """ + Helper: Checks if a specific schema node adds actual validation constraints. + It considers a node 'Meaningless' if it is: + 1. An empty object {}, or {"properties": {}} + 2. A pure $ref (Alias) - because we are checking if the *file* provides value. + 3. An allOf where all children are meaningless. + """ + if not isinstance(schema, dict): + return True + constraint_keys = [ + "required", "enum", "const", "patternProperties", "minProperties", + "items", "minItems", "uniqueItems", "minimum", "pattern", + "oneOf", "anyOf", "not" + ] + if "properties" in schema: + if schema["properties"]: + return True + if any(k in schema for k in constraint_keys): + return True + if "allOf" in schema: + for item in schema["allOf"]: + if has_node_schema(item): + return True + return False + if "$ref" in schema: + return False + return False + +def has_schema(schema: Any) -> bool: + """ + Determines if a generated file should be written to disk. + Returns True only if the schema (or its definitions) defines NEW constraints. + """ + if has_node_schema(schema): + return True + # If the file is a container (no top-level constraints), it is only meaningful + # if at least one definition inside adds ACTUAL constraints (not just aliases). + if isinstance(schema, dict) and "$defs" in schema: + for def_schema in schema["$defs"].values(): + if has_node_schema(def_schema): + return True + return False def has_ucp_annotations(data: Any) -> bool: """Check if schema contains any ucp_* annotations.""" @@ -308,7 +351,7 @@ def write_json(data: dict[str, Any], path: str | Path) -> None: f.write("\n") -def process_schema( +def process_openapi_schema_schema( source_path: str, dest_dir: str, rel_path: str, @@ -348,6 +391,16 @@ def process_schema( else: # Generate per-operation request schemas for op in REQUEST_OPERATIONS: + root_visibility, _ = get_visibility(data, op) + if root_visibility == "omit": + continue + suffix = f" {op.capitalize()} Request" + transformed = transform_schema( + copy.deepcopy(data), op, source_path, annotated_schemas, suffix + ) + if not has_schema(transformed): + continue + out_name = f"{stem}.{op}_req.json" out_path = Path(dest_dir) / dir_path / out_name suffix = f" {op.capitalize()} Request" @@ -382,7 +435,12 @@ def process_schema( return generated, [] -def process_openapi( +# ============================================================================= +# OpenAPI Schema Generation +# ============================================================================= + + +def process_openapi_schema( source_path: str, dest_path: str, annotated_schemas: dict[str, bool] ) -> None: """Split components and convert refs. Preserve absolute URLs if present.""" @@ -430,7 +488,7 @@ def process_openapi( if is_shared: req_comp = f"{name}_request" schemas[req_comp] = {"$ref": f"{base_ref}_req.json"} - req_refs["create"] = req_refs["update"] = ( + req_refs["create"] = req_refs["update"] = req_refs["complete"] = ( f"#/components/schemas/{req_comp}" ) else: @@ -440,8 +498,12 @@ def process_openapi( update_comp = f"{name}_update_request" schemas[update_comp] = {"$ref": f"{base_ref}.update_req.json"} + complete_comp = f"{name}_complete_request" + schemas[complete_comp] = {"$ref": f"{base_ref}.complete_req.json"} + req_refs["create"] = f"#/components/schemas/{create_comp}" req_refs["update"] = f"#/components/schemas/{update_comp}" + req_refs["complete"] = f"#/components/schemas/{complete_comp}" # 4. Map Old -> New and Delete ref_map[f"#/components/schemas/{name}"] = { @@ -466,13 +528,20 @@ def update_node(node: Any, ctx: str): update_node(v, ctx) for root in [spec.get("paths", {}), spec.get("webhooks", {})]: - for path_item in root.values(): + for path, path_item in root.items(): for method, op in path_item.items(): if method in ["parameters", "summary", "description", "$ref"]: continue + # Determine request context based on method and path if method == "post": - req_ctx = "create" + # Check if this is a complete operation + if path.endswith("/complete") or op.get("operationId", "").startswith( + "complete_" + ): + req_ctx = "complete" + else: + req_ctx = "create" elif method in ["put", "patch"]: req_ctx = "update" else: @@ -486,6 +555,87 @@ def update_node(node: Any, ctx: str): write_json(spec, dest_path) +# ============================================================================= +# OpenRPC Schema Generation +# ============================================================================= + + +def process_openrpc_schema( + source_path: str, dest_path: str, annotated_schemas: dict[str, bool] +) -> None: + """Rewrites refs in OpenRPC methods to use operation-specific schemas.""" + spec = schema_utils.load_json(source_path) + if not spec or "methods" not in spec: + return + + def rewrite_schema_ref(schema: Any, operation: str) -> Any: + """Recursively rewrite $refs in schema based on operation type.""" + if isinstance(schema, dict): + if "$ref" in schema: + ref = schema["$ref"] + # Find if this ref points to an annotated schema + found_path = None + for path in annotated_schemas: + path_suffix = os.path.relpath(path, SOURCE_DIR).replace(os.sep, "/") + if ref.endswith(path_suffix) or path_suffix in ref: + found_path = path + break + + if found_path: + is_shared = annotated_schemas[found_path] + # Rewrite the ref to point to the operation-specific schema + if ref.startswith("http:") or ref.startswith("https:"): + base_ref, ext = ref.rsplit(".", 1) if "." in ref else (ref, "json") + else: + p_ref = Path(ref) + base_ref, ext = str(p_ref.with_suffix("")), p_ref.suffix + ext = ext[1:] if ext.startswith(".") else ext + + if operation in ["create", "update", "complete"]: + if is_shared: + new_ref = f"{base_ref}_req.{ext}" + else: + new_ref = f"{base_ref}.{operation}_req.{ext}" + else: + new_ref = f"{base_ref}_resp.{ext}" + + return {**schema, "$ref": new_ref} + + # Recursively process nested schemas + return {k: rewrite_schema_ref(v, operation) for k, v in schema.items()} + elif isinstance(schema, list): + return [rewrite_schema_ref(item, operation) for item in schema] + return schema + + # Process each method + for method in spec.get("methods", []): + method_name = method.get("name", "") + + # Determine operation type from method name + if "complete" in method_name or method_name.endswith(".complete"): + operation = "complete" + elif "create" in method_name: + operation = "create" + elif "update" in method_name: + operation = "update" + else: + operation = "read" + + # Rewrite refs in params + if "params" in method: + for param in method["params"]: + if "schema" in param: + param["schema"] = rewrite_schema_ref(param["schema"], operation) + + # Rewrite refs in result (always response) + if "result" in method and "schema" in method["result"]: + method["result"]["schema"] = rewrite_schema_ref( + method["result"]["schema"], "response" + ) + + write_json(spec, dest_path) + + # ============================================================================= # EP (Embedded Protocol) Generation # ============================================================================= @@ -695,7 +845,7 @@ def main() -> None: # 1. Special Handling: OpenAPI Spec (The Linker) if filename == "openapi.json" and str(rel_path).startswith("services/"): dest_rel = rel_path.parent / "rest.openapi.json" - process_openapi( + process_openapi_schema( str(source_path), str(Path(SPEC_DIR) / dest_rel), annotated_schemas ) print( @@ -707,9 +857,20 @@ def main() -> None: elif filename == "embedded.json": pass - # 3. Standard Handling: JSON Schemas (The Generator) - elif filename.endswith(".json") and filename != "openrpc.json": - generated, errors = process_schema( + # 3. Special Handling: OpenRPC (The Linker for MCP) + elif filename == "openrpc.json" and str(rel_path).startswith("services/"): + dest_rel = rel_path.parent / "mcp.openrpc.json" + process_openrpc_schema( + str(source_path), str(Path(SPEC_DIR) / dest_rel), annotated_schemas + ) + print( + f"{schema_utils.Colors.GREEN}✓{schema_utils.Colors.RESET} {dest_rel}" + ) + generated_count += 1 + + # 4. Standard Handling: JSON Schemas (The Generator) + elif filename.endswith(".json"): + generated, errors = process_openapi_schema_schema( str(source_path), SPEC_DIR, str(rel_path), annotated_schemas ) for g in generated: @@ -717,7 +878,7 @@ def main() -> None: generated_count += len(generated) all_errors.extend(errors) - # 4. Fallback: Copy other files (e.g. openrpc.json) + # 5. Fallback: Copy other files else: dest_name = ( "mcp.openrpc.json" if filename == "openrpc.json" else filename diff --git a/generated/schema-types.ts b/generated/schema-types.ts index b8258930..69c0b480 100644 --- a/generated/schema-types.ts +++ b/generated/schema-types.ts @@ -10,51 +10,27 @@ /** * JWS Detached Content signature (RFC 7515 Appendix F) over the checkout response body (excluding ap2 field). Format: `..`. The header MUST contain 'alg' (ES256/ES384/ES512) and 'kid' claims. The signature covers both the header and JCS-canonicalized checkout payload. * - * This interface was referenced by `AP2MandateExtension`'s JSON-Schema + * This interface was referenced by `AP2MandateExtensionCompleteRequest`'s JSON-Schema * via the `definition` "merchant_authorization". */ -export type MerchantAuthorization = string; +export type MerchantAuthorizationCompleteRequest = string; /** * SD-JWT+kb credential in `ap2.checkout_mandate`. Proving user authorization for the checkout. Contains the full checkout including `ap2.merchant_authorization`. * - * This interface was referenced by `AP2MandateExtension`'s JSON-Schema + * This interface was referenced by `AP2MandateExtensionCompleteRequest`'s JSON-Schema * via the `definition` "checkout_mandate". */ -export type CheckoutMandate = string; +export type CheckoutMandateCompleteRequest = string; /** - * Error codes specific to AP2 mandate verification. - * - * This interface was referenced by `AP2MandateExtension`'s JSON-Schema - * via the `definition` "error_code". - */ -export type AP2ErrorCode = - | 'mandate_required' - | 'agent_missing_key' - | 'mandate_invalid_signature' - | 'mandate_expired' - | 'mandate_scope_mismatch' - | 'merchant_authorization_invalid' - | 'merchant_authorization_missing'; -/** - * Checkout extended with AP2 embedded signature support. + * Checkout extended with AP2 mandate support. * - * This interface was referenced by `AP2MandateExtension`'s JSON-Schema - * via the `definition` "checkout_response_with_ap2". - */ -export type CheckoutWithAP2Mandate = CheckoutResponse & { - ap2?: AP2CheckoutResponseObject; - [k: string]: unknown; -}; -/** - * Capability reference in responses. Only name/version required to confirm active capabilities. + * This interface was referenced by `AP2MandateExtensionCompleteRequest`'s JSON-Schema + * via the `definition` "checkout". */ -export type CapabilityResponse = Base & { +export type CheckoutWithAP2MandateCompleteRequest = CheckoutCompleteRequest & { + ap2?: Ap2WithMerchantAuthorization & Ap2WithCheckoutMandate; [k: string]: unknown; }; -/** - * Container for error, warning, or info messages. - */ -export type Message = MessageError | MessageWarning | MessageInfo; /** * Matches a specific instrument type based on validation logic. */ @@ -98,19 +74,160 @@ export type CardPaymentInstrument = PaymentInstrumentBase & { */ export type PaymentCredential = TokenCredentialResponse | CardCredential; /** - * Order details available at the time of checkout completion. + * Error codes specific to AP2 mandate verification. + * + * This interface was referenced by `AP2MandateExtensionCompleteRequest`'s JSON-Schema + * via the `definition` "error_code". */ -export type OrderConfirmation = { - /** - * Unique order identifier. - */ - id: string; - /** - * Permalink to access the order on merchant site. - */ - permalink_url: string; +export type AP2ErrorCodeCompleteRequest = + | 'mandate_required' + | 'agent_missing_key' + | 'mandate_invalid_signature' + | 'mandate_expired' + | 'mandate_scope_mismatch' + | 'merchant_authorization_invalid' + | 'merchant_authorization_missing'; +/** + * JWS Detached Content signature (RFC 7515 Appendix F) over the checkout response body (excluding ap2 field). Format: `..`. The header MUST contain 'alg' (ES256/ES384/ES512) and 'kid' claims. The signature covers both the header and JCS-canonicalized checkout payload. + * + * This interface was referenced by `AP2MandateExtensionCreateRequest`'s JSON-Schema + * via the `definition` "merchant_authorization". + */ +export type MerchantAuthorizationCreateRequest = string; +/** + * SD-JWT+kb credential in `ap2.checkout_mandate`. Proving user authorization for the checkout. Contains the full checkout including `ap2.merchant_authorization`. + * + * This interface was referenced by `AP2MandateExtensionCreateRequest`'s JSON-Schema + * via the `definition` "checkout_mandate". + */ +export type CheckoutMandateCreateRequest = string; +/** + * Checkout extended with AP2 mandate support. + * + * This interface was referenced by `AP2MandateExtensionCreateRequest`'s JSON-Schema + * via the `definition` "checkout". + */ +export type CheckoutWithAP2MandateCreateRequest = CheckoutCreateRequest & { [k: string]: unknown; -} & string; +}; +/** + * Error codes specific to AP2 mandate verification. + * + * This interface was referenced by `AP2MandateExtensionCreateRequest`'s JSON-Schema + * via the `definition` "error_code". + */ +export type AP2ErrorCodeCreateRequest = + | 'mandate_required' + | 'agent_missing_key' + | 'mandate_invalid_signature' + | 'mandate_expired' + | 'mandate_scope_mismatch' + | 'merchant_authorization_invalid' + | 'merchant_authorization_missing'; +/** + * JWS Detached Content signature (RFC 7515 Appendix F) over the checkout response body (excluding ap2 field). Format: `..`. The header MUST contain 'alg' (ES256/ES384/ES512) and 'kid' claims. The signature covers both the header and JCS-canonicalized checkout payload. + * + * This interface was referenced by `AP2MandateExtensionUpdateRequest`'s JSON-Schema + * via the `definition` "merchant_authorization". + */ +export type MerchantAuthorizationUpdateRequest = string; +/** + * SD-JWT+kb credential in `ap2.checkout_mandate`. Proving user authorization for the checkout. Contains the full checkout including `ap2.merchant_authorization`. + * + * This interface was referenced by `AP2MandateExtensionUpdateRequest`'s JSON-Schema + * via the `definition` "checkout_mandate". + */ +export type CheckoutMandateUpdateRequest = string; +/** + * Checkout extended with AP2 mandate support. + * + * This interface was referenced by `AP2MandateExtensionUpdateRequest`'s JSON-Schema + * via the `definition` "checkout". + */ +export type CheckoutWithAP2MandateUpdateRequest = CheckoutUpdateRequest & { + [k: string]: unknown; +}; +/** + * Error codes specific to AP2 mandate verification. + * + * This interface was referenced by `AP2MandateExtensionUpdateRequest`'s JSON-Schema + * via the `definition` "error_code". + */ +export type AP2ErrorCodeUpdateRequest = + | 'mandate_required' + | 'agent_missing_key' + | 'mandate_invalid_signature' + | 'mandate_expired' + | 'mandate_scope_mismatch' + | 'merchant_authorization_invalid' + | 'merchant_authorization_missing'; +/** + * JWS Detached Content signature (RFC 7515 Appendix F) over the checkout response body (excluding ap2 field). Format: `..`. The header MUST contain 'alg' (ES256/ES384/ES512) and 'kid' claims. The signature covers both the header and JCS-canonicalized checkout payload. + * + * This interface was referenced by `AP2MandateExtensionResponse`'s JSON-Schema + * via the `definition` "merchant_authorization". + */ +export type MerchantAuthorizationResponse = string; +/** + * SD-JWT+kb credential in `ap2.checkout_mandate`. Proving user authorization for the checkout. Contains the full checkout including `ap2.merchant_authorization`. + * + * This interface was referenced by `AP2MandateExtensionResponse`'s JSON-Schema + * via the `definition` "checkout_mandate". + */ +export type CheckoutMandateResponse = string; +/** + * Checkout extended with AP2 mandate support. + * + * This interface was referenced by `AP2MandateExtensionResponse`'s JSON-Schema + * via the `definition` "checkout". + */ +export type CheckoutWithAP2MandateResponse = CheckoutResponse & { + ap2?: Ap2WithMerchantAuthorization1 & Ap2WithCheckoutMandate1; + [k: string]: unknown; +}; +/** + * Capability reference in responses. Only name/version required to confirm active capabilities. + */ +export type CapabilityResponse = Base & { + [k: string]: unknown; +}; +/** + * Container for error, warning, or info messages. + */ +export type Message = MessageError | MessageWarning | MessageInfo; +/** + * Error codes specific to AP2 mandate verification. + * + * This interface was referenced by `AP2MandateExtensionResponse`'s JSON-Schema + * via the `definition` "error_code". + */ +export type AP2ErrorCodeResponse = + | 'mandate_required' + | 'agent_missing_key' + | 'mandate_invalid_signature' + | 'mandate_expired' + | 'mandate_scope_mismatch' + | 'merchant_authorization_invalid' + | 'merchant_authorization_missing'; +/** + * Buyer object extended with consent tracking. + * + * This interface was referenced by `BuyerConsentExtensionCompleteRequest`'s JSON-Schema + * via the `definition` "buyer". + */ +export type BuyerWithConsentCompleteRequest = Buyer & { + consent?: Consent; + [k: string]: unknown; +}; +/** + * Checkout extended with consent tracking via buyer object. + * + * This interface was referenced by `BuyerConsentExtensionCompleteRequest`'s JSON-Schema + * via the `definition` "checkout". + */ +export type CheckoutWithBuyerConsentCompleteRequest = CheckoutCompleteRequest & { + [k: string]: unknown; +}; /** * Buyer object extended with consent tracking. * @@ -118,7 +235,7 @@ export type OrderConfirmation = { * via the `definition` "buyer". */ export type BuyerWithConsentCreateRequest = Buyer & { - consent?: Consent; + consent?: Consent1; [k: string]: unknown; }; /** @@ -138,7 +255,7 @@ export type CheckoutWithBuyerConsentCreateRequest = CheckoutCreateRequest & { * via the `definition` "buyer". */ export type BuyerWithConsentUpdateRequest = Buyer & { - consent?: Consent1; + consent?: Consent2; [k: string]: unknown; }; /** @@ -158,7 +275,7 @@ export type CheckoutWithBuyerConsentUpdateRequest = CheckoutUpdateRequest & { * via the `definition` "buyer". */ export type BuyerWithConsentResponse = Buyer & { - consent?: Consent2; + consent?: Consent3; [k: string]: unknown; }; /** @@ -171,6 +288,15 @@ export type CheckoutWithBuyerConsentResponse = CheckoutResponse & { buyer?: BuyerWithConsentResponse; [k: string]: unknown; }; +/** + * Checkout extended with discount capability. + * + * This interface was referenced by `DiscountExtensionCompleteRequest`'s JSON-Schema + * via the `definition` "checkout". + */ +export type CheckoutWithDiscountCompleteRequest = CheckoutCompleteRequest & { + [k: string]: unknown; +}; /** * Checkout extended with discount capability. * @@ -190,96 +316,402 @@ export type CheckoutWithDiscountCreateRequest = CheckoutCreateRequest & { export type CheckoutWithDiscountUpdateRequest = CheckoutUpdateRequest & { discounts?: DiscountsObject1; [k: string]: unknown; -}; +}; +/** + * Checkout extended with discount capability. + * + * This interface was referenced by `DiscountExtensionResponse`'s JSON-Schema + * via the `definition` "checkout". + */ +export type CheckoutWithDiscountResponse = CheckoutResponse & { + discounts?: DiscountsObject2; + [k: string]: unknown; +}; +/** + * A destination for fulfillment. + */ +export type FulfillmentDestinationRequest = ShippingDestinationRequest | RetailLocationRequest; +/** + * Shipping destination. + */ +export type ShippingDestinationRequest = PostalAddress & { + /** + * ID specific to this shipping destination. + */ + id?: string; + [k: string]: unknown; +}; +/** + * Checkout extended with hierarchical fulfillment. + * + * This interface was referenced by `FulfillmentExtensionCompleteRequest`'s JSON-Schema + * via the `definition` "checkout". + */ +export type CheckoutWithFulfillmentCompleteRequest = CheckoutCompleteRequest & { + [k: string]: unknown; +}; +/** + * Checkout extended with hierarchical fulfillment. + * + * This interface was referenced by `FulfillmentExtensionCreateRequest`'s JSON-Schema + * via the `definition` "checkout". + */ +export type CheckoutWithFulfillmentCreateRequest = CheckoutCreateRequest & { + fulfillment?: FulfillmentRequest; + [k: string]: unknown; +}; +/** + * Checkout extended with hierarchical fulfillment. + * + * This interface was referenced by `FulfillmentExtensionUpdateRequest`'s JSON-Schema + * via the `definition` "checkout". + */ +export type CheckoutWithFulfillmentUpdateRequest = CheckoutUpdateRequest & { + fulfillment?: FulfillmentRequest; + [k: string]: unknown; +}; +/** + * A destination for fulfillment. + */ +export type FulfillmentDestinationResponse = ShippingDestinationResponse | RetailLocationResponse; +/** + * Shipping destination. + */ +export type ShippingDestinationResponse = PostalAddress & { + /** + * ID specific to this shipping destination. + */ + id: string; + [k: string]: unknown; +}; +/** + * Checkout extended with hierarchical fulfillment. + * + * This interface was referenced by `FulfillmentExtensionResponse`'s JSON-Schema + * via the `definition` "checkout". + */ +export type CheckoutWithFulfillmentResponse = CheckoutResponse & { + fulfillment?: FulfillmentResponse; + [k: string]: unknown; +}; + +/** + * Extends Checkout with cryptographic mandate support for non-repudiable authorization per the AP2 protocol. Uses embedded signature model with ap2 namespace. + */ +export declare interface AP2MandateExtensionCompleteRequest { + [k: string]: unknown; +} +/** + * AP2 extension data including merchant authorization. + * + * This interface was referenced by `AP2MandateExtensionCompleteRequest`'s JSON-Schema + * via the `definition` "ap2_with_merchant_authorization". + */ +export declare interface Ap2WithMerchantAuthorization { + [k: string]: unknown; +} +/** + * AP2 extension data including checkout mandate. + * + * This interface was referenced by `AP2MandateExtensionCompleteRequest`'s JSON-Schema + * via the `definition` "ap2_with_checkout_mandate". + */ +export declare interface Ap2WithCheckoutMandate { + checkout_mandate?: CheckoutMandateCompleteRequest; + [k: string]: unknown; +} +/** + * Base checkout schema. Extensions compose onto this using allOf. + */ +export declare interface CheckoutCompleteRequest { + payment: PaymentCompleteRequest; + [k: string]: unknown; +} +/** + * Payment configuration containing handlers. + */ +export declare interface PaymentCompleteRequest { + /** + * The id of the currently selected payment instrument from the instruments array. Set by the agent when submitting payment, and echoed back by the merchant in finalized state. + */ + selected_instrument_id?: string; + /** + * The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. + */ + instruments?: PaymentInstrument[]; + [k: string]: unknown; +} +/** + * The base definition for any payment instrument. It links the instrument to a specific Merchant configuration (handler_id) and defines common fields like billing address. + */ +export declare interface PaymentInstrumentBase { + /** + * A unique identifier for this instrument instance, assigned by the Agent. Used to reference this specific instrument in the 'payment.selected_instrument_id' field. + */ + id: string; + /** + * The unique identifier for the handler instance that produced this instrument. This corresponds to the 'id' field in the Payment Handler definition. + */ + handler_id: string; + /** + * The broad category of the instrument (e.g., 'card', 'tokenized_card'). Specific schemas will constrain this to a constant value. + */ + type: string; + billing_address?: PostalAddress; + credential?: PaymentCredential; + [k: string]: unknown; +} +export declare interface PostalAddress { + /** + * An address extension such as an apartment number, C/O or alternative name. + */ + extended_address?: string; + /** + * The street address. + */ + street_address?: string; + /** + * The locality in which the street address is, and which is in the region. For example, Mountain View. + */ + address_locality?: string; + /** + * 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. + */ + address_region?: string; + /** + * 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. + */ + address_country?: string; + /** + * The postal code. For example, 94043. + */ + postal_code?: string; + /** + * Optional. First name of the contact associated with the address. + */ + first_name?: string; + /** + * Optional. Last name of the contact associated with the address. + */ + last_name?: string; + /** + * Optional. Phone number of the contact associated with the address. + */ + phone_number?: string; + [k: string]: unknown; +} +/** + * Base token credential schema. Concrete payment handlers may extend this schema with additional fields and define their own constraints. + */ +export declare interface TokenCredentialResponse { + /** + * The specific type of token produced by the handler (e.g., 'stripe_token'). + */ + type: string; + [k: string]: unknown; +} +/** + * A card credential containing sensitive payment card details including raw Primary Account Numbers (PANs). This credential type MUST NOT be used for checkout, only with payment handlers that tokenize or encrypt credentials. CRITICAL: Both parties handling CardCredential (sender and receiver) MUST be PCI DSS compliant. Transmission MUST use HTTPS/TLS with strong cipher suites. + */ +export declare interface CardCredential { + /** + * The credential type identifier for card credentials. + */ + type: 'card'; + /** + * The type of card number. Network tokens are preferred with fallback to FPAN. See PCI Scope for more details. + */ + card_number_type: 'fpan' | 'network_token' | 'dpan'; + /** + * Card number. + */ + number?: string; + /** + * The month of the card's expiration date (1-12). + */ + expiry_month?: number; + /** + * The year of the card's expiration date. + */ + expiry_year?: number; + /** + * Cardholder name. + */ + name?: string; + /** + * Card CVC number. + */ + cvc?: string; + /** + * Cryptogram provided with network tokens. + */ + cryptogram?: string; + /** + * Electronic Commerce Indicator / Security Level Indicator provided with network tokens. + */ + eci_value?: string; + [k: string]: unknown; +} +/** + * Extends Checkout with cryptographic mandate support for non-repudiable authorization per the AP2 protocol. Uses embedded signature model with ap2 namespace. + */ +export declare interface AP2MandateExtensionCreateRequest { + [k: string]: unknown; +} +/** + * Base checkout schema. Extensions compose onto this using allOf. + */ +export declare interface CheckoutCreateRequest { + /** + * List of line items being checked out. + */ + line_items: LineItemCreateRequest[]; + buyer?: Buyer; + /** + * ISO 4217 currency code. + */ + currency: string; + payment?: PaymentCreateRequest; + [k: string]: unknown; +} +/** + * Line item object. Expected to use the currency of the parent object. + */ +export declare interface LineItemCreateRequest { + item: ItemCreateRequest; + /** + * Quantity of the item being purchased. + */ + quantity: number; + [k: string]: unknown; +} +export declare interface ItemCreateRequest { + /** + * Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. + */ + id: string; + [k: string]: unknown; +} +export declare interface Buyer { + /** + * First name of the buyer. + */ + first_name?: string; + /** + * Last name of the buyer. + */ + last_name?: string; + /** + * Email of the buyer. + */ + email?: string; + /** + * E.164 standard. + */ + phone_number?: string; + [k: string]: unknown; +} /** - * Checkout extended with discount capability. - * - * This interface was referenced by `DiscountExtensionResponse`'s JSON-Schema - * via the `definition` "checkout". + * Payment configuration containing handlers. */ -export type CheckoutWithDiscountResponse = CheckoutResponse & { - discounts?: DiscountsObject2; +export declare interface PaymentCreateRequest { + /** + * The id of the currently selected payment instrument from the instruments array. Set by the agent when submitting payment, and echoed back by the merchant in finalized state. + */ + selected_instrument_id?: string; + /** + * The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. + */ + instruments?: PaymentInstrument[]; [k: string]: unknown; -}; -/** - * A destination for fulfillment. - */ -export type FulfillmentDestinationRequest = ShippingDestinationRequest | RetailLocationRequest; +} /** - * Shipping destination. + * Extends Checkout with cryptographic mandate support for non-repudiable authorization per the AP2 protocol. Uses embedded signature model with ap2 namespace. */ -export type ShippingDestinationRequest = PostalAddress & { +export declare interface AP2MandateExtensionUpdateRequest { [k: string]: unknown; -}; +} /** - * Checkout extended with hierarchical fulfillment. - * - * This interface was referenced by `FulfillmentExtensionCreateRequest`'s JSON-Schema - * via the `definition` "checkout". + * Base checkout schema. Extensions compose onto this using allOf. */ -export type CheckoutWithFulfillmentCreateRequest = CheckoutCreateRequest & { - fulfillment?: FulfillmentRequest; +export declare interface CheckoutUpdateRequest { + /** + * Unique identifier of the checkout session. + */ + id: string; + /** + * List of line items being checked out. + */ + line_items: LineItemUpdateRequest[]; + buyer?: Buyer; + /** + * ISO 4217 currency code. + */ + currency: string; + payment?: PaymentUpdateRequest; [k: string]: unknown; -}; +} /** - * Checkout extended with hierarchical fulfillment. - * - * This interface was referenced by `FulfillmentExtensionUpdateRequest`'s JSON-Schema - * via the `definition` "checkout". + * Line item object. Expected to use the currency of the parent object. */ -export type CheckoutWithFulfillmentUpdateRequest = CheckoutUpdateRequest & { - fulfillment?: FulfillmentRequest; +export declare interface LineItemUpdateRequest { + id?: string; + item: ItemUpdateRequest; + /** + * Quantity of the item being purchased. + */ + quantity: number; + /** + * Parent line item identifier for any nested structures. + */ + parent_id?: string; [k: string]: unknown; -}; -/** - * A destination for fulfillment. - */ -export type FulfillmentDestinationResponse = ShippingDestinationResponse | RetailLocationResponse; -/** - * Shipping destination. - */ -export type ShippingDestinationResponse = PostalAddress & { +} +export declare interface ItemUpdateRequest { /** - * ID specific to this shipping destination. + * Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. */ id: string; [k: string]: unknown; -}; +} /** - * Checkout extended with hierarchical fulfillment. - * - * This interface was referenced by `FulfillmentExtensionResponse`'s JSON-Schema - * via the `definition` "checkout". + * Payment configuration containing handlers. */ -export type CheckoutWithFulfillmentResponse = CheckoutResponse & { - fulfillment?: FulfillmentResponse; +export declare interface PaymentUpdateRequest { + /** + * The id of the currently selected payment instrument from the instruments array. Set by the agent when submitting payment, and echoed back by the merchant in finalized state. + */ + selected_instrument_id?: string; + /** + * The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. + */ + instruments?: PaymentInstrument[]; [k: string]: unknown; -}; - +} /** * Extends Checkout with cryptographic mandate support for non-repudiable authorization per the AP2 protocol. Uses embedded signature model with ap2 namespace. */ -export declare interface AP2MandateExtension { +export declare interface AP2MandateExtensionResponse { [k: string]: unknown; } /** - * The ap2 object included in checkout responses when AP2 is negotiated. + * AP2 extension data including merchant authorization. * - * This interface was referenced by `AP2MandateExtension`'s JSON-Schema - * via the `definition` "ap2_checkout_response". + * This interface was referenced by `AP2MandateExtensionResponse`'s JSON-Schema + * via the `definition` "ap2_with_merchant_authorization". */ -export declare interface AP2CheckoutResponseObject { - merchant_authorization: MerchantAuthorization; +export declare interface Ap2WithMerchantAuthorization1 { + merchant_authorization?: MerchantAuthorizationResponse; [k: string]: unknown; } /** - * The ap2 object included in complete_checkout requests when AP2 is negotiated. + * AP2 extension data including checkout mandate. * - * This interface was referenced by `AP2MandateExtension`'s JSON-Schema - * via the `definition` "ap2_complete_request". + * This interface was referenced by `AP2MandateExtensionResponse`'s JSON-Schema + * via the `definition` "ap2_with_checkout_mandate". */ -export declare interface AP2CompleteRequestObject { - checkout_mandate: CheckoutMandate; +export declare interface Ap2WithCheckoutMandate1 { + checkout_mandate?: CheckoutMandateResponse; [k: string]: unknown; } /** @@ -431,29 +863,6 @@ export declare interface TotalResponse { amount: number; [k: string]: unknown; } -export declare interface Buyer { - /** - * First name of the buyer. - */ - first_name?: string; - /** - * Last name of the buyer. - */ - last_name?: string; - /** - * Optional, buyer's full name (if first_name or last_name fields are present they take precedence). - */ - full_name?: string; - /** - * Email of the buyer. - */ - email?: string; - /** - * E.164 standard. - */ - phone_number?: string; - [k: string]: unknown; -} export declare interface MessageError { /** * Message type discriminator. @@ -591,140 +1000,29 @@ export declare interface PaymentHandlerResponse { [k: string]: unknown; } /** - * The base definition for any payment instrument. It links the instrument to a specific Merchant configuration (handler_id) and defines common fields like billing address. + * Order details available at the time of checkout completion. */ -export declare interface PaymentInstrumentBase { +export declare interface OrderConfirmation { /** - * A unique identifier for this instrument instance, assigned by the Agent. Used to reference this specific instrument in the 'payment.selected_instrument_id' field. + * Unique order identifier. */ id: string; - /** - * The unique identifier for the handler instance that produced this instrument. This corresponds to the 'id' field in the Payment Handler definition. - */ - handler_id: string; - /** - * The broad category of the instrument (e.g., 'card', 'tokenized_card'). Specific schemas will constrain this to a constant value. - */ - type: string; - billing_address?: PostalAddress; - credential?: PaymentCredential; - [k: string]: unknown; -} -export declare interface PostalAddress { - /** - * An address extension such as an apartment number, C/O or alternative name. - */ - extended_address?: string; - /** - * The street address. - */ - street_address?: string; - /** - * The locality in which the street address is, and which is in the region. For example, Mountain View. - */ - address_locality?: string; - /** - * 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. - */ - address_region?: string; - /** - * 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. - */ - address_country?: string; - /** - * The postal code. For example, 94043. - */ - postal_code?: string; - /** - * Optional. First name of the contact associated with the address. - */ - first_name?: string; - /** - * Optional. Last name of the contact associated with the address. - */ - last_name?: string; - /** - * Optional. Full name of the contact associated with the address (if first_name or last_name fields are present they take precedence). - */ - full_name?: string; - /** - * Optional. Phone number of the contact associated with the address. - */ - phone_number?: string; - [k: string]: unknown; -} -/** - * Base token credential schema. Concrete payment handlers may extend this schema with additional fields and define their own constraints. - */ -export declare interface TokenCredentialResponse { - /** - * The specific type of token produced by the handler (e.g., 'stripe_token'). - */ - type: string; - [k: string]: unknown; -} -/** - * A card credential containing sensitive payment card details including raw Primary Account Numbers (PANs). This credential type MUST NOT be used for checkout, only with payment handlers that tokenize or encrypt credentials. CRITICAL: Both parties handling CardCredential (sender and receiver) MUST be PCI DSS compliant. Transmission MUST use HTTPS/TLS with strong cipher suites. - */ -export declare interface CardCredential { - /** - * The credential type identifier for card credentials. - */ - type: 'card'; - /** - * The type of card number. Network tokens are preferred with fallback to FPAN. See PCI Scope for more details. - */ - card_number_type: 'fpan' | 'network_token' | 'dpan'; - /** - * Card number. - */ - number?: string; - /** - * The month of the card's expiration date (1-12). - */ - expiry_month?: number; - /** - * The year of the card's expiration date. - */ - expiry_year?: number; - /** - * Cardholder name. - */ - name?: string; - /** - * Card CVC number. - */ - cvc?: string; - /** - * Cryptogram provided with network tokens. - */ - cryptogram?: string; - /** - * Electronic Commerce Indicator / Security Level Indicator provided with network tokens. - */ - eci_value?: string; - [k: string]: unknown; -} -/** - * Extension fields for complete_checkout when AP2 is negotiated. - * - * This interface was referenced by `AP2MandateExtension`'s JSON-Schema - * via the `definition` "complete_request_with_ap2". - */ -export declare interface CompleteCheckoutRequestWithAP2 { - ap2?: AP2CompleteRequestObject; + /** + * Permalink to access the order on merchant site. + */ + permalink_url: string; [k: string]: unknown; } /** * Extends Checkout with buyer consent tracking for privacy compliance via the buyer object. */ -export declare interface BuyerConsentExtensionCreateRequest { +export declare interface BuyerConsentExtensionCompleteRequest { [k: string]: unknown; } /** * User consent states for data processing * - * This interface was referenced by `BuyerConsentExtensionCreateRequest`'s JSON-Schema + * This interface was referenced by `BuyerConsentExtensionCompleteRequest`'s JSON-Schema * via the `definition` "consent". */ export declare interface Consent { @@ -747,51 +1045,34 @@ export declare interface Consent { [k: string]: unknown; } /** - * Base checkout schema. Extensions compose onto this using allOf. + * Extends Checkout with buyer consent tracking for privacy compliance via the buyer object. */ -export declare interface CheckoutCreateRequest { - /** - * List of line items being checked out. - */ - line_items: LineItemCreateRequest[]; - buyer?: Buyer; - /** - * ISO 4217 currency code. - */ - currency: string; - payment: PaymentCreateRequest; +export declare interface BuyerConsentExtensionCreateRequest { [k: string]: unknown; } /** - * Line item object. Expected to use the currency of the parent object. + * User consent states for data processing + * + * This interface was referenced by `BuyerConsentExtensionCreateRequest`'s JSON-Schema + * via the `definition` "consent". */ -export declare interface LineItemCreateRequest { - item: ItemCreateRequest; +export declare interface Consent1 { /** - * Quantity of the item being purchased. + * Consent for analytics and performance tracking. */ - quantity: number; - [k: string]: unknown; -} -export declare interface ItemCreateRequest { + analytics?: boolean; /** - * Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. + * Consent for storing user preferences. */ - id: string; - [k: string]: unknown; -} -/** - * Payment configuration containing handlers. - */ -export declare interface PaymentCreateRequest { + preferences?: boolean; /** - * The id of the currently selected payment instrument from the instruments array. Set by the agent when submitting payment, and echoed back by the merchant in finalized state. + * Consent for marketing communications. */ - selected_instrument_id?: string; + marketing?: boolean; /** - * The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. + * Consent for selling data to third parties (CCPA). */ - instruments?: PaymentInstrument[]; + sale_of_data?: boolean; [k: string]: unknown; } /** @@ -806,7 +1087,7 @@ export declare interface BuyerConsentExtensionUpdateRequest { * This interface was referenced by `BuyerConsentExtensionUpdateRequest`'s JSON-Schema * via the `definition` "consent". */ -export declare interface Consent1 { +export declare interface Consent2 { /** * Consent for analytics and performance tracking. */ @@ -826,91 +1107,94 @@ export declare interface Consent1 { [k: string]: unknown; } /** - * Base checkout schema. Extensions compose onto this using allOf. + * Extends Checkout with buyer consent tracking for privacy compliance via the buyer object. */ -export declare interface CheckoutUpdateRequest { - /** - * Unique identifier of the checkout session. - */ - id: string; - /** - * List of line items being checked out. - */ - line_items: LineItemUpdateRequest[]; - buyer?: Buyer; - /** - * ISO 4217 currency code. - */ - currency: string; - payment: PaymentUpdateRequest; +export declare interface BuyerConsentExtensionResponse { [k: string]: unknown; } /** - * Line item object. Expected to use the currency of the parent object. + * User consent states for data processing + * + * This interface was referenced by `BuyerConsentExtensionResponse`'s JSON-Schema + * via the `definition` "consent". */ -export declare interface LineItemUpdateRequest { - id?: string; - item: ItemUpdateRequest; +export declare interface Consent3 { /** - * Quantity of the item being purchased. + * Consent for analytics and performance tracking. */ - quantity: number; + analytics?: boolean; /** - * Parent line item identifier for any nested structures. + * Consent for storing user preferences. */ - parent_id?: string; - [k: string]: unknown; -} -export declare interface ItemUpdateRequest { + preferences?: boolean; /** - * Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the "id" field in the product feed. + * Consent for marketing communications. */ - id: string; + marketing?: boolean; + /** + * Consent for selling data to third parties (CCPA). + */ + sale_of_data?: boolean; [k: string]: unknown; } /** - * Payment configuration containing handlers. + * Extends Checkout with discount code support, enabling agents to apply promotional, loyalty, referral, and other discount codes. */ -export declare interface PaymentUpdateRequest { - /** - * The id of the currently selected payment instrument from the instruments array. Set by the agent when submitting payment, and echoed back by the merchant in finalized state. - */ - selected_instrument_id?: string; - /** - * The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields. - */ - instruments?: PaymentInstrument[]; +export declare interface DiscountExtensionCompleteRequest { [k: string]: unknown; } /** - * Extends Checkout with buyer consent tracking for privacy compliance via the buyer object. + * Breakdown of how a discount amount was allocated to a specific target. + * + * This interface was referenced by `DiscountExtensionCompleteRequest`'s JSON-Schema + * via the `definition` "allocation". */ -export declare interface BuyerConsentExtensionResponse { +export declare interface Allocation { + /** + * JSONPath to the allocation target (e.g., '$.line_items[0]', '$.totals.shipping'). + */ + path: string; + /** + * Amount allocated to this target in minor (cents) currency units. + */ + amount: number; [k: string]: unknown; } /** - * User consent states for data processing + * A discount that was successfully applied. * - * This interface was referenced by `BuyerConsentExtensionResponse`'s JSON-Schema - * via the `definition` "consent". + * This interface was referenced by `DiscountExtensionCompleteRequest`'s JSON-Schema + * via the `definition` "applied_discount". */ -export declare interface Consent2 { +export declare interface AppliedDiscount { /** - * Consent for analytics and performance tracking. + * The discount code. Omitted for automatic discounts. */ - analytics?: boolean; + code?: string; /** - * Consent for storing user preferences. + * Human-readable discount name (e.g., 'Summer Sale 20% Off'). */ - preferences?: boolean; + title: string; /** - * Consent for marketing communications. + * Total discount amount in minor (cents) currency units. */ - marketing?: boolean; + amount: number; /** - * Consent for selling data to third parties (CCPA). + * True if applied automatically by merchant rules (no code required). */ - sale_of_data?: boolean; + automatic?: boolean; + /** + * Allocation method. 'each' = applied independently per item. 'across' = split proportionally by value. + */ + method?: 'each' | 'across'; + /** + * Stacking order for discount calculation. Lower numbers applied first (1 = first). + */ + priority?: number; + /** + * Breakdown of where this discount was allocated. Sum of allocation amounts equals total amount. + */ + allocations?: Allocation[]; [k: string]: unknown; } /** @@ -925,7 +1209,7 @@ export declare interface DiscountExtensionCreateRequest { * This interface was referenced by `DiscountExtensionCreateRequest`'s JSON-Schema * via the `definition` "allocation". */ -export declare interface Allocation { +export declare interface Allocation1 { /** * JSONPath to the allocation target (e.g., '$.line_items[0]', '$.totals.shipping'). */ @@ -942,7 +1226,7 @@ export declare interface Allocation { * This interface was referenced by `DiscountExtensionCreateRequest`'s JSON-Schema * via the `definition` "applied_discount". */ -export declare interface AppliedDiscount { +export declare interface AppliedDiscount1 { /** * The discount code. Omitted for automatic discounts. */ @@ -970,7 +1254,7 @@ export declare interface AppliedDiscount { /** * Breakdown of where this discount was allocated. Sum of allocation amounts equals total amount. */ - allocations?: Allocation[]; + allocations?: Allocation1[]; [k: string]: unknown; } /** @@ -987,7 +1271,7 @@ export declare interface DiscountsObject { /** * Discounts successfully applied (code-based and automatic). */ - applied?: AppliedDiscount[]; + applied?: AppliedDiscount1[]; [k: string]: unknown; } /** @@ -1002,7 +1286,7 @@ export declare interface DiscountExtensionUpdateRequest { * This interface was referenced by `DiscountExtensionUpdateRequest`'s JSON-Schema * via the `definition` "allocation". */ -export declare interface Allocation1 { +export declare interface Allocation2 { /** * JSONPath to the allocation target (e.g., '$.line_items[0]', '$.totals.shipping'). */ @@ -1019,7 +1303,7 @@ export declare interface Allocation1 { * This interface was referenced by `DiscountExtensionUpdateRequest`'s JSON-Schema * via the `definition` "applied_discount". */ -export declare interface AppliedDiscount1 { +export declare interface AppliedDiscount2 { /** * The discount code. Omitted for automatic discounts. */ @@ -1047,7 +1331,7 @@ export declare interface AppliedDiscount1 { /** * Breakdown of where this discount was allocated. Sum of allocation amounts equals total amount. */ - allocations?: Allocation1[]; + allocations?: Allocation2[]; [k: string]: unknown; } /** @@ -1064,7 +1348,7 @@ export declare interface DiscountsObject1 { /** * Discounts successfully applied (code-based and automatic). */ - applied?: AppliedDiscount1[]; + applied?: AppliedDiscount2[]; [k: string]: unknown; } /** @@ -1079,7 +1363,7 @@ export declare interface DiscountExtensionResponse { * This interface was referenced by `DiscountExtensionResponse`'s JSON-Schema * via the `definition` "allocation". */ -export declare interface Allocation2 { +export declare interface Allocation3 { /** * JSONPath to the allocation target (e.g., '$.line_items[0]', '$.totals.shipping'). */ @@ -1096,7 +1380,7 @@ export declare interface Allocation2 { * This interface was referenced by `DiscountExtensionResponse`'s JSON-Schema * via the `definition` "applied_discount". */ -export declare interface AppliedDiscount2 { +export declare interface AppliedDiscount3 { /** * The discount code. Omitted for automatic discounts. */ @@ -1124,7 +1408,7 @@ export declare interface AppliedDiscount2 { /** * Breakdown of where this discount was allocated. Sum of allocation amounts equals total amount. */ - allocations?: Allocation2[]; + allocations?: Allocation3[]; [k: string]: unknown; } /** @@ -1141,18 +1425,21 @@ export declare interface DiscountsObject2 { /** * Discounts successfully applied (code-based and automatic). */ - applied?: AppliedDiscount2[]; + applied?: AppliedDiscount3[]; [k: string]: unknown; } /** * Extends Checkout with fulfillment support using methods, destinations, and groups. */ -export declare interface FulfillmentExtensionCreateRequest { +export declare interface FulfillmentExtensionCompleteRequest { [k: string]: unknown; } /** * A fulfillment option within a group (e.g., Standard Shipping $5, Express $15). * + * This interface was referenced by `FulfillmentExtensionCompleteRequest`'s JSON-Schema + * via the `definition` "fulfillment_option". + * * This interface was referenced by `FulfillmentExtensionCreateRequest`'s JSON-Schema * via the `definition` "fulfillment_option". * @@ -1165,10 +1452,14 @@ export declare interface FulfillmentOptionRequest { /** * A merchant-generated package/group of line items with fulfillment options. * - * This interface was referenced by `FulfillmentExtensionCreateRequest`'s JSON-Schema + * This interface was referenced by `FulfillmentExtensionCompleteRequest`'s JSON-Schema * via the `definition` "fulfillment_group". */ -export declare interface FulfillmentGroupCreateRequest { +export declare interface FulfillmentGroupCompleteRequest { + /** + * Group identifier for referencing merchant-generated groups in updates. + */ + id: string; /** * ID of the selected fulfillment option for this group. */ @@ -1178,10 +1469,14 @@ export declare interface FulfillmentGroupCreateRequest { /** * A fulfillment method (shipping or pickup) with destinations and groups. * - * This interface was referenced by `FulfillmentExtensionCreateRequest`'s JSON-Schema + * This interface was referenced by `FulfillmentExtensionCompleteRequest`'s JSON-Schema * via the `definition` "fulfillment_method". */ -export declare interface FulfillmentMethodCreateRequest { +export declare interface FulfillmentMethodCompleteRequest { + /** + * Unique fulfillment method identifier. + */ + id: string; /** * Fulfillment method type. */ @@ -1189,7 +1484,7 @@ export declare interface FulfillmentMethodCreateRequest { /** * Line item IDs fulfilled via this method. */ - line_item_ids?: string[]; + line_item_ids: string[]; /** * Available destinations. For shipping: addresses. For pickup: retail locations. */ @@ -1201,7 +1496,7 @@ export declare interface FulfillmentMethodCreateRequest { /** * Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. */ - groups?: FulfillmentGroupCreateRequest[]; + groups?: FulfillmentGroupCompleteRequest[]; [k: string]: unknown; } /** @@ -1218,6 +1513,9 @@ export declare interface RetailLocationRequest { /** * Inventory availability hint for a fulfillment method type. * + * This interface was referenced by `FulfillmentExtensionCompleteRequest`'s JSON-Schema + * via the `definition` "fulfillment_available_method". + * * This interface was referenced by `FulfillmentExtensionCreateRequest`'s JSON-Schema * via the `definition` "fulfillment_available_method". * @@ -1230,6 +1528,9 @@ export declare interface FulfillmentAvailableMethodRequest { /** * Container for fulfillment methods and availability. * + * This interface was referenced by `FulfillmentExtensionCompleteRequest`'s JSON-Schema + * via the `definition` "fulfillment". + * * This interface was referenced by `FulfillmentExtensionCreateRequest`'s JSON-Schema * via the `definition` "fulfillment". * @@ -1243,6 +1544,54 @@ export declare interface FulfillmentRequest { methods?: FulfillmentMethodCreateRequest[]; [k: string]: unknown; } +/** + * A fulfillment method (shipping or pickup) with destinations and groups. + * + * This interface was referenced by `FulfillmentExtensionCreateRequest`'s JSON-Schema + * via the `definition` "fulfillment_method". + */ +export declare interface FulfillmentMethodCreateRequest { + /** + * Fulfillment method type. + */ + type: 'shipping' | 'pickup'; + /** + * Line item IDs fulfilled via this method. + */ + line_item_ids?: string[]; + /** + * Available destinations. For shipping: addresses. For pickup: retail locations. + */ + destinations?: FulfillmentDestinationRequest[]; + /** + * ID of the selected destination. + */ + selected_destination_id?: string | null; + /** + * Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method. + */ + groups?: FulfillmentGroupCreateRequest[]; + [k: string]: unknown; +} +/** + * A merchant-generated package/group of line items with fulfillment options. + * + * This interface was referenced by `FulfillmentExtensionCreateRequest`'s JSON-Schema + * via the `definition` "fulfillment_group". + */ +export declare interface FulfillmentGroupCreateRequest { + /** + * ID of the selected fulfillment option for this group. + */ + selected_option_id?: string | null; + [k: string]: unknown; +} +/** + * Extends Checkout with fulfillment support using methods, destinations, and groups. + */ +export declare interface FulfillmentExtensionCreateRequest { + [k: string]: unknown; +} /** * Extends Checkout with fulfillment support using methods, destinations, and groups. */ @@ -1333,17 +1682,9 @@ export declare interface FulfillmentOptionResponse { */ latest_fulfillment_time?: string; /** - * Fulfillment cost before tax in minor currency units. - */ - subtotal?: number; - /** - * Tax amount in minor currency units. - */ - tax?: number; - /** - * Total cost (subtotal + tax) in minor currency units. + * Fulfillment option totals breakdown. */ - total: number; + totals: TotalResponse[]; [k: string]: unknown; } /** @@ -1695,11 +2036,4 @@ export declare interface PlatformOrderConfig { */ webhook_url: string; [k: string]: unknown; -} -/** - * The data that will used to submit payment to the merchant. - */ -export declare interface PaymentData { - payment_data: PaymentInstrument; - [k: string]: unknown; } \ No newline at end of file diff --git a/source/schemas/shopping/ap2_mandate.json b/source/schemas/shopping/ap2_mandate.json index 8d544f0e..0da63446 100644 --- a/source/schemas/shopping/ap2_mandate.json +++ b/source/schemas/shopping/ap2_mandate.json @@ -21,32 +21,58 @@ "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]*\\.[A-Za-z0-9_-]+(~[A-Za-z0-9_-]+)*$" }, - "ap2_checkout_response": { - "title": "AP2 Checkout Response Object", - "description": "The ap2 object included in checkout responses when AP2 is negotiated.", + "ap2_with_merchant_authorization": { "type": "object", - "required": ["merchant_authorization"], + "description": "AP2 extension data including merchant authorization.", "properties": { "merchant_authorization": { "$ref": "#/$defs/merchant_authorization", - "description": "Merchant's signature proving checkout terms are authentic." + "description": "Merchant's signature proving checkout terms are authentic.", + "ucp_request": "omit" } } }, - "ap2_complete_request": { - "title": "AP2 Complete Request Object", - "description": "The ap2 object included in complete_checkout requests when AP2 is negotiated.", + "ap2_with_checkout_mandate": { "type": "object", - "required": ["checkout_mandate"], + "description": "AP2 extension data including checkout mandate.", "properties": { "checkout_mandate": { "$ref": "#/$defs/checkout_mandate", - "description": "SD-JWT+kb proving user authorized this checkout." + "description": "SD-JWT+kb proving user authorized this checkout.", + "ucp_request": { + "create": "omit", + "update": "omit", + "complete": "required" + } } } }, + "checkout": { + "title": "Checkout with AP2 Mandate", + "description": "Checkout extended with AP2 mandate support.", + "allOf": [ + { "$ref": "checkout.json" }, + { + "type": "object", + "properties": { + "ap2": { + "allOf": [ + { "$ref": "#/$defs/ap2_with_merchant_authorization" }, + { "$ref": "#/$defs/ap2_with_checkout_mandate" } + ], + "ucp_request": { + "create": "omit", + "update": "omit", + "complete": "required" + } + } + } + } + ] + }, + "error_code": { "title": "AP2 Error Code", "description": "Error codes specific to AP2 mandate verification.", @@ -60,35 +86,6 @@ "merchant_authorization_invalid", "merchant_authorization_missing" ] - }, - - "checkout_response_with_ap2": { - "title": "Checkout with AP2 Mandate", - "description": "Checkout extended with AP2 embedded signature support.", - "allOf": [ - {"$ref": "checkout.json"}, - { - "type": "object", - "properties": { - "ap2": { - "$ref": "#/$defs/ap2_checkout_response", - "description": "AP2 extension data including merchant authorization." - } - } - } - ] - }, - - "complete_request_with_ap2": { - "title": "Complete Checkout Request with AP2", - "description": "Extension fields for complete_checkout when AP2 is negotiated.", - "type": "object", - "properties": { - "ap2": { - "$ref": "#/$defs/ap2_complete_request", - "description": "AP2 extension data including checkout mandate." - } - } } } } diff --git a/source/schemas/shopping/buyer_consent.json b/source/schemas/shopping/buyer_consent.json index 5a1dbfec..0f2411bd 100644 --- a/source/schemas/shopping/buyer_consent.json +++ b/source/schemas/shopping/buyer_consent.json @@ -5,6 +5,9 @@ "version": "2026-01-11", "title": "Buyer Consent Extension", "description": "Extends Checkout with buyer consent tracking for privacy compliance via the buyer object.", + "ucp_request": { + "complete": "omit" + }, "$defs": { "consent": { "type": "object", @@ -57,7 +60,11 @@ "buyer": { "$ref": "#/$defs/buyer", "description": "Buyer with consent tracking.", - "ucp_request": "optional" + "ucp_request": { + "create": "optional", + "update": "optional", + "complete": "omit" + } } } } diff --git a/source/schemas/shopping/checkout.json b/source/schemas/shopping/checkout.json index ac3ad0e4..782fd91d 100644 --- a/source/schemas/shopping/checkout.json +++ b/source/schemas/shopping/checkout.json @@ -27,7 +27,8 @@ "description": "Unique identifier of the checkout session.", "ucp_request": { "create": "omit", - "update": "required" + "update": "required", + "complete": "omit" } }, "line_items": { @@ -35,11 +36,21 @@ "items": { "$ref": "types/line_item.json" }, - "description": "List of line items being checked out." + "description": "List of line items being checked out.", + "ucp_request": { + "create": "required", + "update": "required", + "complete": "omit" + } }, "buyer": { "$ref": "types/buyer.json", - "description": "Representation of the buyer." + "description": "Representation of the buyer.", + "ucp_request": { + "create": "optional", + "update": "optional", + "complete": "omit" + } }, "status": { "type": "string", @@ -56,7 +67,12 @@ }, "currency": { "type": "string", - "description": "ISO 4217 currency code." + "description": "ISO 4217 currency code.", + "ucp_request": { + "create": "required", + "update": "required", + "complete": "omit" + } }, "totals": { "type": "array", @@ -95,7 +111,12 @@ "ucp_request": "omit" }, "payment": { - "$ref": "payment.json" + "$ref": "payment.json", + "ucp_request": { + "create": "optional", + "update": "optional", + "complete": "required" + } }, "order": { "$ref": "types/order_confirmation.json", diff --git a/source/schemas/shopping/discount.json b/source/schemas/shopping/discount.json index d349b39b..197100eb 100644 --- a/source/schemas/shopping/discount.json +++ b/source/schemas/shopping/discount.json @@ -5,6 +5,9 @@ "version": "2026-01-11", "title": "Discount Extension", "description": "Extends Checkout with discount code support, enabling agents to apply promotional, loyalty, referral, and other discount codes.", + "ucp_request": { + "complete": "omit" + }, "$defs": { "allocation": { "type": "object", @@ -92,7 +95,11 @@ "properties": { "discounts": { "$ref": "#/$defs/discounts_object", - "ucp_request": "optional" + "ucp_request": { + "create": "optional", + "update": "optional", + "complete": "omit" + } } } } diff --git a/source/schemas/shopping/fulfillment.json b/source/schemas/shopping/fulfillment.json index 3f4822eb..6893f235 100644 --- a/source/schemas/shopping/fulfillment.json +++ b/source/schemas/shopping/fulfillment.json @@ -5,6 +5,9 @@ "version": "2026-01-11", "title": "Fulfillment Extension", "description": "Extends Checkout with fulfillment support using methods, destinations, and groups.", + "ucp_request": { + "complete": "omit" + }, "$defs": { "fulfillment_option": { "$ref": "types/fulfillment_option.json" @@ -32,7 +35,11 @@ "fulfillment": { "$ref": "#/$defs/fulfillment", "description": "Fulfillment details.", - "ucp_request": "optional" + "ucp_request": { + "create": "optional", + "update": "optional", + "complete": "omit" + } } } } diff --git a/source/schemas/shopping/payment_data.json b/source/schemas/shopping/payment_data.json deleted file mode 100644 index a7059aef..00000000 --- a/source/schemas/shopping/payment_data.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://ucp.dev/schemas/shopping/payment_data.json", - "title": "Payment Data", - "description": "The data that will used to submit payment to the merchant.", - "type": "object", - "required": ["payment_data"], - "properties": { - "payment_data": { - "$ref": "types/payment_instrument.json" - } - } -} \ No newline at end of file diff --git a/source/schemas/shopping/types/buyer.json b/source/schemas/shopping/types/buyer.json index de4a656d..507bcf39 100644 --- a/source/schemas/shopping/types/buyer.json +++ b/source/schemas/shopping/types/buyer.json @@ -13,10 +13,6 @@ "type": "string", "description": "Last name of the buyer." }, - "full_name": { - "type": "string", - "description": "Optional, buyer's full name (if first_name or last_name fields are present they take precedence)." - }, "email": { "type": "string", "description": "Email of the buyer." diff --git a/source/schemas/shopping/types/fulfillment_group.json b/source/schemas/shopping/types/fulfillment_group.json index 175058f5..972bfaf2 100644 --- a/source/schemas/shopping/types/fulfillment_group.json +++ b/source/schemas/shopping/types/fulfillment_group.json @@ -10,7 +10,11 @@ "id": { "type": "string", "description": "Group identifier for referencing merchant-generated groups in updates.", - "ucp_request": {"create": "omit", "update": "required"} + "ucp_request": { + "create": "omit", + "update": "required", + "complete": "omit" + } }, "line_item_ids": { "type": "array", @@ -26,7 +30,10 @@ }, "selected_option_id": { "type": ["string", "null"], - "description": "ID of the selected fulfillment option for this group." + "description": "ID of the selected fulfillment option for this group.", + "ucp_request": { + "complete": "omit" + } } } } \ No newline at end of file diff --git a/source/schemas/shopping/types/fulfillment_method.json b/source/schemas/shopping/types/fulfillment_method.json index 9b79e1a8..c04c1b7c 100644 --- a/source/schemas/shopping/types/fulfillment_method.json +++ b/source/schemas/shopping/types/fulfillment_method.json @@ -10,33 +10,36 @@ "id": { "type": "string", "description": "Unique fulfillment method identifier.", - "ucp_request": {"create": "omit", "update": "required"} + "ucp_request": {"create": "omit", "update": "required", "complete": "omit"} }, "type": { "type": "string", "enum": ["shipping", "pickup"], "description": "Fulfillment method type.", - "ucp_request": {"create": "required", "update": "omit"} + "ucp_request": {"create": "required", "update": "omit", "complete": "omit"} }, "line_item_ids": { "type": "array", "description": "Line item IDs fulfilled via this method.", "items": { "type": "string" }, - "ucp_request": {"create": "optional", "update": "required"} + "ucp_request": {"create": "optional", "update": "required", "complete": "omit"} }, "destinations": { "type": "array", "description": "Available destinations. For shipping: addresses. For pickup: retail locations.", - "items": { "$ref": "fulfillment_destination.json" } + "items": { "$ref": "fulfillment_destination.json" }, + "ucp_request": {"complete": "omit"} }, "selected_destination_id": { "type": ["string", "null"], - "description": "ID of the selected destination." + "description": "ID of the selected destination.", + "ucp_request": {"complete": "omit"} }, "groups": { "type": "array", "description": "Fulfillment groups for selecting options. Agent sets selected_option_id on groups to choose shipping method.", - "items": { "$ref": "fulfillment_group.json" } + "items": { "$ref": "fulfillment_group.json" }, + "ucp_request": {"complete": "omit"} } } } \ No newline at end of file diff --git a/source/schemas/shopping/types/item.json b/source/schemas/shopping/types/item.json index a6af7751..528af50b 100644 --- a/source/schemas/shopping/types/item.json +++ b/source/schemas/shopping/types/item.json @@ -11,7 +11,10 @@ "properties": { "id": { "type": "string", - "description": "Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the \"id\" field in the product feed." + "description": "Should be recognized by both the Platform, and the Business. For Google it should match the id provided in the \"id\" field in the product feed.", + "ucp_request": { + "complete": "omit" + } }, "title": { "type": "string", diff --git a/source/schemas/shopping/types/line_item.json b/source/schemas/shopping/types/line_item.json index c89431da..c67a87a1 100644 --- a/source/schemas/shopping/types/line_item.json +++ b/source/schemas/shopping/types/line_item.json @@ -15,16 +15,23 @@ "type": "string", "ucp_request": { "create": "omit", - "update": "optional" + "update": "optional", + "complete": "omit" } }, "item": { - "$ref": "item.json" + "$ref": "item.json", + "ucp_request": { + "complete": "omit" + } }, "quantity": { "type": "integer", "description": "Quantity of the item being purchased.", - "minimum": 1 + "minimum": 1, + "ucp_request": { + "complete": "omit" + } }, "totals": { "type": "array", @@ -39,7 +46,8 @@ "description": "Parent line item identifier for any nested structures.", "ucp_request": { "create": "omit", - "update": "optional" + "update": "optional", + "complete": "omit" } } } diff --git a/source/schemas/shopping/types/postal_address.json b/source/schemas/shopping/types/postal_address.json index 3121543f..3cf69437 100644 --- a/source/schemas/shopping/types/postal_address.json +++ b/source/schemas/shopping/types/postal_address.json @@ -36,10 +36,6 @@ "type": "string", "description": "Optional. Last name of the contact associated with the address." }, - "full_name": { - "type": "string", - "description": "Optional. Full name of the contact associated with the address (if first_name or last_name fields are present they take precedence)." - }, "phone_number": { "type": "string", "description": "Optional. Phone number of the contact associated with the address." diff --git a/source/services/shopping/openapi.json b/source/services/shopping/openapi.json index 2d7bfacf..0c5ed0ff 100644 --- a/source/services/shopping/openapi.json +++ b/source/services/shopping/openapi.json @@ -246,7 +246,7 @@ "application/json": { "schema": { "allOf": [ - { "$ref": "#/components/schemas/payment_data" }, + { "$ref": "#/components/schemas/checkout" }, { "title": "Risk Signals", "description": "Optional risk signals for fraud detection.", @@ -521,9 +521,6 @@ "payment": { "$ref": "https://ucp.dev/schemas/shopping/payment.json" }, - "payment_data": { - "$ref": "https://ucp.dev/schemas/shopping/payment_data.json" - }, "ucp": { "$ref": "https://ucp.dev/schemas/ucp.json" } diff --git a/source/services/shopping/openrpc.json b/source/services/shopping/openrpc.json index 89312cc1..a063448f 100644 --- a/source/services/shopping/openrpc.json +++ b/source/services/shopping/openrpc.json @@ -79,9 +79,9 @@ "schema": {"type": "string"} }, { - "name": "payment", - "required": false, - "schema": {"$ref": "https://ucp.dev/schemas/shopping/payment.json"} + "name": "checkout", + "required": true, + "schema": {"$ref": "https://ucp.dev/schemas/shopping/checkout.json"} }, { "name": "idempotency_key", diff --git a/spec/schemas/shopping/ap2_mandate.complete_req.json b/spec/schemas/shopping/ap2_mandate.complete_req.json new file mode 100644 index 00000000..7cdd738c --- /dev/null +++ b/spec/schemas/shopping/ap2_mandate.complete_req.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/ap2_mandate.complete_req.json", + "name": "dev.ucp.shopping.ap2_mandate", + "version": "2026-01-11", + "title": "AP2 Mandate Extension Complete Request", + "description": "Extends Checkout with cryptographic mandate support for non-repudiable authorization per the AP2 protocol. Uses embedded signature model with ap2 namespace.", + "$defs": { + "merchant_authorization": { + "title": "Merchant Authorization Complete Request", + "description": "JWS Detached Content signature (RFC 7515 Appendix F) over the checkout response body (excluding ap2 field). Format: `..`. The header MUST contain 'alg' (ES256/ES384/ES512) and 'kid' claims. The signature covers both the header and JCS-canonicalized checkout payload.", + "type": "string", + "pattern": "^[A-Za-z0-9_-]+\\.\\.[A-Za-z0-9_-]+$" + }, + "checkout_mandate": { + "title": "Checkout Mandate Complete Request", + "description": "SD-JWT+kb credential in `ap2.checkout_mandate`. Proving user authorization for the checkout. Contains the full checkout including `ap2.merchant_authorization`.", + "type": "string", + "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]*\\.[A-Za-z0-9_-]+(~[A-Za-z0-9_-]+)*$" + }, + "ap2_with_merchant_authorization": { + "type": "object", + "description": "AP2 extension data including merchant authorization.", + "properties": {} + }, + "ap2_with_checkout_mandate": { + "type": "object", + "description": "AP2 extension data including checkout mandate.", + "properties": { + "checkout_mandate": { + "$ref": "#/$defs/checkout_mandate", + "description": "SD-JWT+kb proving user authorized this checkout." + } + } + }, + "checkout": { + "title": "Checkout with AP2 Mandate Complete Request", + "description": "Checkout extended with AP2 mandate support.", + "allOf": [ + { + "$ref": "checkout.complete_req.json" + }, + { + "type": "object", + "properties": { + "ap2": { + "allOf": [ + { + "$ref": "#/$defs/ap2_with_merchant_authorization" + }, + { + "$ref": "#/$defs/ap2_with_checkout_mandate" + } + ] + } + } + } + ] + }, + "error_code": { + "title": "AP2 Error Code Complete Request", + "description": "Error codes specific to AP2 mandate verification.", + "type": "string", + "enum": [ + "mandate_required", + "agent_missing_key", + "mandate_invalid_signature", + "mandate_expired", + "mandate_scope_mismatch", + "merchant_authorization_invalid", + "merchant_authorization_missing" + ] + } + } +} diff --git a/spec/schemas/shopping/ap2_mandate.create_req.json b/spec/schemas/shopping/ap2_mandate.create_req.json new file mode 100644 index 00000000..ede2b9ce --- /dev/null +++ b/spec/schemas/shopping/ap2_mandate.create_req.json @@ -0,0 +1,59 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/ap2_mandate.create_req.json", + "name": "dev.ucp.shopping.ap2_mandate", + "version": "2026-01-11", + "title": "AP2 Mandate Extension Create Request", + "description": "Extends Checkout with cryptographic mandate support for non-repudiable authorization per the AP2 protocol. Uses embedded signature model with ap2 namespace.", + "$defs": { + "merchant_authorization": { + "title": "Merchant Authorization Create Request", + "description": "JWS Detached Content signature (RFC 7515 Appendix F) over the checkout response body (excluding ap2 field). Format: `..`. The header MUST contain 'alg' (ES256/ES384/ES512) and 'kid' claims. The signature covers both the header and JCS-canonicalized checkout payload.", + "type": "string", + "pattern": "^[A-Za-z0-9_-]+\\.\\.[A-Za-z0-9_-]+$" + }, + "checkout_mandate": { + "title": "Checkout Mandate Create Request", + "description": "SD-JWT+kb credential in `ap2.checkout_mandate`. Proving user authorization for the checkout. Contains the full checkout including `ap2.merchant_authorization`.", + "type": "string", + "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]*\\.[A-Za-z0-9_-]+(~[A-Za-z0-9_-]+)*$" + }, + "ap2_with_merchant_authorization": { + "type": "object", + "description": "AP2 extension data including merchant authorization.", + "properties": {} + }, + "ap2_with_checkout_mandate": { + "type": "object", + "description": "AP2 extension data including checkout mandate.", + "properties": {} + }, + "checkout": { + "title": "Checkout with AP2 Mandate Create Request", + "description": "Checkout extended with AP2 mandate support.", + "allOf": [ + { + "$ref": "checkout.create_req.json" + }, + { + "type": "object", + "properties": {} + } + ] + }, + "error_code": { + "title": "AP2 Error Code Create Request", + "description": "Error codes specific to AP2 mandate verification.", + "type": "string", + "enum": [ + "mandate_required", + "agent_missing_key", + "mandate_invalid_signature", + "mandate_expired", + "mandate_scope_mismatch", + "merchant_authorization_invalid", + "merchant_authorization_missing" + ] + } + } +} diff --git a/spec/schemas/shopping/ap2_mandate.update_req.json b/spec/schemas/shopping/ap2_mandate.update_req.json new file mode 100644 index 00000000..d6360516 --- /dev/null +++ b/spec/schemas/shopping/ap2_mandate.update_req.json @@ -0,0 +1,59 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/ap2_mandate.update_req.json", + "name": "dev.ucp.shopping.ap2_mandate", + "version": "2026-01-11", + "title": "AP2 Mandate Extension Update Request", + "description": "Extends Checkout with cryptographic mandate support for non-repudiable authorization per the AP2 protocol. Uses embedded signature model with ap2 namespace.", + "$defs": { + "merchant_authorization": { + "title": "Merchant Authorization Update Request", + "description": "JWS Detached Content signature (RFC 7515 Appendix F) over the checkout response body (excluding ap2 field). Format: `..`. The header MUST contain 'alg' (ES256/ES384/ES512) and 'kid' claims. The signature covers both the header and JCS-canonicalized checkout payload.", + "type": "string", + "pattern": "^[A-Za-z0-9_-]+\\.\\.[A-Za-z0-9_-]+$" + }, + "checkout_mandate": { + "title": "Checkout Mandate Update Request", + "description": "SD-JWT+kb credential in `ap2.checkout_mandate`. Proving user authorization for the checkout. Contains the full checkout including `ap2.merchant_authorization`.", + "type": "string", + "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]*\\.[A-Za-z0-9_-]+(~[A-Za-z0-9_-]+)*$" + }, + "ap2_with_merchant_authorization": { + "type": "object", + "description": "AP2 extension data including merchant authorization.", + "properties": {} + }, + "ap2_with_checkout_mandate": { + "type": "object", + "description": "AP2 extension data including checkout mandate.", + "properties": {} + }, + "checkout": { + "title": "Checkout with AP2 Mandate Update Request", + "description": "Checkout extended with AP2 mandate support.", + "allOf": [ + { + "$ref": "checkout.update_req.json" + }, + { + "type": "object", + "properties": {} + } + ] + }, + "error_code": { + "title": "AP2 Error Code Update Request", + "description": "Error codes specific to AP2 mandate verification.", + "type": "string", + "enum": [ + "mandate_required", + "agent_missing_key", + "mandate_invalid_signature", + "mandate_expired", + "mandate_scope_mismatch", + "merchant_authorization_invalid", + "merchant_authorization_missing" + ] + } + } +} diff --git a/spec/schemas/shopping/ap2_mandate.json b/spec/schemas/shopping/ap2_mandate_resp.json similarity index 63% rename from spec/schemas/shopping/ap2_mandate.json rename to spec/schemas/shopping/ap2_mandate_resp.json index 41a4eb9f..aad534d2 100644 --- a/spec/schemas/shopping/ap2_mandate.json +++ b/spec/schemas/shopping/ap2_mandate_resp.json @@ -3,28 +3,24 @@ "$id": "https://ucp.dev/schemas/shopping/ap2_mandate.json", "name": "dev.ucp.shopping.ap2_mandate", "version": "2026-01-11", - "title": "AP2 Mandate Extension", + "title": "AP2 Mandate Extension Response", "description": "Extends Checkout with cryptographic mandate support for non-repudiable authorization per the AP2 protocol. Uses embedded signature model with ap2 namespace.", "$defs": { "merchant_authorization": { - "title": "Merchant Authorization", + "title": "Merchant Authorization Response", "description": "JWS Detached Content signature (RFC 7515 Appendix F) over the checkout response body (excluding ap2 field). Format: `..`. The header MUST contain 'alg' (ES256/ES384/ES512) and 'kid' claims. The signature covers both the header and JCS-canonicalized checkout payload.", "type": "string", "pattern": "^[A-Za-z0-9_-]+\\.\\.[A-Za-z0-9_-]+$" }, "checkout_mandate": { - "title": "Checkout Mandate", + "title": "Checkout Mandate Response", "description": "SD-JWT+kb credential in `ap2.checkout_mandate`. Proving user authorization for the checkout. Contains the full checkout including `ap2.merchant_authorization`.", "type": "string", "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]*\\.[A-Za-z0-9_-]+(~[A-Za-z0-9_-]+)*$" }, - "ap2_checkout_response": { - "title": "AP2 Checkout Response Object", - "description": "The ap2 object included in checkout responses when AP2 is negotiated.", + "ap2_with_merchant_authorization": { "type": "object", - "required": [ - "merchant_authorization" - ], + "description": "AP2 extension data including merchant authorization.", "properties": { "merchant_authorization": { "$ref": "#/$defs/merchant_authorization", @@ -32,13 +28,9 @@ } } }, - "ap2_complete_request": { - "title": "AP2 Complete Request Object", - "description": "The ap2 object included in complete_checkout requests when AP2 is negotiated.", + "ap2_with_checkout_mandate": { "type": "object", - "required": [ - "checkout_mandate" - ], + "description": "AP2 extension data including checkout mandate.", "properties": { "checkout_mandate": { "$ref": "#/$defs/checkout_mandate", @@ -46,23 +38,9 @@ } } }, - "error_code": { - "title": "AP2 Error Code", - "description": "Error codes specific to AP2 mandate verification.", - "type": "string", - "enum": [ - "mandate_required", - "agent_missing_key", - "mandate_invalid_signature", - "mandate_expired", - "mandate_scope_mismatch", - "merchant_authorization_invalid", - "merchant_authorization_missing" - ] - }, - "checkout_response_with_ap2": { - "title": "Checkout with AP2 Mandate", - "description": "Checkout extended with AP2 embedded signature support.", + "checkout": { + "title": "Checkout with AP2 Mandate Response", + "description": "Checkout extended with AP2 mandate support.", "allOf": [ { "$ref": "checkout_resp.json" @@ -71,23 +49,32 @@ "type": "object", "properties": { "ap2": { - "$ref": "#/$defs/ap2_checkout_response", - "description": "AP2 extension data including merchant authorization." + "allOf": [ + { + "$ref": "#/$defs/ap2_with_merchant_authorization" + }, + { + "$ref": "#/$defs/ap2_with_checkout_mandate" + } + ] } } } ] }, - "complete_request_with_ap2": { - "title": "Complete Checkout Request with AP2", - "description": "Extension fields for complete_checkout when AP2 is negotiated.", - "type": "object", - "properties": { - "ap2": { - "$ref": "#/$defs/ap2_complete_request", - "description": "AP2 extension data including checkout mandate." - } - } + "error_code": { + "title": "AP2 Error Code Response", + "description": "Error codes specific to AP2 mandate verification.", + "type": "string", + "enum": [ + "mandate_required", + "agent_missing_key", + "mandate_invalid_signature", + "mandate_expired", + "mandate_scope_mismatch", + "merchant_authorization_invalid", + "merchant_authorization_missing" + ] } } } diff --git a/spec/schemas/shopping/checkout.complete_req.json b/spec/schemas/shopping/checkout.complete_req.json new file mode 100644 index 00000000..0643ddb3 --- /dev/null +++ b/spec/schemas/shopping/checkout.complete_req.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/checkout.complete_req.json", + "name": "dev.ucp.shopping.checkout", + "version": "2026-01-11", + "title": "Checkout Complete Request", + "description": "Base checkout schema. Extensions compose onto this using allOf.", + "type": "object", + "required": [ + "payment" + ], + "additionalProperties": true, + "properties": { + "payment": { + "$ref": "payment.complete_req.json" + } + } +} diff --git a/spec/schemas/shopping/checkout.create_req.json b/spec/schemas/shopping/checkout.create_req.json index f5b8b934..770047d3 100644 --- a/spec/schemas/shopping/checkout.create_req.json +++ b/spec/schemas/shopping/checkout.create_req.json @@ -8,8 +8,7 @@ "type": "object", "required": [ "line_items", - "currency", - "payment" + "currency" ], "additionalProperties": true, "properties": { diff --git a/spec/schemas/shopping/checkout.update_req.json b/spec/schemas/shopping/checkout.update_req.json index 010b59c3..175037fa 100644 --- a/spec/schemas/shopping/checkout.update_req.json +++ b/spec/schemas/shopping/checkout.update_req.json @@ -9,8 +9,7 @@ "required": [ "id", "line_items", - "currency", - "payment" + "currency" ], "additionalProperties": true, "properties": { diff --git a/spec/schemas/shopping/payment.complete_req.json b/spec/schemas/shopping/payment.complete_req.json new file mode 100644 index 00000000..01eb8ccc --- /dev/null +++ b/spec/schemas/shopping/payment.complete_req.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/payment.complete_req.json", + "title": "Payment Complete Request", + "description": "Payment configuration containing handlers.", + "type": "object", + "properties": { + "selected_instrument_id": { + "type": "string", + "description": "The id of the currently selected payment instrument from the instruments array. Set by the agent when submitting payment, and echoed back by the merchant in finalized state." + }, + "instruments": { + "type": "array", + "items": { + "$ref": "types/payment_instrument.json" + }, + "description": "The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields." + } + } +} diff --git a/spec/schemas/shopping/payment_data.json b/spec/schemas/shopping/payment_data.json deleted file mode 100644 index 263ec657..00000000 --- a/spec/schemas/shopping/payment_data.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://ucp.dev/schemas/shopping/payment_data.json", - "title": "Payment Data", - "description": "The data that will used to submit payment to the merchant.", - "type": "object", - "required": [ - "payment_data" - ], - "properties": { - "payment_data": { - "$ref": "types/payment_instrument.json" - } - } -} diff --git a/spec/schemas/shopping/types/buyer.json b/spec/schemas/shopping/types/buyer.json index de4a656d..507bcf39 100644 --- a/spec/schemas/shopping/types/buyer.json +++ b/spec/schemas/shopping/types/buyer.json @@ -13,10 +13,6 @@ "type": "string", "description": "Last name of the buyer." }, - "full_name": { - "type": "string", - "description": "Optional, buyer's full name (if first_name or last_name fields are present they take precedence)." - }, "email": { "type": "string", "description": "Email of the buyer." diff --git a/spec/schemas/shopping/types/payment_handler.create_req.json b/spec/schemas/shopping/types/payment_handler.create_req.json deleted file mode 100644 index 06fba632..00000000 --- a/spec/schemas/shopping/types/payment_handler.create_req.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://ucp.dev/schemas/shopping/types/payment_handler.create_req.json", - "title": "Payment Handler Create Request", - "type": "object", - "properties": {} -} diff --git a/spec/schemas/shopping/types/payment_handler.update_req.json b/spec/schemas/shopping/types/payment_handler.update_req.json deleted file mode 100644 index 108a7a90..00000000 --- a/spec/schemas/shopping/types/payment_handler.update_req.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://ucp.dev/schemas/shopping/types/payment_handler.update_req.json", - "title": "Payment Handler Update Request", - "type": "object", - "properties": {} -} diff --git a/spec/schemas/shopping/types/postal_address.json b/spec/schemas/shopping/types/postal_address.json index 3121543f..3cf69437 100644 --- a/spec/schemas/shopping/types/postal_address.json +++ b/spec/schemas/shopping/types/postal_address.json @@ -36,10 +36,6 @@ "type": "string", "description": "Optional. Last name of the contact associated with the address." }, - "full_name": { - "type": "string", - "description": "Optional. Full name of the contact associated with the address (if first_name or last_name fields are present they take precedence)." - }, "phone_number": { "type": "string", "description": "Optional. Phone number of the contact associated with the address." diff --git a/spec/schemas/shopping/types/token_credential.complete_req.json b/spec/schemas/shopping/types/token_credential.complete_req.json new file mode 100644 index 00000000..0c705370 --- /dev/null +++ b/spec/schemas/shopping/types/token_credential.complete_req.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ucp.dev/schemas/shopping/types/token_credential.complete_req.json", + "title": "Token Credential Complete Request", + "description": "Base token credential schema. Concrete payment handlers may extend this schema with additional fields and define their own constraints.", + "type": "object", + "required": [ + "type", + "token" + ], + "properties": { + "type": { + "type": "string", + "description": "The specific type of token produced by the handler (e.g., 'stripe_token')." + }, + "token": { + "type": "string", + "description": "The token value." + } + }, + "additionalProperties": true +} diff --git a/spec/schemas/shopping/types/total.create_req.json b/spec/schemas/shopping/types/total.create_req.json deleted file mode 100644 index 21aa7176..00000000 --- a/spec/schemas/shopping/types/total.create_req.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://ucp.dev/schemas/shopping/types/total.create_req.json", - "title": "Total Create Request", - "type": "object", - "properties": {} -} diff --git a/spec/schemas/shopping/types/total.update_req.json b/spec/schemas/shopping/types/total.update_req.json deleted file mode 100644 index f30831a8..00000000 --- a/spec/schemas/shopping/types/total.update_req.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://ucp.dev/schemas/shopping/types/total.update_req.json", - "title": "Total Update Request", - "type": "object", - "properties": {} -} diff --git a/spec/services/shopping/mcp.openrpc.json b/spec/services/shopping/mcp.openrpc.json index 89312cc1..baad1580 100644 --- a/spec/services/shopping/mcp.openrpc.json +++ b/spec/services/shopping/mcp.openrpc.json @@ -26,12 +26,16 @@ { "name": "checkout", "required": true, - "schema": {"$ref": "https://ucp.dev/schemas/shopping/checkout.json"} + "schema": { + "$ref": "https://ucp.dev/schemas/shopping/checkout.create_req.json" + } } ], "result": { "name": "checkout", - "schema": {"$ref": "https://ucp.dev/schemas/shopping/checkout.json"} + "schema": { + "$ref": "https://ucp.dev/schemas/shopping/checkout_resp.json" + } } }, { @@ -41,12 +45,16 @@ { "name": "id", "required": true, - "schema": {"type": "string"} + "schema": { + "type": "string" + } } ], "result": { "name": "checkout", - "schema": {"$ref": "https://ucp.dev/schemas/shopping/checkout.json"} + "schema": { + "$ref": "https://ucp.dev/schemas/shopping/checkout_resp.json" + } } }, { @@ -56,17 +64,23 @@ { "name": "id", "required": true, - "schema": {"type": "string"} + "schema": { + "type": "string" + } }, { "name": "checkout", "required": true, - "schema": {"$ref": "https://ucp.dev/schemas/shopping/checkout.json"} + "schema": { + "$ref": "https://ucp.dev/schemas/shopping/checkout.update_req.json" + } } ], "result": { "name": "checkout", - "schema": {"$ref": "https://ucp.dev/schemas/shopping/checkout.json"} + "schema": { + "$ref": "https://ucp.dev/schemas/shopping/checkout_resp.json" + } } }, { @@ -76,22 +90,31 @@ { "name": "id", "required": true, - "schema": {"type": "string"} + "schema": { + "type": "string" + } }, { - "name": "payment", - "required": false, - "schema": {"$ref": "https://ucp.dev/schemas/shopping/payment.json"} + "name": "checkout", + "required": true, + "schema": { + "$ref": "https://ucp.dev/schemas/shopping/checkout.complete_req.json" + } }, { "name": "idempotency_key", "required": true, - "schema": {"type": "string", "format": "uuid"} + "schema": { + "type": "string", + "format": "uuid" + } } ], "result": { "name": "checkout", - "schema": {"$ref": "https://ucp.dev/schemas/shopping/checkout.json"} + "schema": { + "$ref": "https://ucp.dev/schemas/shopping/checkout_resp.json" + } } }, { @@ -101,17 +124,24 @@ { "name": "id", "required": true, - "schema": {"type": "string"} + "schema": { + "type": "string" + } }, { "name": "idempotency_key", "required": true, - "schema": {"type": "string", "format": "uuid"} + "schema": { + "type": "string", + "format": "uuid" + } } ], "result": { "name": "checkout", - "schema": {"$ref": "https://ucp.dev/schemas/shopping/checkout.json"} + "schema": { + "$ref": "https://ucp.dev/schemas/shopping/checkout_resp.json" + } } } ] diff --git a/spec/services/shopping/rest.openapi.json b/spec/services/shopping/rest.openapi.json index 83b92f6d..1f46681a 100644 --- a/spec/services/shopping/rest.openapi.json +++ b/spec/services/shopping/rest.openapi.json @@ -255,7 +255,7 @@ "schema": { "allOf": [ { - "$ref": "#/components/schemas/payment_data" + "$ref": "#/components/schemas/checkout_complete_request" }, { "title": "Risk Signals", @@ -540,9 +540,6 @@ "order": { "$ref": "https://ucp.dev/schemas/shopping/order.json" }, - "payment_data": { - "$ref": "https://ucp.dev/schemas/shopping/payment_data.json" - }, "ucp": { "$ref": "https://ucp.dev/schemas/ucp.json" }, @@ -555,6 +552,9 @@ "checkout_update_request": { "$ref": "https://ucp.dev/schemas/shopping/checkout.update_req.json" }, + "checkout_complete_request": { + "$ref": "https://ucp.dev/schemas/shopping/checkout.complete_req.json" + }, "payment_response": { "$ref": "https://ucp.dev/schemas/shopping/payment_resp.json" }, @@ -563,6 +563,9 @@ }, "payment_update_request": { "$ref": "https://ucp.dev/schemas/shopping/payment.update_req.json" + }, + "payment_complete_request": { + "$ref": "https://ucp.dev/schemas/shopping/payment.complete_req.json" } } }