# Fluid Docs — full documentation > Source: https://docs.fluidpayments.io > This file concatenates the body of every page in the Fluid public documentation. > Generated by scripts/generate-llms.mjs — do not edit by hand. --- # Introduction > Source: https://docs.fluidpayments.io/docs/integration-manual/intro This document gives an outline of the Fluid Wallet widgets and how they are integrated into the host website. ## 1. Fluid Widget The main Fluid Widget has three principal user functions: **Deposit**, **Quick Deposit** and **Withdrawal**. The initial screen presented to the user for each of these functions is shown in the figure below. These principal functions allow the user to perform deposits and withdrawals with a variety of customised settings. See how to integrate it [here](https://docs.fluidpayments.io/docs/integration-manual/fluid-widget-integration). ![](https://docs.fluidpayments.io/img/integration-manual/intro/principal-user-functions.png) ## 2. Fluid Quick Deposit The Fluid Quick Deposit widget is a simplified version of the Fluid Wallet that allows the user to make a deposit with a single click, using their recently stored method. If the user has no stored methods, the widget emits a notification to the host website, which it can react to by opening the Fluid Wallet for regular deposit. This web component is designed with desktop gameplay in mind, and it is integrated into the DOM as an inline element, respecting its parent element styles. See how to integrate it [here](https://docs.fluidpayments.io/docs/integration-manual/fluid-quick-deposit-integration). ![](https://docs.fluidpayments.io/img/integration-manual/intro/inline-quick-deposit.png) ## 3. Fluid Virtual for Sweepstakes The Fluid Virtual widget is a version of the Fluid Wallet that allows users to deposit and withdraw virtual currency for sweepstakes gameplay. It operates similarly to the main Fluid Wallet but is tailored for virtual currency transactions. See how to integrate it [here](https://docs.fluidpayments.io/docs/integration-manual/fluid-virtual-integration). **Packs selection** Fluid presents available sweepstakes packs to users organised in multiple sections: - Promoted Packs as a carousel - Special Promotion Pack as in its own banner - Regular Packs as a grid Fluid also allows for purchasing custom amounts of virtual currency via the amount input field, with immediate conversion presented. **Visual features** Pack items can be styled with a predefined variant to highlight specific offers, and operators can configure which sections to display based on their promotional strategies; - "regular" (default) - "green" - "red" - "yellow" - "promotion" The previous variant names ("best_value", "discount", "exclusive") are still accepted for backwards compatibility — see the [Sweepstakes integration page](https://docs.fluidpayments.io/docs/integration-manual/fluid-virtual-integration#backwards-compatibility) for details. Packs can also be tagged with a "Hot" label to draw user attention. --- # Integration Tutorial > Source: https://docs.fluidpayments.io/docs/integration-manual/tutorial This page is an interactive component. View it in the browser at https://docs.fluidpayments.io/docs/integration-manual/tutorial. --- # Fluid Virtual Widget Integration for Sweepstakes > Source: https://docs.fluidpayments.io/docs/integration-manual/fluid-virtual-integration The Fluid Virtual, same as the standard Fluid Widget, is implemented as a web component integrated into the host page DOM. By design, the Fluid widget [script](https://get.fluidpayments.io/index.js) should get injected into the host site **upon user authentication**, followed by injecting `` web component into the DOM, providing required init attributes. ### Automatic Init The `` custom element expects several attributes required for initialisation (more on attributes [here](#fluid-virtual-custom-element-attributes-in-detail)). If the required initialisation parameters are provided at injection, the widget will automatically initialise and be ready for use. This initialisation should occur once per user session, immediately after user authentication. A [notification](#notifications-emitted-by-the-fluid-wallet) will indicate that the widget is ready for opening - it **should not be allowed to open before this notification is emitted**. Once the session ends, the widget should be removed from the DOM to ensure proper shutdown. ## Fluid Virtual custom element attributes in detail Fluid widget setup expects a list of parameters to properly configure itself for an authenticated user: - `operator-id` - unique identifier of the host site / operator \*\* - `session-id` - up-to-date session code of the currently authenticated user \*\* - `user-id` - identifier of currently authenticated user \*\* - `user-data` - details of currently authenticated user of type `FluidUserData` \*\* - `locale` - locale tag according to IETF BCP 47 (e.g. `en-NZ` or `es-MX`), with `en` (default English) and `ar` (default Arabic) being an exception \*\*. POSIX-style underscores are normalised automatically (`en_GB` is accepted as `en-GB`). If the value is still invalid after normalisation, the widget falls back to `en` and emits a `fluid-error` event with message `invalid-init-attributes`. - `country` - country of currently authenticated user in ISO 3166-1 Alpha-3 format \*\* - `currency` - FIAT currency code according to ISO 4217 \*\* - `virtual-currencies` - virtual currencies held by the user, object of type _VirtualCurrencies_ available in the [`@fluidpayments/types`](https://www.npmjs.com/package/@fluidpayments/types) package, stringified as JSON: ```ts type VirtualCurrencies = { depositCurrency: VirtualCurrency; withdrawalCurrency: VirtualCurrency; }; type VirtualCurrency = { name: string; code: string; symbol: string; exchangeRateToFiatCurrency: number; icon?: string; conversionOffset?: number; }; ``` - `transaction` - _deposit_ | _withdrawal_ | _quick-deposit_ - `lock-transaction-type` - When true, the user cannot switch from the current transaction type. - `open` - _true_ or _false_ - `balance` - current user balances, object of type _VirtualBalance_ available in the [`@fluidpayments/types`](https://www.npmjs.com/package/@fluidpayments/types) package, stringified as JSON: ```ts type VirtualBalance = { depositCurrencyBalance: number; withdrawalCurrencyBalance: number; lockedWithdrawalCurrencyBalance?: number; }; ``` - `packs` - stringified packs data, structure described [below](#packs-data-object) - `deposit-limit` - responsible gaming deposit limit - `success-cta-link` - link for the CTA button after a successful transaction - `z-index` - use a value high enough to display the wallet in front of other elements on the host site - `turned-over-percentage` - percentage of the turned over amount. If none is provided the information will not be displayed - `transaction-attributes` - a stringified json object of key-value pairs that will be sent to the payment provider as transaction attributes together with the user agent and bonus code (if applicable) - `deposit-amount` - the amount that will be pre-filled for the user in deposit. It takes precedence over the configured ones and should be unset for bringing back the default behaviour \*\* Mandatory for Automatic Init The `operator-id` value must correspond to the Payment Operator Config property value. This value is provided by Fluid Payments. ### Observed (reactive) Attributes The following attributes are observed by the widget and change in their value on the host site causes a reaction/event within the wallet. - `open` - triggers the wallet to become visible or hidden - `balance` - up-to-date balance information in virtual currencies - `session-id` - assures consistently valid user session Other reactive attributes are observed only while the wallet is closed: - `transaction` - updates transaction type - `lock-transaction-type` - locks the transaction type, preventing the user from switching between Quick Buy and Redeem - `deposit-limit` - updates responsible gaming deposit limit amount - `user-data` - updates user data for resolving Suggested Deposit Amounts, Payment Methods Order and KYC status - `success-cta-link` - sets the link to follow on successful transaction - `turned-over-percentage` - sets the turned over percentage - `transaction-attributes` - updates transaction attributes sent with each transaction request Note that there won't be any reaction to changes of those 6 attributes while the wallet is open. This is to assure integrity of user's experience and that the transaction flow is not interrupted by any changes on the host site. ## Notifications emitted by the Fluid Wallet In addition to receiving information from the host site, the Fluid wallet emits information out to the host website using `CustomEvent` (https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent), with the `detail` property containing the information. This property is an object with the following structure, also available as a type in the [`@fluidpayments/types`](https://www.npmjs.com/package/@fluidpayments/types) package as `FluidNotificationDetail` ```ts type FluidNotificationDetail = { message: string; [key: string]: any; }; ``` `message` contains a string with the different event types listed below. Add the following code to receive those events: ```ts fluid.addEventListener("fluid-command", onFluidCommand); fluid.addEventListener("fluid-info", onFluidInfo); fluid.addEventListener("fluid-error", onFluidError); ``` - `fluid-info` - messages of informational nature, with the purpose of e.g. tracking or allowing user action - `fluid-error` - unexpected failure notifications - `fluid-command` - commands to react to Possible values of those types can be expected to be: - `fluid-info`: - _initialised_ - wallet has been prepared for opening - it should not be allowed to open before this is emitted - _opened_ - the wallet has been opened - _destroyed_ - the wallet instance has been terminated - _internal-operation-change_ - transaction flow has been amended internally, e.g. upon withdrawal without a positive withdrawable balance - _success-cta-click_ - user clicked on the CTA shown on the transaction success screen - _deposit-success_ - when a successful deposit is made - _deposit-failure_ - deposit attempt failed - _error-cta-clicked_ - user clicked on the CTA shown on the transaction failure screen - _withdrawal-success_ - when a successful withdrawal is made - _withdrawal-failure_ - withdrawal attempt failed - _withdrawal-cancelled_ - when a withdrawal is cancelled - _contact-support_ - user clicked on the Contact Support link shown on transaction failure screen - _bonus-changed_ - user changed selected deposit bonus - _payment-method-changed_ - user changed the selected payment method - _dialog-opened_ - a dialog has been opened from the wallet - _dialog-closed_ - a dialog has been closed from the wallet - `fluid-error`: - _initialisation-failure_ - Fluid wasn’t able to configure itself, e.g. due to a network or backend issue - _operation-execution-failure_ - an operation failed unexpectedly due to an error - _invalid-bonus-data_ - the bonus data is not in the correct format expected - _invalid-user-data_ - the user data is not in the correct format expected - _invalid-transaction-attributes_ - the transaction attributes are not in the correct format expected - _invalid-init-attributes_ - an init attribute (currently the `locale`) failed validation; the widget falls back to a safe default (`en` for `locale`) and keeps initialising. - `fluid-command`: - _close_ - user selected to close the wallet from within, the `open` attribute should be set to _false_ - _handle-transaction_ - when deposit or withdrawal is to be handled outside of Fluid - _start-kyc-verification_ - when the user clicks on the Verify button in the fluent message - _handle-banner-cta-click_ - when the user clicks on the banner on the first step of Quick Buy flow Note that `fluid-info`notifications are not primarily designed for tracking, although some carry detailed information on the event, e.g. `payment-method-changed`, `bonus-changed` and all transaction result ones include `activityId`, representing unique user interaction with the wallet, which allows for stitching those events with a particular transaction id. For cases where the widget needs to request data or trigger an action on the host page and receive a typed response, see the [Window Bridge API](https://docs.fluidpayments.io/docs/integration-manual/bridge-api). ## Example code The following is an example of what's to be injected to your website DOM upon user login for Automatic Init: ```html ``` It should stay present in the DOM for the time of user session. Initial mandatory attributes are: `operator-id`, `session-id`, `user-id`, `user-data`, `country`, `locale`, and `currency`. ## Packs Data Object Fluid Virtual organises packs into five sections, each with its own layout: a grid of **regular** packs, a carousel of **promoted** packs (in the `green`, `red`, and `yellow` color variants), a **promoted special** banner, a **promoted on abort** modal, and a **promoted upsell** strip. The diagram below labels each pack type with the properties that drive its appearance — `label`, `price`, `previousPrice`, `discount`, `info`, `tagged`, and `expirationDate` — so you can map what you pass to what users see. The `variant` field only controls the badge **colour**; the badge text comes from `label`, the price-in-red treatment from `priceHighlighted`, and the upsell's secondary red badge from `discount`. ![Anatomy of a Sweepstakes pack](https://docs.fluidpayments.io/img/integration-manual/fluid-virtual-integration/sweepstakes-pack-structure.png) _Figure - Anatomy of a Sweepstakes pack_ ```ts type Pack = { packId: string; variant: PackVariant; value: { price: number; previousPrice?: number; deposit: number; withdrawal: number; }; logoUrl: string; logoAlt?: string; label?: string; title?: string; /** @deprecated Use `label` instead. */ info?: string; tagged?: boolean; selected?: boolean; expirationDate?: Date; discount?: string; /** * When `true`, renders the current price in the accent (red) colour. * Has no visible effect when `value.previousPrice` is set — that path already uses the accent colour. * When omitted, treated as `false`. */ priceHighlighted?: boolean; }; type PackSet = { regular: Pack[]; promoted: Pack[]; promotedSpecial?: Pack; promotedUpsell?: Pack; promotedOnAbort?: Pack; }; ``` The structure containing sample data (type of _PackSet_ available in the [`@fluidpayments/types`](https://www.npmjs.com/package/@fluidpayments/types) package) is as follows: ```ts const packs = { regular: [ { packId: "pack-regular-01", logoUrl: "assets/images/sweepstakes/pack-4.99.png", variant: "regular", value: { price: 4.99, deposit: 5000, withdrawal: 5, }, }, { packId: "pack-regular-02", logoUrl: "assets/images/sweepstakes/pack-9.99.png", variant: "regular", value: { price: 9.99, deposit: 10000, withdrawal: 10, }, }, ], promoted: [ { packId: "pack-red-01", logoUrl: "assets/images/sweepstakes/pack-red.png", variant: "red", // colour of the badge — purely visual label: "-25%", // text shown on the badge value: { price: 49.99, previousPrice: 64.99, // when set, the current price is auto-rendered in the accent (red) colour deposit: 65000, withdrawal: 65, }, }, { packId: "pack-yellow-01", logoUrl: "assets/images/sweepstakes/pack-yellow.png", variant: "yellow", label: "Exclusive", priceHighlighted: true, // renders the price in the accent (red) colour even without a previousPrice tagged: true, value: { price: 79.99, deposit: 100000, withdrawal: 100, }, }, { packId: "pack-green-01", logoUrl: "assets/images/sweepstakes/pack-green.png", variant: "green", label: "Best value", value: { price: 9.99, deposit: 15000, withdrawal: 15, }, }, ], promotedSpecial: { packId: "pack-promotion-01", logoUrl: "assets/images/sweepstakes/special-promotion.png", variant: "promotion", label: "Special promotion", info: "+ 5,000 purchases this week", expirationDate: "2026-12-31T23:59:59Z", value: { price: 74.99, previousPrice: 99.99, // previousPrice already paints the price in the accent colour — no priceHighlighted needed deposit: 10000, withdrawal: 5, }, }, promotedUpsell: { packId: "pack-promotion-upsell-01", logoUrl: "assets/images/sweepstakes/upsell-promotion.png", variant: "promotion", label: "Exclusive Offer", expirationDate: "2026-12-31T23:59:59Z", discount: "-15%", // the only place the `discount` field is rendered: as a second red badge next to `label` value: { price: 89.99, previousPrice: 99.99, deposit: 10000, withdrawal: 100, }, }, promotedOnAbort: { packId: "pack-promotion-upsell-modal-01", logoUrl: "assets/images/sweepstakes/upsell-promotion-modal.png", variant: "promotion", label: "Special promotion", info: "+ 5,000 purchases this week", expirationDate: "2026-12-31T23:59:59Z", value: { price: 89.99, previousPrice: 99.99, deposit: 10000, withdrawal: 100, }, }, }; ``` _Figure 4 - Definition of Packs Passed to the Fluid Widget (Example)_ ### Packs usage - **regular**: default list of packs, shown on _First-Time Deposit_ and in the _View All Packs_ dialog - **promoted**: packs displayed in the carousel - **promotedSpecial**: main promotional pack displayed below the carousel on _First-Time Deposit_ and in the _View All Packs_ dialog - **promotedUpsell** pack displayed at the bottom of the payment method selection on _First-Time Deposit_ and on the first step of a _Subsequent Deposit_ - **promotedOnAbort** if available, displayed in a modal when the user closes the wallet during the deposit journey ### Packs structure - `packId` (`string`) - unique identifier of the pack - `variant` (`string`) - `'regular' | 'green' | 'red' | 'yellow' | 'promotion'` - `value` (`object`) - details of the pack: - `price` (`number`) - price of the pack in FIAT currency - `previousPrice` (optional, `number`) - previous price of the pack in FIAT currency, used to show a price discount - `deposit` (`number`) - amount of virtual currency credited to user's deposit balance - `withdrawal` (`number`) - amount of virtual currency credited to user's withdrawal balance - `logoUrl` (`string`) - URL of the pack image\* - `logoAlt` (optional, `string`) - alt text for the pack image - `label` (optional, `string`) - text shown on the pack badge (for example `"Best value"` on a `green` pack) - `info` (optional, `string`) - additional info label for the pack - `tagged` (optional, `boolean`) - indicates if the pack should be visually tagged - `selected` (optional, `boolean`) - indicates if the pack is preselected - `expirationDate` (optional, `Date`) - expiration date of the pack in ISO 8601 format - `discount` (optional, `string`) - discount text, for example `"-25%"`. Used **only** by the promoted upsell, where it renders as a second red badge alongside `label`. - `priceHighlighted` (optional, `boolean`) - renders the current price in the accent (red) colour. Has no visible effect when `value.previousPrice` is set (that path already uses the accent colour). Defaults to `false` when omitted. ### Backwards compatibility The `label` property and the `green`/`red`/`yellow` variant values replace the previous `title` property and `best_value`/`discount`/`exclusive` variants. Existing integrations that still pass the deprecated names continue to work — Fluid normalizes them at the input boundary — but new integrations should use the new vocabulary, and existing operators are encouraged to migrate. The normalization layer also preserves two side-effects the deprecated variants used to imply: - Packs sent with `variant: "exclusive"` automatically get `priceHighlighted: true` so the price keeps rendering in the accent colour, matching the old yellow-exclusive look. - Packs sent with `variant: "discount"` that only carry a `discount` text (and no `label`) automatically receive `label = discount` so the carousel badge keeps its text after the rendering switch from `discount` to `label`. ### Pack image dimensions All the images used for the packs have **a ratio of 2:1**. The available dimensions are: - `regular`, `promoted` and `promotedUpsell` packs: 154px × 77px (308px × 154px for retina) - `promotedSpecial` and `promotedOnAbort` packs: 328px × 164px (656px × 328px for retina) The retina dimension is recommended, for a sharp display on mobile devices. ## User Data Object Used for resolving Suggested Deposit Amounts and Payment Methods Order with use of Machine Learning based on historical transactions' data. The structure, available as `FluidUserData` type in the [`@fluidpayments/types`](https://www.npmjs.com/package/@fluidpayments/types) package, is as follows: ```ts type FluidUserData = { age?: number; affiliateId?: string; depositCount?: number; daysSinceRegistration?: number; fullName?: string; kycStatus?: FluidKycStatus; lifetimeDeposit?: number; previousDeposit?: number; tags?: string[]; }; ``` All the properties are optional. --- # Fluid Quick Deposit Integration > Source: https://docs.fluidpayments.io/docs/integration-manual/fluid-quick-deposit-integration ## Overview The **Fluid Quick Deposit** is a web component that integrates into the DOM similarly to the [Fluid Widget](https://docs.fluidpayments.io/docs/integration-manual/fluid-widget-integration). It is designed as an inline element that respects its parent element styles and is intended for desktop gameplay. ## Integration ### Initialisation Similar to the main Fluid Widget, `` component requires specific attributes to be initialised correctly. Please note that initialising one component will automatically prepare the other component for use, for improved performance. [Programmatic initialisation](https://docs.fluidpayments.io/docs/integration-manual/fluid-widget-integration#programmatic-init) can be used to initialise both components. ## Attributes Compared to the Fluid Widget, the **Fluid Quick Deposit** component is simpler and requires only the following attributes: - `operator-id` ** - `session-id` - `user-id` ** - `locale` ** - `currency` ** - `country` ** - `z-index` - `bonuses` *** - `deposit-limit` - `user-data` - `transaction-attributes` - `deposit-amount` For detailed explanations of these attributes, refer to [Fluid custom element attributes in detail](https://docs.fluidpayments.io/docs/integration-manual/fluid-widget-integration#fluid-custom-element-attributes-in-detail). ** Not required in case of [programmatic initialisation](https://docs.fluidpayments.io/docs/integration-manual/fluid-widget-integration#programmatic-init). *** Even if bonuses are not available during the quick deposit process, providing bonus data to the component serves performance purpose - bonuses will be processed just once and be available in the main Fluid Widget. ## Notifications The **Fluid Quick Deposit** component emits the same event types as the [Fluid Widget](https://docs.fluidpayments.io/docs/integration-manual/fluid-widget-integration#notifications-emitted-by-the-fluid-wallet) and introduces two additional events: - `fluid-info`: - `deposit-cta-clicked` – Triggered when a user clicks the "Deposit" button (displayed when no recent payment method is available). - `error-cta-clicked` – Triggered when an error occurs in the deposit flow and the user clicks the "Try Again" button. ## Example Implementation Below is an example of how to inject the **Fluid Quick Deposit** component into your website's DOM upon user login for automatic initialisation: ```html ``` For further details, refer to the documentation on [bonus data](https://docs.fluidpayments.io/docs/integration-manual/fluid-widget-integration#bonus-data-object) and [user data](https://docs.fluidpayments.io/docs/integration-manual/fluid-widget-integration#user-data-object) in the main widget [integration guide](https://docs.fluidpayments.io/docs/integration-manual/fluid-widget-integration). --- # Fluid Widget Integration > Source: https://docs.fluidpayments.io/docs/integration-manual/fluid-widget-integration ## Integration The Fluid Widget is implemented as a web component integrated into the host page DOM. By design, the Fluid widget [script](https://get.fluidpayments.io/index.js) should get injected into the host site **upon user authentication**, followed by either: - injecting `` web component into the DOM, providing required init attributes (Automatic Init) - calling `fluid.init` function with the init params object (Programmatic Init) ### Automatic Init This is the recommended way in most cases. The `` custom element expects several attributes required for initialisation (more on attributes [here](#fluid-custom-element-attributes-in-detail)). If the required initialisation parameters are provided at injection, the widget will automatically initialise and be ready for use. This initialisation should occur once per user session, immediately after user authentication. A [notification](#notifications-emitted-by-the-fluid-wallet) will indicate that the widget is ready for opening - it **should not be allowed to open before this notification is emitted**. Once the session ends, the widget should be removed from the DOM to ensure proper shutdown. ### Programmatic Init This method is recommended if the widget is embedded in an element rendered on open, injected many times. If your website injects the Fluid component multiple times during a user session, ensure the widget is initialised upon user authentication. To do this, call the global `fluid.init` function with the necessary payload immediately after downloading the Fluid script. This function accepts an instance of the FluidInitParams type, available in the [`@fluidpayments/types`](https://www.npmjs.com/package/@fluidpayments/types) package. Unless it's specifically intended, `fluid.init` should be called only once per user session and to update widget parameters, use the [reactive attributes](#observed-reactive-attributes). ```ts type FluidInitParams = { operatorId: number; userId: string; sessionId: string; locale: string; countryCode: string; currencyCode: string; bonuses?: FluidBonusData; userData?: FluidUserData; overscroll-behavior-auto?: boolean; } ``` Then on injecting the widget component provide only the reactive parameters, like `transaction`, `open`, `balance`, `withdrawable-balance`, `bonuses`, `deposit-limit`, `success-cta-link` and `session-id`. **Note:** if `bonuses` data doesn't change the widget won't process it again on inject, same with `session-id` - if it's the same as provided to the init function, the widget won't re-initialise. Otherwise, if any of the required init parameters change, the widget will re-initialise itself on inject. **Validation:** `fluid.init` validates `locale` before initialising. POSIX-style underscores are normalised (`en_GB` is accepted as `en-GB`); if the resulting value is still not a valid IETF BCP 47 tag, the returned promise rejects with an `Error` whose `message` describes the offending value. This differs from the HTML-attribute path, which falls back to `en` and emits a `fluid-error` event instead — programmatic callers are expected to surface the failure explicitly. **Warning:** Only one Fluid Widget custom element should be present in the DOM, otherwise unexpected behaviour may occur. ## Fluid custom element attributes in detail Fluid widget setup expects a list of parameters to properly configure itself for an authenticated user: - `operator-id` - unique identifier of the host site / operator \*\* - `session-id` - up-to-date session code of the currently authenticated user \*\* - `user-id` - identifier of currently authenticated user \*\* - `user-data` - details of currently authenticated user of type `FluidUserData` \*\* - `locale` - locale tag according to IETF BCP 47 (e.g. `en-NZ` or `es-MX`), with `en` (default English) and `ar` (default Arabic) being an exception \*\*. POSIX-style underscores are normalised automatically (`en_GB` is accepted as `en-GB`). If the value is still invalid after normalisation, the widget falls back to `en` and emits a `fluid-error` event with message `invalid-init-attributes`. - `country` - country of currently authenticated user in ISO 3166-1 Alpha-3 format \*\* - `currency` - currency code according to ISO 4217 \*\* - `transaction` - _deposit_ | _withdrawal_ | _quick-deposit_ - `lock-transaction-type` - When true, the user cannot switch from the current transaction type. - `open` - _true_ or _false_ - `balance` - current user balance in given currency - `withdrawable-balance` - amount available to withdraw - `bonuses` - stringified bonus data, structure described below - `deposit-limit` - responsible gaming deposit limit - `success-cta-link` - link for the CTA button after a successful transaction - `z-index` - use a value high enough to display the wallet in front of other elements on the host site - `turned-over-percentage` - percentage of the turned over amount. If none is provided the information will not be displayed - `transaction-attributes` - a stringified JSON object of key-value pairs that will be sent to the payment provider as transaction attributes together with the user agent and bonus code (if applicable) - `deposit-amount` - the amount that will be pre-filled for the user in deposit. It takes precedence over the configured ones and should be unset for bringing back the default behaviour - `prefilled-bonus-code` - pre-fills the manual bonus code input field - `two-factor-auth-enabled` - when `"true"`, adds a 2FA verification step to the withdrawal flow. See [verify2FA](https://docs.fluidpayments.io/docs/integration-manual/bridge-api#verify2fa) - `overscroll-behavior-auto` - when added, the parameter will allow to set `overscroll-behavior` to `auto` for the [inline version](https://docs.fluidpayments.io/docs/backoffice-guide/settings/overview#embedded-within-as-inline-elements) of the cashier. - `withdrawal-warning` - a stringified JSON object that displays a custom warning message on the withdrawal input screen, optionally with an action CTA. See [Withdrawal Warning](#withdrawal-warning) below for the object shape, examples and the emitted event. \*\* Mandatory for Automatic Init The `operator-id` value must correspond to the Payment Operator Config property value. This value is provided by Fluid Payments. ### Observed (reactive) Attributes The following attributes are observed by the widget and change in their value on the host site causes a reaction/event within the wallet. - `open` - triggers the wallet to become visible or hidden - `balance` and `withdrawable-balance` - update withdrawal information - `session-id` - assures consistently valid user session Other reactive attributes are observed only while the wallet is closed: - `transaction` - updates transaction type - `lock-transaction-type` — locks the transaction type, preventing the user from switching between Deposit and Withdrawal - `bonuses` - updates bonuses information - `deposit-limit` - updates responsible gaming deposit limit amount - `user-data` - updates user data for resolving Suggested Deposit Amounts, Payment Methods Order and KYC status - `success-cta-link` - sets the link to follow on successful transaction - `turned-over-percentage` - sets the turned over percentage - `transaction-attributes` - updates transaction attributes sent with each transaction request - `prefilled-bonus-code` - pre-fills the manual bonus code input field. Requires `manualBonusCodesEnabled` to be enabled in operator configuration. The code is not auto-validated; the user must click "Apply" to trigger verification via the [Bridge API](https://docs.fluidpayments.io/docs/integration-manual/bridge-api#verifybonuscode) - `two-factor-auth-enabled` - when set to `"true"`, adds a 2FA verification step to the withdrawal flow. The user must enter a 6-digit authenticator code before the withdrawal is submitted. Code validation is handled via the [Bridge API](https://docs.fluidpayments.io/docs/integration-manual/bridge-api#verify2fa). This is a per-player flag — the host evaluates whether the player has 2FA enabled and sets it accordingly - `withdrawal-warning` - updates the custom warning message displayed on the withdrawal input screen Note that there won't be any reaction to changes of those attributes while the wallet is open. This is to assure integrity of user's experience and that the transaction flow is not interrupted by any changes on the host site. ## Notifications emitted by the Fluid Wallet In addition to receiving information from the host site, the Fluid wallet emits information out to the host website using `CustomEvent` (https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent), with the `detail` property containing the information. This property is an object with the following structure, also available as a type in the [`@fluidpayments/types`](https://www.npmjs.com/package/@fluidpayments/types) package as `FluidNotificationDetail` ```ts type FluidNotificationDetail = { message: string; [key: string]: any; }; ``` `message` contains a string with the different event types listed below. Add the following code to receive those events: ```ts fluid.addEventListener("fluid-command", onFluidCommand); fluid.addEventListener("fluid-info", onFluidInfo); fluid.addEventListener("fluid-error", onFluidError); ``` - `fluid-info` - messages of informational nature, with the purpose of e.g. tracking or allowing user action - `fluid-error` - unexpected failure notifications - `fluid-command` - commands to react to Possible values of those types can be expected to be: - `fluid-info`: - _initialised_ - wallet has been prepared for opening - it should not be allowed to open before this is emitted - _opened_ - the wallet has been opened - _destroyed_ - the wallet instance has been terminated - _internal-operation-change_ - transaction flow has been amended internally, e.g. upon withdrawal without a positive withdrawable balance - _success-cta-click_ - user clicked on the CTA shown on the transaction success screen - _deposit-success_ - when a successful deposit is made - _deposit-failure_ - deposit attempt failed - _error-cta-clicked_ - user clicked on the CTA shown on the transaction failure screen - _withdrawal-success_ - when a successful withdrawal is made - _withdrawal-failure_ - withdrawal attempt failed - _withdrawal-cancelled_ - when a withdrawal is cancelled - _contact-support_ - user clicked on the Contact Support link shown on transaction failure screen - _bonus-changed_ - user changed selected deposit bonus - _payment-method-changed_ - user changed the selected payment method - _dialog-opened_ - a dialog has been opened from the wallet - _dialog-closed_ - a dialog has been closed from the wallet - `fluid-error`: - _initialisation-failure_ - Fluid wasn’t able to configure itself, e.g. due to a network or backend issue - _operation-execution-failure_ - an operation failed unexpectedly due to an error - _invalid-bonus-data_ - the bonus data is not in the correct format expected - _invalid-user-data_ - the user data is not in the correct format expected - _invalid-transaction-attributes_ - the transaction attributes are not in the correct format expected - _invalid-init-attributes_ - an init attribute (currently the `locale`) failed validation; the widget falls back to a safe default (`en` for `locale`) and keeps initialising. When the widget is initialised programmatically via `fluid.init(...)`, the call rejects with an error instead (see [Programmatic Init](#programmatic-init) above). - _invalid-withdrawal-warning_ - the `withdrawal-warning` attribute could not be parsed as JSON. The widget renders no warning until the attribute is corrected. See [Withdrawal Warning](#withdrawal-warning). - `fluid-command`: - _close_ - user selected to close the wallet from within, the `open` attribute should be set to _false_ - _handle-transaction_ - when deposit or withdrawal is to be handled outside of Fluid - _start-kyc-verification_ - when the user clicks on the Verify button in the fluent message - _withdrawal-warning-cta-clicked_ - user clicked the CTA shown in the configured withdrawal warning. The host should react accordingly (for example, navigate the user to the bonuses screen). See [Withdrawal Warning](#withdrawal-warning). Note that `fluid-info`notifications are not primarily designed for tracking, although some carry detailed information on the event, e.g. `payment-method-changed`, `bonus-changed` and all transaction result ones include `activityId`, representing unique user interaction with the wallet, which allows for stitching those events with a particular transaction id. For cases where the widget needs to request data or trigger an action on the host page and receive a typed response, see the [Window Bridge API](https://docs.fluidpayments.io/docs/integration-manual/bridge-api). ## Example code The following is an example of what's to be injected to your website DOM upon user login for Automatic Init: ```html ``` It should stay present in the DOM for the time of user session. Initial mandatory attributes are: `operator-id`, `session-id`, `user-id`, `user-data`, `country`, and `locale`. ## Bonus Data Object The structure containing sample data (type of `FluidBonusData` available in the [`@fluidpayments/types`](https://www.npmjs.com/package/@fluidpayments/types) package) is as follows: ```ts const bonusData = [{ "code": "DepositBonus", "title": "Deposit Bonus", "description": "100% up to 200€ + 10 Mega Spins", "logoUrl": "https://.com/assets/img/rewards/bonus-img/deposit-bonus.png", "maxBonus": 200, "maxBonusPercentage": 150, "minDeposit": 10, "maxDeposit": 250; "minDepositCount": 2; "maxDepositCount": 10; "minDaysSinceRegistration": 25; "maxDaysSinceRegistration": 180; "selected": true, "termsAndConditions": "Welcome Offer Terms And Conditions 1...", "paymentMethodFilter": { "applyTo": [ { "providerType": "CREDITCARD" }, { "providerType": "WEBREDIRECT", "service": "BLIXTPAY" } ], "excludeFrom": [ { "providerType": "JETON" } ] } }] ``` _Figure 4 - Definition of Bonuses Passed to the Fluid Widget (Example)_ - The `termsAndConditions` of the bonus should be provided as an HTML string. - The `logoUrl` represents the URL of the bonus image\*. If `logoUrl` is absent or the path is 404, a fallback image will be used. This fallback image has to be set from the CMS's theme. - Bonus codes will be available for all payment methods unless a `paymentMethodFilter` is specified. - If a `paymentMethodFilter` is used, the bonus is applied depending on the properties set. - If `applyTo` is set then the bonus only would apply to those listed payment methods. - If `excludeFrom` is set then the bonus won’t apply to those payment methods. - `providerType` is sufficient if the payment method does not have a `service`. Both values should be provided exactly as in Payment Provider configuration - `maxBonus` and `maxBonusPercentage` are not mandatory. - `maxBonusPercentage` requires a `maxBonus` value. - `minDeposit` is an optional property indicating the minimum deposit amount required for the bonus. - `maxDeposit` is an optional property indicating the maximum deposit amount required for the bonus. - `minDaysSinceRegistration` is an optional property indicating the minimum days since player registration required for the bonus. - `maxDaysSinceRegistration` is an optional property indicating the maximum days since player registration required for the bonus. - If there is a `maxBonus` but no `maxBonusPercentage`, it is assumed that `maxBonusPercentage` is 100% (examples of bonus calculations can be found in [the deposit example section](https://docs.fluidpayments.io/docs/integration-manual/how-fluid-works#example-transaction-1-deposit)). - `selected` is an optional property indicating the bonus should be preselected. If more than 1 bonus is set to true a bonus configuration error will be thrown. \*Bonus logo image size should be 84x84px (168px168px for retina) ## User Data Object Used for resolving Suggested Deposit Amounts and Payment Methods Order with use of Machine Learning based on historical transactions' data. The structure, available as `FluidUserData` type in the [`@fluidpayments/types`](https://www.npmjs.com/package/@fluidpayments/types) package, is as follows: ```ts type FluidUserData = { age?: number; affiliateId?: string; depositCount?: number; daysSinceRegistration?: number; fullName?: string; kycStatus?: FluidKycStatus; lifetimeDeposit?: number; previousDeposit?: number; tags?: string[]; }; ``` All the properties are optional. ## Withdrawal Warning The `withdrawal-warning` attribute lets you surface a custom notice on the withdrawal input screen, for example, when an active bonus must be reviewed or cancelled before the player can withdraw. The warning appears in the initial (pre-focus) state of the amount input and is dismissed once the player focuses the input. The attribute is observed while the wallet is closed: updating it then replaces the rendered warning the next time the wallet is opened. The attribute value is a JSON string with the following shape: ```ts type WithdrawalWarning = { title: string; // required, shown as the heading message?: string; // optional body text ctaLabel?: string; // optional; when set, renders a CTA button. Clicking emits `withdrawal-warning-cta-clicked` (fluid-command) }; ``` Field rules: - `title` is required. If it is missing, the warning is silently not shown. - `message` and `ctaLabel` are optional and independent. `ctaLabel` works with or without a `message`. - When `ctaLabel` is set, a primary CTA button is rendered under the message. Clicking it emits a `fluid-command` event with `message: "withdrawal-warning-cta-clicked"`. Use this to react on the host page (for example, navigate the player to the bonuses screen). - If the attribute value is not valid JSON, the widget emits an `invalid-withdrawal-warning` `fluid-error` event and renders no warning. Minimal example — title and message only: ```html ``` With an action CTA: ```html ``` ## Manual Bonus Codes When the **Manual Bonus Codes** feature is enabled in the CMS (`Manual Bonus Codes Enabled`), the widget displays a text input allowing the user to enter a bonus code manually. The widget validates the code using the `verifyBonusCode` [Bridge API](https://docs.fluidpayments.io/docs/integration-manual/bridge-api) method. ### Enabling the feature The feature is controlled by the `Manual Bonus Codes Enabled` setting in the Fluid CMS. When enabled, a bonus code input field appears in the deposit flow alongside the regular bonus list. ### Bridge handler The host page must register a `verifyBonusCode` handler as described in the [Window Bridge API](https://docs.fluidpayments.io/docs/integration-manual/bridge-api) documentation. The handler receives `{ code: string }` (the trimmed user input) and must return a `FluidBridgeVerifyBonusCodeResponse`: - When `status` is `'valid'`, the `bonus` object must conform to the same structure as entries in the [Bonus Data Object](#bonus-data-object) — including optional `paymentMethodFilter`, `logoUrl`, and `termsAndConditions`. - When `status` is `'invalid'`, the widget displays an error message to the user. - Optionally, return `autoOptedIn: true` on a valid response to control the post-validation bonus UX. See [`autoOptedIn` behaviour](https://docs.fluidpayments.io/docs/integration-manual/bridge-api#autooptedin-behaviour) for the full behaviour table. ## CSS ### Font The `font-family` used by the widget will inherit from its parent element, ensuring consistency with the host site's typography. If another font is desired, it can be set on the parent element of the ``. The widget uses [three different font weights](https://docs.fluidpayments.io/docs/backoffice-guide/theme#font-weight), so the font-family should include all of them. --- # Framework integrations > Source: https://docs.fluidpayments.io/docs/integration-manual/framework-integrations ## React While React is yet to improve their Web Component support in version 19 (https://github.com/facebook/react/issues/11347#issuecomment-1122275286) the current solution requires a simple workaround to assure critical Widget parameters are set on init. The Widget wrapper and `useEffect`: ```jsx let scriptLoaded = false; function FluidWrapper({ open, transaction, bonuses, onInfo, onCommand, onError }) { const ref = useRef(null); useEffect(() => { let script; if (window && document && !scriptLoaded) { script = document.createElement('script'); script.src = 'https://get.fluidpayments.io/index.js'; script.onload = () => { console.log('Fluid script loaded'); }; document.head.appendChild(script); scriptLoaded = true; } return () => { if (script) { script.remove(); } }; }, []); useLayoutEffect(() => { const fluid = ref.current; fluid.addEventListener('fluid-command', onCommand); fluid.addEventListener('fluid-info', onInfo); fluid.addEventListener('fluid-error', onError); return () => { fluid.removeEventListener('fluid-command', onCommand); fluid.removeEventListener('fluid-info', onInfo); fluid.removeEventListener('fluid-error', onError); } }, [onCommand, onError, onInfo, ref]); return ( ); } ``` Mind the `scriptLoaded` is there to prevent React from loading the Widget script twice on render. An example of possible integration use: ```jsx function App() { const [open, setOpen] = useState(false); const [transaction, setTransaction] = useState('deposit'); const [numberOfBonuses, setNumberOfBonuses] = useState(bonuses.length); function deposit() { setTransaction('deposit'); setOpen(true); } function withdraw() { setTransaction('withdrawal'); setOpen(true); } function quickDeposit() { setTransaction('quick-deposit'); setOpen(true); } function close() { setOpen(false); } function onCommand(event) { console.info(`%cFluid COMMAND: ${event.detail}`, 'color: lightgreen', event); if (event.detail === 'close') { close(); } } function onInfo(event) { console.info(`%cFluid INFO: ${event.detail}`, 'color: cornflowerblue', event); } function onError(event) { console.error(`Fluid ERROR: ${event.detail}`, event); } function changeNumberOfBonuses() { const newNumberOfBonuses = numberOfBonuses - 1 < 0 ? 3 : numberOfBonuses - 1; setNumberOfBonuses(newNumberOfBonuses); console.log('Number of bonuses set to', newNumberOfBonuses); } return ( <>

