Embedded Checkout Protocol
The Embedded Checkout Protocol (ECP) enables your application to embed a merchant's checkout UI, receive events as the buyer interacts with checkout, and delegate key actions like address and payment selection to your native experience.
Anchor to How it worksHow it works
ECP is a technical bridge that defines how your host application communicates with the embedded checkout:
- Load the checkout in a web view or iframe using the
continue_urlwith ECP parameters. - Receive events as the buyer progresses through checkout via JSON-RPC 2.0 messages.
- Delegate actions like payment instrument selection and address changes to your native UI.
- Complete the purchase when checkout signals completion.
ECP draws inspiration from the W3C Payment Request API, adapting its mental model for embedded checkout scenarios.
For the full protocol specification, see the ECP specification.
| Concept | W3C Payment Request | Embedded Checkout |
|---|---|---|
| Initialization | new PaymentRequest() | Load with continue_url |
| UI Ready | show() returns Promise | ec.start notification |
| Payment Change | paymentmethodchange event | ec.payment.change notification |
| Address Change | shippingaddresschange event | ec.fulfillment.address_change_request |
| Submit Payment | User accepts → PaymentResponse | ec.payment.credential_request |
| Completion | response.complete() | ec.complete notification |
Anchor to Construct the embedded URLConstruct the embedded URL
When you receive a requires_escalation status from from a UCP checkout response (via REST, MCP, or other transport), add ECP query parameters to the continue_url to enable embedded checkout.
See the UCP spec for more details.
Anchor to URL ParametersURL Parameters
The UCP version for this session. Must be 2026-01-11.
Authentication token in merchant-defined format. Optional if not required by the merchant.
Comma-delimited list of delegations the host wants to handle natively. See Delegations.
Embedded URL construction
Example URL
Anchor to Web view integrationWeb view integration
Load the embedded checkout URL in a web view. Communication between your Host and the Embedded Checkout happens through two JavaScript globals:
EmbeddedCheckoutProtocolConsumer: Created by your app. Checkout callspostMessage()to send events to your application.EmbeddedCheckoutProtocol: Created by Shopify Checkout. Your app callspostMessage()to respond to events.
All messages use JSON-RPC 2.0 format. Messages with an id field are requests that require a response. Messages without id are notifications that don't expect a response.
iOS
Android
Anchor to DelegationsDelegations
Delegations declare which operations your Host handles natively instead of in the Embedded Checkout UI. Each delegation maps to a corresponding _request message:
ec_delegate value | Corresponding message | Description |
|---|---|---|
fulfillment.address_change | ec.fulfillment.address_change_request | Host presents address selection UI |
payment.credential | ec.payment.credential_request | Host authenticates and provides payment credentials |
payment.instruments_change | ec.payment.instruments_change_request | Host presents payment method selection UI |
When you accept a delegation:
- Embedded checkout fires the
_requestmessage when that action is triggered, and waits for your response. - Your host must respond to every request, including errors if the user cancels.
- Embedded checkout doesn't show its own UI for delegated actions.
Anchor to Event referenceEvent reference
All events use JSON-RPC 2.0 format. Events are either:
- Requests (include
id): Require a response from your host. - Notifications (no
id): Informational only, no response expected.
Anchor to [object Object]ec.ready
ec.readyBroadcast when Embedded Checkout is ready. This initializes the communication channel and indicates which delegations were accepted.
Direction: Embedded Checkout → Host
Type: Request (requires response)
Payload:
delegate: Array of accepted delegation identifiers (subset of what you requested viaec_delegate)
Response:
checkout(optional): Additional display-only state, such aspayment.instrumentsupgrade(optional): AMessagePortto upgrade communication channel
ec.ready
Request
{
"jsonrpc": "2.0",
"id": "ready_1",
"method": "ec.ready",
"params": {
"delegate": [
"fulfillment.address_change",
"payment.instruments_change",
"payment.credential"
]
}
}{} Response
{
"jsonrpc": "2.0",
"id": "ready_1",
"result": {
"checkout": {
"payment": {
"instruments": [
{
"id": "pm_1234567890abc",
"handler_id": "gpay",
"type": "card",
"brand": "visa",
"last_digits": "4242"
}
],
"selected_instrument_id": "pm_1234567890abc"
}
}
}
}Anchor to [object Object]ec.start
ec.startSignals that checkout is visible and ready for buyer interaction.
Direction: Embedded Checkout → Host
Type: Notification (no response)
Payload:
checkout: The current state of the checkout
ec.start
Anchor to [object Object]ec.fulfillment.address_change_request
ec.fulfillment.address_change_requestRequests the host to present address selection UI for shipping.
Direction: Embedded Checkout → Host
Type: Request (requires response)
Payload:
checkout: Current checkout state including fulfillment details
Response:
checkout.fulfillment.methods: Updated methods withselected_destination_idanddestinations
ec.fulfillment.address_change_request
Request
{
"jsonrpc": "2.0",
"id": "address_1",
"method": "ec.fulfillment.address_change_request",
"params": {
"checkout": {
"id": "gid://shopify/Checkout/abc123?key=xyz789",
"fulfillment": {
"methods": [...]
}
}
}
}{} Response
{
"jsonrpc": "2.0",
"id": "address_1",
"result": {
"checkout": {
"fulfillment": {
"methods": [
{
"id": "method_1",
"type": "shipping",
"selected_destination_id": "gid://host/Address/789",
"destinations": [
{
"id": "gid://host/Address/789",
"street_address": "123 Main Street",
"address_locality": "Brooklyn",
"address_region": "NY",
"postal_code": "11201",
"address_country": "US",
"first_name": "Jane",
"last_name": "Smith"
}
]
}
]
}
}
}
}Anchor to [object Object]ec.payment.instruments_change_request
ec.payment.instruments_change_requestRequests the Host to present payment instrument selection UI.
Direction: Embedded Checkout → Host
Type: Request (requires response)
Payload:
checkout: Current checkout state including payment details
Response:
checkout.payment.instruments: Updated array of payment instrumentscheckout.payment.selected_instrument_id: ID of the selected instrument
ec.payment.instruments_change_request
Request
{
"jsonrpc": "2.0",
"id": "instruments_1",
"method": "ec.payment.instruments_change_request",
"params": {
"checkout": {
"id": "gid://shopify/Checkout/abc123?key=xyz789",
"payment": {...}
}
}
}{} Response
{
"jsonrpc": "2.0",
"id": "instruments_1",
"result": {
"checkout": {
"payment": {
"instruments": [
{
"id": "pm_1234567890abc",
"handler_id": "gpay",
"type": "card",
"brand": "visa",
"last_digits": "4242",
"billing_address": {
"street_address": "123 Main Street",
"address_locality": "Charleston",
"address_region": "SC",
"postal_code": "29401",
"address_country": "US"
}
}
],
"selected_instrument_id": "pm_1234567890abc"
}
}
}
}Anchor to [object Object]ec.payment.credential_request
ec.payment.credential_requestRequests a payment credential for the selected instrument during checkout submission. This typically involves user authentication (biometric/PIN).
Direction: Embedded Checkout → Host
Type: Request (requires response)
Payload:
checkout: Current checkout state including payment details
Response:
checkout.payment.instruments: Updated instrument array withcredentialfield added to the selected instrument
ec.payment.credential_request
Request
{
"jsonrpc": "2.0",
"id": "credential_1",
"method": "ec.payment.credential_request",
"params": {
"checkout": {
"id": "gid://shopify/Checkout/abc123?key=xyz789",
"payment": {
"selected_instrument_id": "pm_1234567890abc"
}
}
}
}{} Response
{
"jsonrpc": "2.0",
"id": "credential_1",
"result": {
"checkout": {
"payment": {
"instruments": [
{
"id": "pm_1234567890abc",
"handler_id": "gpay",
"type": "card",
"brand": "visa",
"last_digits": "4242",
"credential": {
"type": "payment_gateway",
"token": "examplePaymentMethodToken"
}
}
]
}
}
}
}Anchor to [object Object]ec.complete
ec.completeIndicates successful checkout completion.
Direction: Embedded Checkout → Host
Type: Notification (no response)
Payload:
checkout: Final checkout stateorder: Order confirmation details
ec.complete
Anchor to Error responsesError responses
When a user cancels a delegated action, respond with an error: