Window 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 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.
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 package in your host application.
@fluidpayments/types ships FluidBridgeVerifyBonusCodeResponse for the bonus code verification method, which uses the existing FluidBonusData item shape for the verified bonus payload:
import type { FluidBridgeVerifyBonusCodeResponse } from '@fluidpayments/types';
declare module '@fluidpayments/types' {
interface FluidBridgeContract {
verifyBonusCode: {
request: { code: string };
response: FluidBridgeVerifyBonusCodeResponse;
};
}
}
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:
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
{ code: string }
| Field | Type | Description |
|---|---|---|
code | string | The bonus code the user entered (trimmed) |
Response payload
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:
{
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
// 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,
};
});
Limitations
- There is no per-request timeout configuration — the 5000ms timeout applies to all methods.
- The handler registry is shared across all widget instances on the page. If more than one Fluid widget element is present simultaneously, they share the same handlers.