Fluid Fluid

) } ``` Complete code of the POC: https://github.com/soltechno/fluid-react-integration --- # How Fluid Works > Source: https://docs.fluidpayments.io/docs/integration-manual/how-fluid-works ## Example Transaction 1: Deposit When depositing funds, the user may have payment methods stored (e.g. credit card, ewallet etc), along with the associated details stored. This enables a user to choose one or their preferred payment methods and deposit funds seamlessly. In addition to the previously stored payment methods, various other methods can be presented to the user should they wish to use a new method (stored after using it for the first time). The wallet can customise the ordering of the stored and new payment methods. Each payment method has its own minimum deposit and maximum deposit limits. Each method also has its own set of bonuses that can be used with the method. The figure below gives an example of how the fluid-widget element may appear in the rendered html for a transaction deposit. Once the user is authenticated on the host site, they are identified by the the user-id attribute. Data relating to the language used , currency, user balance etc are passed in and determine the appearance of the wallet, as illustrated below. The various steps shown in this example are for a user depositing **100€** using a credit card. Note the bonuses data is passed in as a stringified array of json bonus objects. This is detailed in the following section “Bonuses”. ![Deposit user journey](https://docs.fluidpayments.io/img/integration-manual/how-fluid-works/deposit-user-journey.png) _Figure 1 - Example User Journey for a Deposit_ The maxBonus property defines the maximum bonus amount that can be claimed. For example, in the image below showing the preselected bonus, the maxBonus amount would be **150€**. The maxBonusPercentage property defines the multiple applied to the amount deposited by the user to calculate the bonus amount added. This multiple is expressed as a percentage. For example, if the maxBonusPercentage is **150%** and the user deposits **50€**, then the bonus amount would be **75€** *(50 x 150% = 75).* As a second example, if the maxBonusPercentage is **100%** and the user deposits **200€,** the bonus amount would be **200€** *(200 x 100% = 200).* In the image below, the maxBonusPercentage is **100%**, hence the text ***“100% up to 150€ + …”*** for the login bonus. A specific bonus can be preselected by setting `"selected": true` on the corresponding entry in the `bonuses` array (see the [Bonus Data Object](https://docs.fluidpayments.io/docs/integration-manual/fluid-widget-integration#bonus-data-object)). The preselected bonus must be part of the `bonuses` array passed to the widget. The `bonuses` attribute is observed, so the preselection can be changed after the wallet has loaded. Preselection is useful when the user is referred to the operator with a specific bonus offer, for example. ![Preselected bonus](https://docs.fluidpayments.io/img/integration-manual/how-fluid-works/preselected-bonus.png) _Figure 2 - Example of a Preselected Bonus_ ## Example Transaction 2: Quick Deposit For quick deposits, the user can deposit funds with the least effort simply by entering say CVC number and deposit amount. The figure below gives an example of how the fluid-widget element may appear in the rendered html for a quick deposit. Note the transaction attribute value is “quick-deposit”. As before, the various attribute values determine the various settings of the wallet, tailored to the user. ![Quick Deposit: Step 1](https://docs.fluidpayments.io/img/integration-manual/how-fluid-works/quick-deposit-step-1.png) _Figure 3 - Quick Deposit: Step 1_ ## Example Transaction 3: Withdrawal The figure below shows the Fluid Wallet for a withdrawal transaction. Note in this example, the withdrawable balance of **900€** is passed in as property and displayed in the initial screen presented to the user. ![Withdrawal: Step 1](https://docs.fluidpayments.io/img/integration-manual/how-fluid-works/withdrawal.png) _Figure 4 - Withdrawal: Step 1_ ## Responsible Gaming Limit The wallet enables responsible gaming limits to be defined and when applicable, the max deposit amount is adjusted amount on step 1. Each payment had its own maximum deposit amount, however when the responsible gaming is below this limit, the maximum deposit is limited to this value. For example, in the figure below the responsible gaming limit is set at **220€** (shown as Max: €220). If the user enters an amount exceeding this limit, the text is highlighted red and the fluent box displays the limit set by responsible gaming. ![Responsible Gaming Limit](https://docs.fluidpayments.io/img/integration-manual/how-fluid-works/responsible-gaming-limit.png) _Figure 5 - Responsible Gaming Limit_ --- # Integrating with AI > Source: https://docs.fluidpayments.io/docs/integration-manual/integrating-with-ai The Fluid public documentation is also available in an AI-friendly form following the [llmstxt.org](https://llmstxt.org) standard. AI coding assistants (Cursor, Claude, ChatGPT and others) can read these files directly to answer questions about embedding the Fluid Cashier or configuring it from the back office. Two files are published: - **Index** — [`https://docs.fluidpayments.io/llms.txt`](https://docs.fluidpayments.io/llms.txt) — a short list of every public page with a one-line summary and link. - **Full text** — [`https://docs.fluidpayments.io/llms-full.txt`](https://docs.fluidpayments.io/llms-full.txt) — every public page concatenated into a single Markdown file. ## How to use them - **In a chat assistant** — paste either URL into the conversation and ask your question. Most AI assistants will fetch and ingest the file. - **In a developer tool** (e.g. Cursor, Claude Code, Codex) — add the URL as documentation context, or download `llms-full.txt` and reference it from your prompt. - **In an automated pipeline** — fetch `llms.txt` to discover available pages, then fetch individual pages as needed. ## Caveat AI answers are only as accurate as the documentation they are given, and Fluid's product evolves over time. Always verify integration steps against the live documentation and your operator-specific configuration before shipping. --- # Operator Configuration > Source: https://docs.fluidpayments.io/docs/integration-manual/operator-configuration ## Transaction Result Callbacks The transaction result callback URLs are defined in DatoCMS, on the **Payment Gateway** model in the **Callback Urls** section. Set the Success, Pending, Cancel and Failure callback URL fields to the Fluid transaction result URL for each outcome (`state=SUCCESS`, `state=PENDING`, `state=CANCELLED`, `state=FAILED`). Fluid completes the per transaction values automatically, delivers each result back to the user and forwards it to your platform where required. ## Fluid Wallet Content defined by the Operator Much of the content of the fluid wallet can be customised by the operator. Such content includes visual elements like the colour theme of the wallet, the style of the buttons etc. Other content defined by the operator includes certain text that is displayed in the various pages and modal boxes that are presented to the user. Currently, this is retrieved from a DatoCMS database. The image below shows examples of text content displayed in the wallet, some of which are taken from the wallet in a dark colour theme. ![Text content customized](https://docs.fluidpayments.io/img/integration-manual/operator-configuration/fluid-content-defined-by-the-operator.png) _Figure 1 - Example Text Content at various Steps in the Fluid Wallet_ ## Fluid Wallet Behaviour Defined by the Operator Following a successful transaction, the user is notified in the final step with the amount being deposited or withdrawn, as shown below. The exact text displayed on the buttons (indicated 1,2,3) can be configured by the operator. The operator can also define what action is performed when the user clicks on this button **Play now** e.g. the user may be taken to the home screen of the operator or simply have the wallet close with the user returning to the screen from which the wallet was opened. ![Final Step Notification](https://docs.fluidpayments.io/img/integration-manual/operator-configuration/fluid-behaviour-defined-by-the-operator.png) _Figure 2 - Example Final Step Notification_ In a similar manner to above, the buttons **Try again** and **Contact support** can be configured by the operator. ![Example Transaction Failure Cases](https://docs.fluidpayments.io/img/integration-manual/operator-configuration/errors.png) _Figure 3 - Example Transaction Failure Cases_ ## Fluid Wallet Content Defined by the Operator ### Theme One of Fluid's strengths is the possibility of matching the wallet style with the host(casino). The wallet can follow the new [casino theme](https://docs.fluidpayments.io/docs/backoffice-guide/theme) for a specific event, like Xmas. ### Content Set The translations used by the wallet. The copy could be selected to fit the theme. For example, the tone of voice of the fluent box could be different for Xmas. --- # Window Bridge API > Source: https://docs.fluidpayments.io/docs/integration-manual/bridge-api The Window Bridge API provides a request/response communication channel between the Fluid widget and the host page. It complements the existing [one-way event model](https://docs.fluidpayments.io/docs/integration-manual/fluid-widget-integration#notifications-emitted-by-the-fluid-wallet) for cases where the widget needs to ask the host page for data and await a typed response. ## Events vs. Bridge | Use case | Mechanism | |---|---| | Widget notifying the host that something happened | DOM `CustomEvent` (`fluid-info`, `fluid-command`, `fluid-error`) | | Widget requesting data or an action from the host and awaiting a typed response | `window.fluid.bridge.handleRequest(...)` | ## How the method name connects both sides The method name string is the shared key between the widget and your page. Your handler must be registered under **exactly the same name** that the widget uses when it calls that method. If the names do not match, the request rejects immediately with `BRIDGE_HANDLER_NOT_FOUND`. ## Registering a handler The host page registers a handler by calling `window.fluid.bridge.handleRequest(methodName, handler)`. This should be done **before** the widget needs the data — typically right after the Fluid script is loaded. Bridge handlers must be registered **after** the Fluid script has finished executing, otherwise `window.fluid.bridge` is `undefined`. See [Script loading for bridge usage](#script-loading-for-bridge-usage) below for both inline and programmatic loading patterns. ```ts window.fluid.bridge.handleRequest('verifyBonusCode', async ({ code }) => { const result = await myApi.verifyBonusCode(code); if (!result.valid) { return { status: 'invalid' }; } return { status: 'valid', bonus: result.bonus, autoOptedIn: result.autoOptedIn }; }); ``` Calling `handleRequest` again with the same method name silently replaces the previous handler. ## Defining the typed contract Bridge method names and their request/response shapes are defined by augmenting the `FluidBridgeContract` interface from the [`@fluidpayments/types`](https://www.npmjs.com/package/@fluidpayments/types) package in your host application. `@fluidpayments/types` ships response types for each bridge method: ```ts import type { FluidBridgeVerifyBonusCodeResponse, FluidBridgeVerify2FAResponse } from '@fluidpayments/types'; declare module '@fluidpayments/types' { interface FluidBridgeContract { verifyBonusCode: { request: { code: string }; response: FluidBridgeVerifyBonusCodeResponse; }; verify2FA: { request: { code: string }; response: FluidBridgeVerify2FAResponse; }; } } ``` This gives you compile-time safety: your handler signature will be typed according to the contract you define. ## Timeout and errors All bridge requests have a fixed timeout of **5000ms**. If the handler does not respond within that time, or if no handler has been registered, the returned promise rejects with a `FluidBridgeError` object: ```ts type FluidBridgeError = { code: 'BRIDGE_HANDLER_NOT_FOUND' | 'BRIDGE_TIMEOUT' | 'BRIDGE_HANDLER_ERROR'; message: string; details?: unknown; // present for BRIDGE_HANDLER_ERROR — contains the original thrown value }; ``` | `code` | Cause | |---|---| | `BRIDGE_HANDLER_NOT_FOUND` | No handler has been registered for the requested method | | `BRIDGE_TIMEOUT` | The handler did not resolve within 5000ms | | `BRIDGE_HANDLER_ERROR` | The handler threw or returned a rejected promise | ## Available methods List of bridge methods that the Fluid Widget may invoke. You only need to register handlers for the methods your integration uses. ### `verifyBonusCode` Validates a manual bonus code entered by the user. The widget invokes this method when the user clicks "Apply" in the manual bonus code input. **Required when** the `manualBonusCodesEnabled` operator configuration flag is enabled. If the flag is enabled but no handler is registered, the widget will show a validation error after the 5000ms timeout. #### Request payload ```ts { code: string } ``` | Field | Type | Description | |---|---|---| | `code` | `string` | The bonus code the user entered (trimmed) | #### Response payload ```ts type FluidBridgeVerifyBonusCodeResponse = { status: 'valid' | 'invalid'; bonus?: FluidBonusData; autoOptedIn?: boolean; }; ``` | Field | Type | Required | Description | |---|---|---|---| | `status` | `'valid'` \| `'invalid'` | Yes | Whether the code is valid | | `bonus` | `FluidBonusData` | When `status` is `'valid'` | The bonus details to display | | `autoOptedIn` | `boolean` | No | Controls whether the user is automatically opted into the bonus. Defaults to `false` when omitted | The `bonus` object follows the same `FluidBonusData` shape used in the `bonuses` attribute: ```ts { code: string; title: string; description: string; logoUrl?: string; termsAndConditions?: string; minDeposit?: number; maxDeposit?: number; maxBonus?: number; maxBonusPercentage?: number; paymentMethodFilter?: string[]; } ``` #### `autoOptedIn` behaviour When `autoOptedIn` is `true`, the user is automatically opted into the validated bonus without needing to confirm via the bonus selection UI. When `autoOptedIn` is `false` or absent, the user must confirm their bonus selection — for stored-methods users the bonus list modal auto-opens after validation. | Flow | `autoOptedIn` | Behaviour | |---|---|---| | First-time depositor (no stored methods) | `false` / absent | Default — bonus shown on the bonus selection step; user confirms before proceeding | | First-time depositor (no stored methods) | `true` | Bonus selector card shown on step 1, bonus step skipped | | Stored methods | `true` | Default — works as before | | Stored methods | `false` / absent | Bonus list modal auto-opens after validation | #### Example ```ts // Register the verifyBonusCode handler once after the Fluid script loads window.fluid.bridge.handleRequest('verifyBonusCode', async ({ code }) => { const result = await myApi.verifyBonusCode(code); if (!result.valid) { return { status: 'invalid' }; } return { status: 'valid', bonus: { code: result.code, title: result.title, description: result.description, logoUrl: result.logoUrl, termsAndConditions: result.termsAndConditions, minDeposit: result.minDeposit, maxBonus: result.maxBonus, maxBonusPercentage: result.maxBonusPercentage, paymentMethodFilter: result.paymentMethodFilter, }, autoOptedIn: result.autoOptedIn, }; }); ``` ### `verify2FA` Validates a 6-digit authenticator code entered by the user during the withdrawal flow. The widget invokes this method when the user clicks "Verify code" in the 2FA verification step. **Required when** the `two-factor-auth-enabled` attribute is set to `"true"` on the widget element. If the attribute is enabled but no handler is registered, the widget will show a validation error after the 5000ms timeout. #### Request payload ```ts { code: string } ``` | Field | Type | Description | |---|---|---| | `code` | `string` | The 6-digit authenticator code the user entered | #### Response payload ```ts type FluidBridgeVerify2FAResponse = | { status: 'valid' } | { status: 'invalid' } | { status: 'rate_limited'; retryAfterMs?: number }; ``` | Field | Type | Required | Description | |---|---|---|---| | `status` | `'valid'` \| `'invalid'` \| `'rate_limited'` | Yes | The verification result | | `retryAfterMs` | `number` | No | Milliseconds before the user can retry. Only used when `status` is `'rate_limited'`. The widget shows a countdown and auto-re-enables the input after this period. The `{seconds}` placeholder in the rate limit content key is interpolated from this value | #### Example ```ts // Register the verify2FA handler once after the Fluid script loads window.fluid.bridge.handleRequest('verify2FA', async ({ code }) => { const result = await myApi.verify2FA(code); if (result.valid) { return { status: 'valid' }; } if (result.rateLimited) { return { status: 'rate_limited', retryAfterMs: result.retryAfterMs }; } return { status: 'invalid' }; }); ``` ## Script loading for bridge usage Bridge handlers must be registered **after** the Fluid script has finished executing. There are two common loading patterns: ### Inline ` ``` ### Programmatic loading When loading the script dynamically (common in SPA / framework integrations), register handlers in the `onload` callback: ```js const script = document.createElement('script'); script.src = 'https://get.fluidpayments.io/index.js'; script.onload = () => { // window.fluid.bridge is guaranteed to exist here window.fluid.bridge.handleRequest('verifyBonusCode', async ({ code }) => { // ... }); }; document.head.appendChild(script); ``` Do **not** set `script.async = true` — async loading defers execution, so `window.fluid.bridge` may not exist when your `onload` callback runs. For framework-specific examples (e.g. React `useEffect`), see [Framework integrations](https://docs.fluidpayments.io/docs/integration-manual/framework-integrations). ### Defensive fallback: queue-drain shim If your integration cannot guarantee that handler registration happens after the script loads (e.g. handlers are registered at module scope in a bundled app), you can install a lightweight shim **before** loading the Fluid script: ```html ``` On init the widget captures any queued `handleRequest` calls and replays them into the real handler registry. This is a defensive fallback — the recommended approaches are the inline `