# Widget Integration

> Embed hosted checkout with the browser widget runtime.

Canonical: https://stafiel.org/documentation/developer-integration/widget-integration
Version: v1.0.0

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
checkoutSessionUrl from the response data to the browser.

Important: Do not put API keys in frontend or browser code.

## Runtime Scripts

Load one of the browser runtimes from the widget domain for your network mode.
The stable paths are:

Runtime
Script
Global
Use when

Checkout snippet
https://widget.stafiel.com/widget/v1/checkout.js
window.StafielCheckout
You want a smaller helper for button binding or declarative HTML binding.

Widget runtime
https://widget.stafiel.com/widget/v1/widget.js
window.StafielWidget
You want direct control over create, open, mount, events, and cleanup.

## Checkout vs Widget

Use Checkout snippet for quick development and deployment. It is best for
payment buttons, simple modal checkout, and declarative HTML binding.

Use Widget runtime when you need direct control over the checkout instance. It is
best for inline checkout areas, custom lifecycle handling, event subscriptions,
theme changes, or cleanup in single-page applications.

Both runtimes consume the same checkoutSessionUrl. The checkoutSessionUrl
is an opaque hosted checkout URL. Do not parse, rebuild, or modify it.

## Checkout Snippet Example

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',
    theme: 'light'
  });
</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.

## Checkout Snippet Binding

open(), bind(), and bindAll() return binding instances.

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](#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.

theme
No
light
One of light or dark.

autoFallback
No
false
Allows fallback to another mode when needed.

onOpen
No
None
Called when checkout opens.

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.

## Declarative Binding

checkout.js can bind elements declared in HTML.

<div
  data-stafiel-checkout
  data-checkout-session-url="https://pay.stafiel.com/pay/ps_your_session_token"
  data-mode="lite"
  data-theme="light"
  data-scale="1"
  data-border-radius="16"
></div>

<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](#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-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 Example

<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'),
    theme: 'light'
  });

  widget.mount();
</script>

Use open() for redirect and modal mode. Use on() to subscribe to widget
events, and clean up subscriptions or widget instances when your page no longer
needs them.

<script>
  const widget = window.StafielWidget.create({
    checkoutSessionUrl: 'https://pay.stafiel.com/pay/ps_your_session_token',
    mode: 'modal',
    theme: 'light'
  });

  const unsubscribe = widget.on('order.payment.received_fullpaid', function (event) {
    console.log('Order paid', event);
  });

  await widget.open();

  // Later, for example when leaving a single-page app route:
  unsubscribe();
  widget.destroy();
</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](#widget-modes).

container
Required for mounted modes
None
HTMLElement used by inline, lite, or micro. You may also pass it to mount(container).

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.

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](#widget-methods) and
[Events](#events).

The Checkout snippet accepts a flat borderRadius option. The Widget runtime
nests the same setting under appearance.borderRadius.

Internal debug, preview, and advanced timeout options are intentionally not part
of the public integration surface.

## Widget Runtime API

Method
Returns
Description

create(options)
WidgetInstance
Creates a widget instance from a hosted checkout session URL and widget options.

## 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 checkout in an overlay.

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. The runtime scales the complete checkout surface
uniformly. Modal checkout may be constrained by the available browser viewport
on smaller screens. widget.js and checkout.js share this non-redirect scale
contract; no legacy scale mapping is applied.

## Widget Methods

Method
Returns
Description

open()
Promise<void>
Opens redirect or modal mode.

mount(container?)
Promise<void>
Mounts inline, lite, or micro mode.

close()
void
Closes the current widget surface when supported.

destroy()
void
Removes listeners, frames, and runtime state for the instance.

setTheme(theme)
void
Switches the instance between light and dark.

on(event, handler)
() => void
Subscribes to a widget event and returns an unsubscribe function.

## Events

Widget events are browser-side UI and status signals. The full event set below
is available through the Widget runtime on(event, handler) API. Checkout
snippet integrations receive lifecycle signals through onOpen, onClose,
onError, and onFallback options in
[Checkout Snippet Options](#checkout-snippet-options). Use webhooks or the order
query APIs for server-side state changes.

Event
Description

widget.ready
The widget instance or iframe runtime is ready.

widget.opened
Checkout was opened or mounted.

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 reported an awaiting-payment order.

order.payment.detected
The checkout surface reported a detected payment.

order.payment.received_fullpaid
The checkout surface reported a fully paid order.

order.payment.received_underpaid
The checkout surface reported an underpaid order.

order.payment.received_overpaid
The checkout surface reported an overpaid order.

order.payment.confirmed
The checkout surface reported payment confirmation.

order.paid
The checkout surface reported a paid status.

order.settled
The checkout surface reported settlement.

order.expired
The checkout surface reported expiration.

order.closed
The checkout surface reported closure.

order.compliance_hold
The checkout surface reported a compliance hold.

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.

## Security Notes

Create checkout sessions on your server. The browser widget only needs the
checkoutSessionUrl.

Keep the widget script host aligned with the checkout session's network mode. If
you use a testnet checkout session URL in widget code, use the testnet widget
script host and testnet checkout configuration.
