Skip to content

Fluid Cashier

The Fluid Cashier (<fluid-widget>) is the full-featured cashier component. It supports deposits, withdrawals, and payment method management, typically presented as a modal overlay on your site.

Add the Fluid script after the user has authenticated:

<script src="https://get.fluidpayments.io/index.js"></script>

Place the widget element in your page with the required attributes:

<fluid-widget
operator-id="your-operator-id"
session-id="user-session-id"
user-id="user-id"
locale="en"
currency="EUR"
country="MLT"
></fluid-widget>

The widget renders invisibly until you set the open attribute.

The widget can be initialised in one of two ways. Both end in the same state — a configured widget that emits initialised and is ready to open. They differ in what triggers the initialisation and in how the element lives in your DOM:

Automatic initialisation Programmatic initialisation
Triggered by Adding the element to the DOM Calling fluid.init()
When it happens On element mount Right after the script loads, before any mount
Attributes on the element The full required set Only the reactive ones
The element lives Permanently, mounted once per session Wherever your framework puts it, mounted and unmounted freely
Use it when The element sits in a stable part of your page for the whole session Your framework re-renders or conditionally renders the element — for example, it exists only while the cashier is open, or is recreated on route changes

By default, the widget triggers initialisation as soon as it is added to the DOM. This is the simplest approach and the recommended one in most cases:

// 1. Create the element
const widget = document.createElement('fluid-widget');
// 2. Set required attributes
widget.setAttribute('operator-id', 'your-operator-id');
widget.setAttribute('session-id', 'user-session-id');
widget.setAttribute('user-id', 'user-id');
widget.setAttribute('locale', 'en');
widget.setAttribute('currency', 'EUR');
widget.setAttribute('country', 'MLT');
// 3. Attach listeners BEFORE adding to DOM
widget.addEventListener('fluid-info', handleInfo);
widget.addEventListener('fluid-error', handleError);
widget.addEventListener('fluid-command', handleCommand);
// 4. Add to page — initialisation starts automatically
document.body.appendChild(widget);

The element then stays in the DOM for the whole session, driven through its reactive attributes. Don’t open it before initialised fires. For the rules that keep a session healthy, see Session Handling.

Use this approach when the element is not permanent: when it is rendered only while the cashier is open, recreated on navigation, or otherwise injected many times during a session. With automatic initialisation every one of those mounts would start from scratch; fluid.init() moves that work to login time, so each mount finds everything prepared and is instant.

Call fluid.init() right after the script loads. It takes the identity values that would otherwise be set as attributes — note the parameter names countryCode and currencyCode, and that operatorId is a number:

// 1. Prepare the widget — once per user session. This doesn't open any UI.
await fluid.init({
operatorId: 123,
userId: 'user-id',
sessionId: 'user-session-id',
locale: 'en',
countryCode: 'MLT',
currencyCode: 'EUR',
// Optional: bonuses, userData
});
// 2. Create and mount the widget. Keep session-id on the element
// so the widget picks up session rotations.
const widget = document.createElement('fluid-widget');
widget.setAttribute('session-id', 'user-session-id');
// ... attach listeners
document.body.appendChild(widget);

The parameters follow the FluidInitParams type, also available in the @fluidpayments/types package.

Unless specifically intended, call fluid.init() only once per user session. To update widget parameters afterwards, use the reactive attributes. Whenever your page renders the element, it only needs to carry reactive attributes such as transaction, open, balance, withdrawable-balance, bonuses, transaction-limits, success-cta-link and session-id.

When the element is injected after fluid.init():

  • If bonuses are unchanged, the widget doesn’t process them again; likewise, a session-id equal to the one passed to fluid.init() doesn’t trigger re-initialisation.
  • If any of the required init parameters has changed, the widget re-initialises itself on inject.

Both paths normalise POSIX-style underscores, so en_GB is accepted as en-GB. If the result is still not a valid IETF BCP 47 tag, they behave differently:

  • fluid.init() returns a promise that rejects with an Error whose message describes the offending value. Programmatic callers are expected to surface the failure explicitly.
  • The locale attribute falls back to en and emits an invalid-init-attributes fluid-error event.

Once the initialised event fires, open the cashier:

// Open to the default view
widget.setAttribute('open', 'true');
// Open to a specific transaction type: set `transaction` first, then open
widget.setAttribute('transaction', 'withdrawal'); // or 'deposit', 'quick-deposit'
widget.setAttribute('open', 'true');

open only takes true or false. The transaction attribute is applied only while the cashier is closed, so set it before opening.

Three event types require listeners:

widget.addEventListener('fluid-info', (e) => {
const { message } = e.detail;
switch (message) {
case 'initialised':
// Widget is ready to open
break;
case 'deposit-success':
// Deposit was successful
break;
case 'withdrawal-success':
// Withdrawal was successful
break;
}
});
widget.addEventListener('fluid-error', (e) => {
console.error('Fluid error:', e.detail);
});
widget.addEventListener('fluid-command', (e) => {
const { message } = e.detail;
switch (message) {
case 'close':
// User requested to close the cashier
widget.setAttribute('open', 'false');
break;
}
});

Close the cashier by setting open to false:

widget.setAttribute('open', 'false');

Remove the widget entirely when the session ends:

widget.remove();

The widget observes attribute changes while it is open. For example, you can update the session ID if it rotates:

widget.setAttribute('session-id', 'new-session-id');

See the Attributes reference for the full list of supported attributes and which ones are reactive.

An example of everything that can be injected into your page on user login for automatic initialisation. Only operator-id, session-id, user-id, locale, country and currency are required:

<script src="https://get.fluidpayments.io/index.js"></script>
<fluid-widget
operator-id="<your operator ID>"
session-id="<authenticated user session ID>"
user-id="<authenticated user ID>"
user-data="<authenticated user details>"
locale="<locale tag>"
country="<authenticated user country>"
currency="<user currency code>"
transaction="<deposit / withdrawal / quick-deposit>"
lock-transaction-type="<false / true>"
open="<false / true>"
balance="<user current balance>"
withdrawable-balance="<user current withdrawable balance>"
bonuses="<bonus data>"
transaction-limits="<transaction limit data>"
success-cta-link="<link to URL/path following a successful transaction>"
z-index="<z-index value>"
transaction-attributes="<stringified JSON object of key-value pairs for the payment provider>"
deposit-amount="<pre-filled deposit amount>"
allow-decimal-amounts="<true / false>"
prefilled-bonus-code="<bonus code to pre-fill>"
two-factor-auth-enabled="<false / true>"
></fluid-widget>

The element should stay in the DOM for the whole user session. The bonus and user data shapes are documented on the Data Objects page.

  • For cases where the widget needs to request data or trigger an action on your page and receive a typed response, see the Bridge API.
  • Feature-specific behaviours, such as the Withdrawal Warning and Manual Bonus Codes, are documented in the Features section.
  • Fonts, stacking and style encapsulation are covered on the Styling page.