Widget Integration
Embed hosted checkout with the browser widget runtime.
Use the widget runtime when your frontend needs to launch a Stafiel checkout
session. Create the checkout session first on your server, then pass the
complete checkoutSessionUrl from the response data to the browser. Do not
parse, rebuild, or modify this URL.
Important: Do not put API keys in frontend or browser code.
Widget Base URL
https://widget.stafiel.com
Choose a Runtime
Checkout Snippet
Script path:
/widget/v1/checkout.js
This script exposes window.StafielCheckout. Use it for quick binding and
declarative integration.
Widget Runtime
Script path:
/widget/v1/widget.js
This script exposes window.StafielWidget. Use it when you need direct control
over widget instances, events, mounting, theme updates, and cleanup.
Your application owns loading and failure handling while either browser script loads. Once a checkout frame is running, Stafiel renders its built-in loading and failure states.
A merchant-rendered payment page uses a separate integration model. See Custom Payment Page.
Widget Modes
| Mode | Call | Default frame size | Description |
|---|---|---|---|
redirect |
open() |
Hosted checkout page | Opens the hosted checkout URL in a new tab by default, or in the current tab when openInNewTab is false. |
modal |
open() |
828 x 648 px |
Opens the built-in modal. |
inline |
mount() |
272 x 384 px |
Mounts a full checkout frame into your page. |
lite |
mount() |
368 x 144 px |
Mounts a compact checkout frame. |
micro |
mount() |
256 x 128 px |
Mounts the smallest checkout frame for compact payment areas. |
The shown frame size applies when scale is 1. All non-redirect modes accept
values from 0.8 through 2.5 and scale the complete checkout surface
uniformly. Modal checkout fits the available browser viewport on smaller
screens.
In redirect mode, an allowed metadata.returnToUrl supplies the hosted
checkout Back destination. In modal, inline, lite, and micro modes,
the merchant frontend controls the surrounding page; metadata.returnToUrl
does not navigate it.
Checkout Snippet
Checkout Snippet Quick Start
Use checkout.js when you want to bind checkout behavior to a button or DOM
node without managing the lower-level widget instance yourself.
<button id="pay-now">Pay now</button>
<script src="https://widget.stafiel.com/widget/v1/checkout.js"></script>
<script>
window.StafielCheckout.bind('#pay-now', {
checkoutSessionUrl: 'https://pay.stafiel.com/pay/ps_your_session_token',
mode: 'modal'
});
</script>
Checkout Snippet API
| Method | Returns | Description |
|---|---|---|
open(options) |
Promise<CheckoutSnippetBinding> |
Opens checkout immediately. |
bind(target, options) |
CheckoutSnippetBinding |
Binds checkout to a CSS selector or HTMLElement. |
bindAll(root?, defaults?) |
CheckoutSnippetBinding[] |
Binds every [data-stafiel-checkout] node under root. |
setTheme(target, theme) |
void |
Updates the theme for an existing binding. |
unbind(target) |
void |
Removes the click trigger listener for one binding. |
destroy(target?) |
void |
Removes one binding, or all bindings when no target is provided. |
Binding Methods
bind() returns one binding, bindAll() returns an array of bindings, and
open() resolves to a binding.
| Method | Returns | Description |
|---|---|---|
open() |
Promise<void> |
Opens the bound checkout. |
close() |
void |
Closes the current checkout surface when supported. |
destroy() |
void |
Removes the binding and its runtime state. |
setTheme(theme) |
void |
Switches the binding between light and dark. |
update(options) |
void |
Updates the binding with new checkout snippet options. |
Checkout Snippet Options
| Option | Required | Default | Description |
|---|---|---|---|
checkoutSessionUrl |
Yes | None | Hosted checkout URL returned by your server. |
mode |
Yes | None | One of the values listed in Widget Modes. |
container |
No | Bound target | Optional container selector or element for mounted modes. |
openInNewTab |
No | true for redirect |
Controls redirect mode tab behavior. |
scale |
No | 1 |
Widget scale for non-redirect modes, clamped between 0.8 and 2.5. |
borderRadius |
No | 24 for modal, 16 otherwise |
Frame border radius in pixels, clamped between 0 and 24. |
backdrop |
No | true |
Modal only. Set to false to hide the dimming; the page remains non-interactive. |
theme |
No | light |
One of light or dark. |
autoFallback |
No | false |
Allows fallback to another mode when needed. |
onOpen |
No | None | Called when the checkout surface opens; payment data may still be loading. |
onClose |
No | None | Called when checkout closes. |
onError |
No | None | Called when checkout fails to initialize or open. |
onFallback |
No | None | Called when the runtime falls back to another mode. |
Checkout Snippet modal always uses the full page.
Declarative Binding
checkout.js can bind elements declared in HTML.
<button
data-stafiel-checkout
data-checkout-session-url="https://pay.stafiel.com/pay/ps_your_session_token"
data-mode="modal"
data-theme="light"
data-scale="1"
data-border-radius="24"
data-backdrop="true"
>
Pay now
</button>
<script src="https://widget.stafiel.com/widget/v1/checkout.js"></script>
<script>
window.StafielCheckout.bindAll();
</script>
Supported data attributes:
| Attribute | Required | Description |
|---|---|---|
data-stafiel-checkout |
Yes | Marks the element for bindAll(). |
data-checkout-session-url |
Yes, unless supplied in bindAll defaults |
Hosted checkout URL. |
data-mode |
Yes | One of the values listed in Widget Modes. |
data-container |
No | Selector for a separate mounted container. |
data-scale |
No | Widget scale for non-redirect modes. |
data-border-radius |
No | Frame border radius in pixels. |
data-backdrop |
No | Modal only. Set to false to hide the dimming; the page remains non-interactive. |
data-theme |
No | light or dark. |
data-auto-fallback |
No | Boolean value: true, false, 1, or 0. |
data-open-in-new-tab |
No | Boolean value used by redirect mode. |
Widget Runtime
Widget Runtime Quick Start
<div id="stafiel-payment"></div>
<script src="https://widget.stafiel.com/widget/v1/widget.js"></script>
<script>
const widget = window.StafielWidget.create({
checkoutSessionUrl: 'https://pay.stafiel.com/pay/ps_your_session_token',
mode: 'inline',
container: document.getElementById('stafiel-payment')
});
widget.mount();
</script>
Widget Options
| Option | Required | Default | Description |
|---|---|---|---|
checkoutSessionUrl |
Yes | None | Hosted checkout URL returned by your server after creating a checkout session. |
mode |
Yes | None | One of the values listed in Widget Modes. |
container |
For mounted modes | None | Connected HTMLElement used by inline, lite, and micro. |
openInNewTab |
No | true for redirect |
Controls whether redirect mode opens a new browser tab. |
scale |
No | 1 |
Widget scale for non-redirect modes, clamped between 0.8 and 2.5. |
appearance.borderRadius |
No | 24 for modal, 16 otherwise |
Frame border radius in pixels, clamped between 0 and 24. |
modal.backdrop |
No | true |
Modal only. Set to false to hide the dimming; the page remains non-interactive. |
modal.boundary |
No | Full page | Connected, positioned HTMLElement that bounds the complete modal area. |
autoFallback |
No | false |
Allows the runtime to fall back to another mode when the requested mode cannot be opened. |
theme |
No | light |
One of light or dark. |
The Widget runtime delivers events through widget.on(event, handler) rather
than option-level callbacks. See Widget Methods and
Events.
The Checkout snippet accepts a flat borderRadius option. The Widget runtime
nests the same setting under appearance.borderRadius.
Widget Methods
| Method | Returns | Description |
|---|---|---|
StafielWidget.create(options) |
WidgetInstance |
Creates a widget instance from a hosted checkout session URL and widget options. |
widget.open() |
Promise<void> |
Opens redirect or modal mode. |
widget.mount(container?) |
Promise<void> |
Mounts inline, lite, or micro mode. |
widget.close() |
void |
Closes the current checkout and built-in modal. |
widget.destroy() |
void |
Removes listeners, frames, and runtime state for the instance. |
widget.setTheme(theme) |
void |
Switches the instance between light and dark. |
widget.on(event, handler) |
() => void |
Subscribes to a widget event and returns an unsubscribe function. |
Custom Modal Boundary
modal.boundary limits the backdrop, payment panel, and close area to part of
your page. It does not resize only the payment panel.
A custom boundary must be connected, positioned, and have a visible size before
you call widget.open().
<div id="stafiel-modal-boundary"></div>
<style>
#stafiel-modal-boundary {
position: relative;
width: 100%;
height: 720px;
overflow: hidden;
}
</style>
<script>
(async function () {
const boundary = document.getElementById('stafiel-modal-boundary');
const widget = window.StafielWidget.create({
checkoutSessionUrl: 'https://pay.stafiel.com/pay/ps_your_session_token',
mode: 'modal',
modal: {
boundary
}
});
await widget.open();
})();
</script>
Omit modal.boundary to use the default full-page modal.
Events
Widget events are browser-side UI and status signals available through the
Widget runtime on(event, handler) API. Order events are available only while
an embedded checkout frame is active in modal, inline, lite, or micro
mode. Redirect mode does not emit order events.
These events reflect states observed by the active checkout surface and do not
represent a complete order lifecycle. Checkout snippet integrations receive
lifecycle signals through onOpen, onClose, onError, and onFallback
options in Checkout Snippet Options. Use webhooks
or the order query APIs for server-side state changes.
| Event | Description |
|---|---|
widget.ready |
The widget instance is ready. Emitted once per instance. |
widget.opened |
Checkout was opened or mounted; payment data may still be loading. |
widget.closed |
Checkout was closed. |
widget.error |
The widget failed to initialize, mount, open, or load. |
widget.fallback |
The runtime switched to another mode. |
order.created |
The checkout surface observed the order in the awaiting-payment state. |
order.payment.detected |
The checkout surface received a real-time payment-detected signal. This event is not guaranteed for every payment path. |
order.payment.received_fullpaid |
The currently recorded payment amount matched the required amount. |
order.payment.received_underpaid |
The currently recorded payment amount was below the required amount. |
order.payment.received_overpaid |
The currently recorded payment amount exceeded the required amount. |
Event payload fields vary by event type.
| Field | Description |
|---|---|
event |
Event name. Present on every widget event. |
version |
Widget event payload version. Present on every widget event. |
timestamp |
Event timestamp. Present on every widget event. |
orderId |
Order ID when available. |
paymentToken |
Payment token when available. |
mode |
Active widget mode. Present on lifecycle, error, and order events. |
reason |
Error or fallback reason. Present on widget.error and widget.fallback. |
recoverable |
Whether the error can fall back to another mode. Present on widget.error. |
fromMode |
Original widget mode. Present on widget.fallback. |
toMode |
Fallback widget mode. Present on widget.fallback. |
status |
Order status. Present on order events. |
payload |
Event-specific payload. Present on order events and some error events. |