> ## Documentation Index
> Fetch the complete documentation index at: https://docs.waftpay.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Embedded Checkout

> Open Waftpay checkout in an overlay on your own page and drive it with JavaScript callbacks.

Embed Waftpay checkout directly in your page instead of redirecting away. The checkout runs in an iframe on Waftpay's domain — card and payment details never touch your page — and a small loader script gives you a JavaScript API over it.

<Note>
  You still [create the request token on your server](/api-reference/checkout/checkout-request), exactly as for the [redirect flow](/pages/guides/checkout). The only difference is how the customer reaches the page. Never generate the token in the browser.
</Note>

<Tip>
  Want to see a full integration first? Try the **[WaftStore demo →](https://waftstore.dev.waftpay.io/)**, a sample store that creates a session and opens this checkout.
</Tip>

***

## Quick start

Add the loader script, then mount the checkout with the token your server created.

```html theme={null}
<script src="https://checkout.waftpay.io/v1/waftpay.js"></script>
<script>
  var checkout = Waftpay.mount({
    token: "REQUEST_TOKEN_FROM_YOUR_SERVER",
    onSuccess: function (event) {
      // Update the UI, then confirm server-side before fulfilling. See below.
      console.log(event.reference);
    }
  });
</script>
```

The checkout opens as a centered card over a blurred overlay; your page stays visible behind it.

***

## Confirm payments on your server

<Warning>
  **`onSuccess` is a UI event, not proof of payment.** It is a `postMessage` from a frame, and anyone who can open your page can send one. Treat it purely as a signal to update the UI. Before you fulfil an order, ship goods, or credit an account, confirm the transaction server-side — via your [webhook callback](/pages/webhooks/overview), which remains the source of truth.
</Warning>

***

## `Waftpay.mount(options)`

| Option        | Type     | Description                                       |
| ------------- | -------- | ------------------------------------------------- |
| `token`       | string   | **Required.** The request token from your server. |
| `onReady`     | function | Checkout has loaded and is usable.                |
| `onInitiated` | function | Payment started. Receives `{ reference }`.        |
| `onSuccess`   | function | Payment succeeded. See the redirect rule below.   |
| `onFailure`   | function | Payment failed. Receives `{ reason }`.            |
| `onCancel`    | function | Payer cancelled, or the session expired.          |
| `onClose`     | function | The overlay was removed, for any reason.          |
| `onEvent`     | function | Every raw event, for logging and debugging.       |
| `zIndex`      | number   | Overlay stacking order. Defaults to `2147483000`. |

It returns a handle:

```js theme={null}
checkout.close();    // asks the checkout to close cleanly, then tears down
checkout.destroy();  // removes the overlay immediately
```

Pressing <kbd>Esc</kbd> also asks the checkout to close.

***

## The redirect rule

When a payment resolves, Waftpay produces a success or failure redirect URL. What the loader does with it depends on whether you passed a callback:

* **If you supplied `onSuccess`** (or `onFailure`), we assume you want to stay on your page — your callback fires and the overlay closes. No navigation.
* **If you did not**, the loader navigates your top-level page to the redirect URL — matching the hosted redirect flow.

So a single-page app just supplies callbacks; a traditional page supplies none and gets the classic redirect.

***

## Events

Every event is delivered to `onEvent` in raw form (and to the matching `on*` callback).

| Event                             | Payload                                                       |
| --------------------------------- | ------------------------------------------------------------- |
| `waft:ready`                      | —                                                             |
| `waft:initiated`                  | `reference`                                                   |
| `waft:success`                    | `reference`, `amount`, `currency`, `partial`, `pendingAmount` |
| `waft:failed`                     | `reason`                                                      |
| `waft:cancelled` / `waft:expired` | —                                                             |
| `waft:close`                      | —                                                             |
| `waft:redirect`                   | `url`, `kind` — handled by the loader (see the redirect rule) |
| `waft:open_external`              | `url` — handled by the loader                                 |

<Tip>
  `partial: true` on `waft:success` means the payer settled only part of the total. The overlay deliberately stays open so they can pay the remainder.
</Tip>

***

## Raw iframe (fallback only)

For environments that can't run our script — some WebViews, or sites that block third-party JavaScript — embed the frame directly:

```html theme={null}
<iframe
  src="https://checkout.waftpay.io/embed/REQUEST_TOKEN?origin=https://yoursite.com"
  allow="payment"
  referrerpolicy="strict-origin"
  style="width:100%;height:100%;border:0"
></iframe>
```

* Pass your **exact origin** as `?origin=`, or events cannot be delivered to you.
* Implement the `postMessage` handling yourself, and **validate `event.origin`** against `https://checkout.waftpay.io` on every message.

<Info>
  Prefer the loader script wherever you can — the raw `/embed/<token>` URL is a frozen contract and won't gain new behaviour.
</Info>

***

## Current limitations

* **Overlay only.** The checkout mounts as a centered card over a blurred scrim; in-flow ("inline") embedding is not yet supported.
* **Domain allowlisting is not yet enforced.** During the pilot any origin may frame the checkout. When per-merchant domain registration ships, you'll need to register the domains you embed from — watch for that announcement.

***

## Related links

* [WaftStore demo](https://waftstore.dev.waftpay.io/) — a working merchant integration
* [Checkout (redirect flow)](/pages/guides/checkout)
* [Create Checkout Request API](/api-reference/checkout/checkout-request)
* [Webhooks overview](/pages/webhooks/overview)
