Shop Pay in Checkout Kit
You build with Checkout Kit, Shopify's open-source SDK for embedding checkout in any surface. Shop Pay is one import from it, @shopify/checkout-kit/shop-pay, which adds a <shop-pay> element to your page. The element opens Shop Pay with your session and tells you how the purchase goes, and you never collect or hold the buyer's actual payment details.
Today, Shop Pay opens a checkout that Shopify creates from your carts, for merchants on Shopify, and the element runs in browsers and in your app's web view. Support for any merchant that accepts Shop Pay, and for Checkout Kit's Swift, Kotlin, and React Native SDKs, is coming soon.
shop-pay.js
Anchor to How it worksHow it works
Your server creates a cart at each merchant and combines the carts into one universal session. Shop Pay opens in its own window over your page, either from Shop Pay's button, placed where your other wallet buttons go, or from your own pay button, with Shop Pay as a row in your payment list. The buyer signs in and pays, Shop Pay completes the checkout at each merchant, and your page receives the completed checkouts with their orders.
Anchor to Build your integrationBuild your integration
Universal Checkout is in early access and available by request. Tool names, inputs, and response fields might change before general availability. To request access for your API key, submit the Universal Checkout early access request form.
Universal Checkout is in early access and available by request. Tool names, inputs, and response fields might change before general availability. To request access for your API key, submit the Universal Checkout early access request form.
Anchor to RequirementsRequirements
- API credentials from Catalogs in the Dev Dashboard, with your client ID and client secret. Your server exchanges them for an access token, as Authentication describes, and sends it as a Bearer token in every request below.
Anchor to Step 1: Prepare the checkoutStep 1: Prepare the checkout
On your server, create a cart at each merchant with the create_cart tool on its Cart MCP endpoint. Then create one Universal session from the carts with the create_checkout tool at https://catalog.shopify.com/api/ucp/mcp. Pass up to 15 carts, one for each merchant, all in the same currency.
create_checkout returns a continue_url, the Universal session URL, that your page hands to Shop Pay in the next step. It gives access to the buyer's checkout, so return it to your page only, and don't log it. Prepare a new checkout whenever the cart changes.
server.js
{} The result of create_checkout
Anchor to Step 2: Open Shop PayStep 2: Open Shop Pay
Add a <shop-pay> element to your page. Importing @shopify/checkout-kit/shop-pay registers the element. When your server returns the combined checkout, set its continue_url as the element's src. Whenever the cart changes, take Shop Pay away and clear src before you ask for a new combined checkout, and offer Shop Pay again only with the new checkout. Otherwise Shop Pay can pay for a cart that your page no longer shows. If requests can overlap, then keep only the latest response.
With target="popup", Shop Pay opens in a pop-up window over your page. Without it, Shop Pay opens in a new tab. While Shop Pay is open, the element shows an overlay over your page, with a button that brings Shop Pay's window to the front and a button that closes it.
What opens Shop Pay is up to you: Shop Pay's button, or your own pay button.
Add the element where your other wallet buttons go, and set button after you set src. The element draws the Shop Pay button that buyers trust to accelerate checkouts, and a tap opens Shop Pay. Hide the button whenever you clear src.
checkout.html
shop-pay.js
Add Shop Pay as a row in your payment list, and add the element without the button attribute anywhere in your page. The element draws nothing until Shop Pay opens, but it must stay in the page, because it shows the overlay and receives Shop Pay's messages. Hide the Shop Pay row whenever you clear src.
Create the combined checkout before the buyer presses your pay button, for example when your checkout page loads. When the buyer presses your pay button with Shop Pay selected, call open() from the click handler itself. Browsers open a window only in response to the buyer's click, so a click handler that waits for your server first loses the chance to open it.

