Redirect vs. embed
After you create a checkout session, the response includes a hostedurl. You can present it two ways:
- Redirect — send the customer to
url(window.location.href = url). Simplest to integrate; the customer leaves your page and comes back viareturn_url. See the Quickstart. - Embed — load
urlin an<iframe>so checkout renders in context, without a full-page navigation. This page covers embedding.
url is presented on your frontend.
Soap checkout is cookieless: the session’s
client_secret travels as a query parameter on every request, so cross-origin embedding does not depend on third-party cookies and needs no special browser configuration.Before you start: register your embedding domain
Two things are tied to the domain of the page that hosts the iframe (your site’s top-level domain). Share your production and staging origins with Soap once, during onboarding:- Framing allowlist — Soap’s checkout only allows itself to be framed by approved origins (CSP
frame-ancestors). Until your origin is allowlisted, the iframe will render blank. - Apple Pay domain registration — Apple validates Apple Pay against the top-level page, so your domain must be registered for Apple Pay web merchant validation. Cards and Google Pay work without this.
1. Create the session on your backend
Almost unchanged from the redirect flow — create the checkout server-side (so your API key stays private), pass areturn_url, and set experience: "iframe". That flag tells Soap the checkout will be framed: Soap redirects the customer to return_url inside the iframe on completion, and Apple Pay validates against your embedding domain instead of Soap’s hosted one.
2. Embed the checkout URL in an iframe
Load the returnedurl into an <iframe>. The allow="payment" attribute is required for Apple Pay, Google Pay, and other Payment Request wallets to work inside the frame.
3. Know when checkout completes
Use two signals, in order of authority:Webhooks (source of truth)
Payment state is confirmed server-side. Always reconcile off webhooks — never treat a client-side event as proof of payment.return_url + postMessage (UX hint)
On completion the checkout redirects within the iframe to your return_url. Because that page loads inside the frame, it can notify your top-level page with postMessage:
The completion message is sent by your own
return_url page (it loads inside the iframe after the checkout redirects to it), so event.origin is your site’s origin — not the Soap wallet domain. Validate it against your own origin as shown above, and treat the message as a UX hint only: confirm the payment via webhooks.Caveats
Apple Pay requires registering your embedding domain
Apple Pay requires registering your embedding domain
Apple validates Apple Pay against the top-level page domain — the site hosting the iframe, not the checkout iframe itself. To offer Apple Pay in-frame you need both pieces from this guide: your embedding domain registered with Soap for Apple Pay web merchant validation (see Before you start), and the session created with
experience: "iframe". The checkout detects your top-level domain automatically at payment time — no extra frontend work.Bank login (Plaid / Link Money) may open a new window
Bank login (Plaid / Link Money) may open a new window
Banks refuse to be framed, so OAuth-style bank connection can open in a popout/new window and return control to the iframe afterward. Every other method — cards, Apple Pay, Google Pay — stays fully in-frame.
Sandbox vs. production URLs
Sandbox vs. production URLs
Sandbox checkout URLs are on
wallet-sandbox.paywithsoap.com; production on wallet.paywithsoap.com. The url in the API response already points at the right one for the key you used.
