Embedded Checkout Protocol
Overview
Embedded Checkout Protocol (ECP) enables a host to embed a business’s checkout interface, receive events as the buyer interacts, and delegate key user actions such as address and payment selection.
W3C Payment Request Alignment
ECP draws inspiration from W3C Payment Request API, adapting its mental model for embedded checkout scenarios:
| Concept | W3C Payment Request | Embedded Checkout |
|---|---|---|
| Initialization | new PaymentRequest() | Load with continue_url |
| UI Ready | show() returns Promise | ec.start notification |
| Payment Method Change | paymentmethodchange event | ec.payment.change notification |
| Submit Payment | User accepts → PaymentResponse | Delegated ec.payment.credential_request |
| Completion | response.complete() | ec.complete notification |
Discovery
ECP availability is signaled via service discovery. When a business advertises the embedded transport, all continue_url values support ECP:
{
"services": {
"dev.ucp.shopping": {
"embedded": {
"schema": "https://ucp.dev/services/shopping/embedded.openrpc.json"
}
}
}
}Loading Embedded Checkout
To initiate an ECP session, augment the continue_url with query parameters:
ec_version(string, REQUIRED): UCP version (format:YYYY-MM-DD)ec_auth(string, OPTIONAL): Authentication tokenec_delegate(string, OPTIONAL): Comma-delimited list of delegations
Example:
https://example.com/checkout/abc123?ec_version=2026-01-11&ec_delegate=payment.credential,fulfillment.address_changeDelegations
Delegations allow the host to handle specific actions natively:
ec_delegate value | Corresponding message |
|---|---|
payment.instruments_change | ec.payment.instruments_change_request |
payment.credential | ec.payment.credential_request |
fulfillment.address_change | ec.fulfillment.address_change_request |
Message Format
All ECP messages MUST use JSON-RPC 2.0 format:
{
"jsonrpc": "2.0",
"method": "ec.start",
"params": {...},
"id": "optional_request_id"
}Core Messages
ec.ready (Handshake)
Establishes connection between host and Embedded Checkout:
{
"jsonrpc": "2.0",
"id": "ready_1",
"method": "ec.ready",
"params": {
"delegate": ["payment.credential", "fulfillment.address_change"]
}
}Host response:
{
"jsonrpc": "2.0",
"id": "ready_1",
"result": {
"checkout": {
"payment": {
"instruments": [...]
}
}
}
}ec.start (Lifecycle)
Signals checkout is visible and ready for interaction:
{
"jsonrpc": "2.0",
"method": "ec.start",
"params": {
"checkout": {
"id": "checkout_123",
"status": "incomplete",
"totals": [...],
"line_items": [...]
}
}
}ec.complete (Lifecycle)
Indicates successful checkout completion:
{
"jsonrpc": "2.0",
"method": "ec.complete",
"params": {
"checkout": {
"id": "checkout_123",
"order": {
"id": "ord_99887766",
"permalink_url": "https://merchant.com/orders/ord_99887766"
}
}
}
}ec.payment.credential_request (Delegation)
Requests a payment credential from the host:
{
"jsonrpc": "2.0",
"id": "payment_credential_request_1",
"method": "ec.payment.credential_request",
"params": {
"checkout": {
"id": "checkout_123",
"payment": {
"selected_instrument_id": "payment_instrument_123"
}
}
}
}Host response:
{
"jsonrpc": "2.0",
"id": "payment_credential_request_1",
"result": {
"checkout": {
"payment": {
"instruments": [
{
"id": "payment_instrument_123",
"credential": {
"type": "token",
"token": "tok_123"
}
}
]
}
}
}
}Communication Channels
Web-Based Hosts
Use postMessage between host and embedded windows. Host MUST validate origin.
Native Hosts
Inject window.EmbeddedCheckoutProtocolConsumer global object:
{
postMessage(message: string): void
}Security
CSP Requirements
- Business: Set
frame-ancestors <host_origin>; - Host: Use appropriate
frame-srcor intermediate iframe
Iframe Sandbox
<iframe sandbox="allow-scripts allow-forms allow-same-origin"></iframe>Credentialless Iframes
<iframe credentialless src="https://business.example.com/checkout"></iframe>Error Codes
| Code | Description |
|---|---|
abort_error | User cancelled the interaction |
security_error | Origin validation failed |
not_supported_error | Payment method not supported |
invalid_state_error | Handshake out of order |
not_allowed_error | Missing user activation |
See Also
- Checkout Capability - Core checkout specification
- Checkout REST Binding - REST API binding