checkout.html
shop-pay.js
Anchor to Step 3: Follow the purchaseStep 3: Follow the purchase
Shop Pay opens, and the buyer signs in and reviews the purchase. When the checkouts become interactive, the element dispatches start. When a checkout changes, for example when the buyer's Shop Pay address replaces yours or the buyer picks a shipping option, the element dispatches update. Shop Pay applies each change at the merchant for you.
Each event's detail lists only the checkouts that it describes, as {context, checkout} entries. context.shopId names the merchant. The element keeps no state for you to read back, so keep the latest entry for each merchant yourself, and add your listeners before you call open().
shop-pay.js
Anchor to Step 4: Show your confirmationStep 4: Show your confirmation
When the buyer presses Pay now, which happens once for the whole cart, Shop Pay completes each checkout at its merchant. Each merchant that completes arrives in a complete event while the others can still send updates, so one complete doesn't end the session. The session ends after one merchant has completed and every other merchant has completed, failed, or left, and Shop Pay's window stays open until you call close().
In each completed checkout, status is completed, and order contains that merchant's order, with its id and label. Shop Pay doesn't show an order confirmation. Show yours, with one order for each merchant, using order.label as the order number.
Use order.id on your server to follow each order with Order MCP and order webhooks, which return the order's permalink_url for the buyer's order status page. Each merchant also sends the buyer its usual order confirmation.
shop-pay.js
Anchor to Edge casesEdge cases
The steps above are the happy path. Handle the following too.
Anchor to The buyer closes Shop PayThe buyer closes Shop Pay
If the buyer closes Shop Pay's window before paying, or closes it from the overlay, then the element dispatches close. Nothing is completed at the merchants, and the buyer can open Shop Pay again with the same session, or pay another way. A close with no earlier start, update, or error means that the buyer left Shop Pay's sign-in page before any checkout was shown.
To close Shop Pay from your page, call close(). Changing src or target also closes it.
shop-pay.js
Anchor to A merchant drops outA merchant drops out
In a session with several merchants, one merchant can fail while the others continue. An update reports that merchant with context.status set to failed, which Shop Pay can still retry, or ejected, which means that the merchant left the session. A merchant that can't continue also arrives in error, as an entry whose context.shopId names it. The other checkouts carry on, and complete reports only the merchants that completed. Tell the buyer which items weren't bought.
shop-pay.js
Anchor to Shop Pay can't continueShop Pay can't continue
If Shop Pay can't continue, then the element dispatches error with an entry that has no context.shopId, and the session ends. Each entry has an error with a code and a message. Use code to decide what to do, and treat message as diagnostic text. Offer another payment method, and create a new combined checkout if the buyer wants to try Shop Pay again.
The element also reports problems on your page this way, before it opens Shop Pay, as entries with no context at all: unsupported_browser when the browser lacks a feature that Shop Pay needs, and sdk_error when src is empty or isn't an HTTPS URL.
shop-pay.js
{} The detail of an error event
Anchor to The browser blocks Shop Pay's windowThe browser blocks Shop Pay's window
Browsers open a window only in response to the buyer's tap. Shop Pay's button opens Shop Pay from the tap itself. With your own button, call open() directly from the buyer's click, and never from a blocked listener, a timer, or after an await. If the browser blocks the window anyway, then the element dispatches blocked, and its overlay offers the buyer a button that opens Shop Pay again. If the buyer dismisses the overlay instead, then the element dispatches close.
shop-pay.js
Anchor to Your page runs in your app's web viewYour page runs in your app's web view
Checkout Kit for the web works the same in a native app's web view, and needs three things from the app:
- JavaScript and DOM storage, which Android web views don't enable by default.
- Your app's shared, persistent cookie store, so that the buyer signs in to Shop Pay on
shop.apponce per install. - A window for Shop Pay. The
<shop-pay>element opens Shop Pay withwindow.open. Create that window as a web view of its own, on the same cookie store, present it in your own UI with a close button, and dismiss it when the page closes it.
CheckoutViewController.swift
CheckoutWebView.kt
Anchor to ReferenceReference
<shop-pay> is the whole interface: an element with attributes, two methods, and six events. Every event is dispatched on the element and doesn't bubble, so add your listeners to the element itself, before you call open(). Each attribute is also a property.
Anchor to AttributesAttributes
src
• string Required (critical)
The Universal session URL: the continue_url that create_checkout returned to your server. Changing it closes Shop Pay if it's open.
button
• boolean
Draws Shop Pay's button in the element. A tap calls open(). Without it, the element draws nothing, and you call open() from your own button.
target
• string
Where Shop Pay opens: popup for a pop-up window over your page, auto (the default) or _blank for a new tab, or the name of a window. Changing it closes Shop Pay if it's open.
Anchor to MethodsMethods
open()
• method
Opens Shop Pay with the session in src. Shop Pay's button calls it on tap. With your own pay button, call it from the click handler itself.
close()
• method
Closes Shop Pay and the overlay. The element dispatches close.
Anchor to EventsEvents
start
• event
The checkouts became interactive. detail is an array of {context, checkout} entries.
update
• event
Checkouts changed, or a merchant's context.status changed. detail is an array of {context, checkout} entries for the merchants that changed.
complete
• event
Merchants completed. detail is an array of {context, checkout} entries for the merchants that completed in this step. The others can continue, so a session can dispatch complete more than once.
error
• event
detail is an array of {context, checkout, error} entries. An entry with context.shopId belongs to that merchant and leaves the session open. Any other error ends it.
close
• event
Shop Pay closed. detail is null. Closing says nothing about whether the purchase completed.
blocked
• event
The browser blocked Shop Pay's window. detail is {code: 'popup_blocked'}. The overlay offers the buyer a retry, and dismissing it dispatches close.
The shop-pay element
{} The detail of a complete event
Anchor to Next stepsNext steps
- Checkout Kit: The SDK that adds Shop Pay to your page, and embeds a merchant's full Shopify checkout too.
- Cart MCP: Create the carts that you combine into one checkout.
- Build a Universal Checkout: The
create_checkouttool in full, with its requests, responses, and message codes. - Order MCP: Follow the orders that buyers place with Shop Pay.
- Shop Pay in UCP: The handler that merchants advertise to accept Shop Pay.