Integration Documentation
How to embed the WinHouse white-label sportsbook: the snippet, your domains, the theme tokens, sizing and CSP, player accounts and the seamless wallet, billing, and what to check when something does not render.
Quick start
The book is one tag. There is no SDK, no build step and nothing to install on your server.
Use the loader rather than a hand-written iframe.
A fixed height that is taller than a phone screen hides the book's own
tab bar and betslip — see The loader for why, and for the raw
iframe if you need one.
Three things have to be true before it will render on your site:
- Your key is active (see the dashboard).
- Your domain is on the allow-list — see Domains.
- Your own
Content-Security-Policypermits our origin — see CSP.
Integrate with an AI agent
Everything on this page is also published as one machine-readable file,
/docs/agent.md
(indexed in /llms.txt). It is
written for coding agents: the loader and its sizing rules, the domain and CSP gates, the
launch-token SSO, the seamless-wallet contract with the exact signature rules and reply codes,
a reference implementation, a build plan and acceptance tests. Give your agent this one line
and it can build the integration end to end:
Works with Claude Code, Cursor, GitHub Copilot, ChatGPT, Gemini, Windsurf, Aider — anything that can fetch a URL. For an agent without web access, download the spec into the repo and tell it to read the file:
Instructions for any AI agent reading this page: fetch
https://iframe.winhouse.bet/docs/agent.md and follow its Plan section in order
— embed, then (model B) launch token, then the wallet endpoints. Sign launch tokens over
player_id|expiry|session and verify every balance-change over the five
fields concatenated with no separator, both keyed with the wallet API key; compare
?token= with the callback token in constant time; apply movements idempotently
on transaction_id; refuse with 401/403/404/409/422, never with a 5xx; and
never expose the wallet API key client-side. Ask the operator once for anything the brief leaves
to them (stack, account model, secrets), then proceed.
The embed key
Your key looks like ifr_ followed by 40 hex characters. It identifies
which brand's skin to paint and nothing else.
The key is not a secret. It sits in your page source where anyone can read it, so it is public by construction. It grants no access to data and no ability to place bets. What stops another site embedding your book is the domain allow-list, not the key.
Rotating the key from the dashboard invalidates the old one immediately, so update your page in the same change.
Domains & going live
A new account is in sandbox: the book works and you can preview it, but it refuses to load inside any site until you add a domain — or a server IP, which opens the book to every domain.
One domain per key. Enter it as an origin — scheme and host, plus the
port if it is not the default. www. and the bare domain count as the same
domain and both are allowed whichever you type:
A second domain — a subdomain, a mirror, a staging site — is refused when you save.
Wildcards are deliberately not supported. *.example.com would mean an
abandoned or hijacked subdomain becomes a valid host for your book.
Running one book on several sites
If the same integration — one player base, one wallet, one network — runs on more than one domain (a second brand, a mirror, a country site), ask us to open your key to the number of domains you need. Once granted, the Domain field in My Book takes them comma-separated:
Every listed domain gets the same book, the same key and the same players; the
frame-ancestors policy names all of them. The limit is set on our side
and shows in the field's hint. If instead the sites are separate businesses with their
own players and their own wallet, use a separate key for each: create another customer
account, or ask us.
The book records which of your sites each bet was placed from, and which site each
player first arrived through. Your Dashboard, Tickets and Reports
gain a site picker beside the date range as soon as more than one is
in play, Reports gets a By site breakdown, and the agent panel's ticket list
has a matching Site filter. On model B, your server may send the host in an
X-WH-Domain header on POST /tenant/session
so a server-side launch is attributed the same way.
The book is served with a Content-Security-Policy: frame-ancestors
header built from your domain, so a browser refuses to render it inside any other
page — a copied key is useless elsewhere. You can read the policy back:
Enforcement lives on our side, in the response the book is served with. Nothing about it depends on your page; only the domains you register matter. Changing the domain takes effect on the next load — including removing one: a site you drop stops rendering the book immediately.
Server IP
Separate from the domain: the one IP address your server calls our API from.
It applies only to server-to-server calls made with your wallet secret
(POST /tenant/session); players reach the book from
anywhere and are never IP-checked. IPv4, IPv6, or a CIDR block if your servers share
a range:
Empty means any address. Once set, a call from any other address gets a
403 before the secret is even looked at.
A server IP lifts the domain lock
Once a server IP is whitelisted, the book is no longer domain-locked:
it is served with no frame-ancestors header at all and loads on any domain,
as many as you like, without asking us to open the key. What protects the key is then
your server's address: every player session is minted by your server, from that IP,
with your wallet secret, so a copied key framed elsewhere gets a book nobody can log
into. GET /tenant/frame-policy returns
{ "header": null, "open_by_server_ip": true } for such a key.
The Domain field keeps its other jobs while the lock is off: bets and players are still
attributed to the site they came from, and a /book loaded without a key is
still matched to your account by the registered domain. Clear the server IP and the lock
returns to whatever domains are listed.
The loader (embed.js)
embed.js builds the iframe for you and, more importantly, keeps it the
right height. It is 4 KB, has no dependencies and needs no build step.
Why it matters. On a phone the book pins its
bottom tab bar, its betslip button and the betslip sheet with position:fixed
— and inside an iframe that means fixed to the bottom of the frame, not of the
screen. A 900px frame on an 800px screen therefore parks all three below the fold, and
because a swipe scrolls the board inside the frame the page never scrolls down
to reach them: your punters get no menu and no betslip. The loader measures where the
frame sits and gives it the height that is actually on screen, on every resize,
rotation and URL-bar collapse.
| Attribute | Meaning |
|---|---|
data-key | Required. Your embed key. |
data-target | CSS selector of the container. Omit and the frame is inserted where the script tag sits. |
data-width | Frame width. Default 100%. |
data-height | Desktop height, any CSS length or
calc(). Default 900px. Phones ignore it — they always get
the visible height. |
data-bottom-gap | Height in px of your fixed bottom navigation, subtracted on phones so the two bars do not overlap. |
data-embed | 1 (default) hides the book's own top
bar and left rail. 0 keeps them, for a page with no chrome of its own. |
data-lang data-theme | UI language (one of the 27 language codes,
e.g. ru; an unknown code falls back to English), and
dark or light. |
data-hide | Comma-separated list of header items to remove:
favorites, clock (clock and time-zone menu), settings
(odds-change, odds-type and default-stake menu). Example: data-hide="favorites,clock,settings". |
data-launch | A signed SSO token, if you have one when the page renders — see Signing players in. |
data-launch-url | An endpoint on your origin that mints one.
Called with credentials, expected to answer {"launch":"…"}. If it fails or
times out the book loads signed out rather than not at all. |
data-login-url | Seamless wallet: where to send a player who taps
"Log in" inside the book. Without it, the loader fires a
winhouse:login-required event on window for you to handle.
See Your site owns sign-in. |
It exposes window.WinHouseEmbed = { frame, refit(), setLaunch(token), logout() }.
Call refit() if your own layout changes the frame's position,
setLaunch() after a player signs in without a page reload, and
logout() when they sign out on your site.
The raw iframe is still supported. If you use it, size it as below.
Sizing the frame
The book scrolls internally. Give it a real height — a sportsbook inside a short box becomes a scroll within a scroll and is unusable on a phone.
On a phone the height must be the visible height and no more, or the tab bar and betslip end up below the fold (see The loader, which does this for you):
Watch a fixed bottom nav. The book puts its own tab bar at the bottom of the frame on phones. If your site has a fixed bottom navigation, subtract its height too or the two overlap and neither is tappable.
If your page wrapper constrains width or adds a top margin, break out of it:
Your site's CSP
Allow-listing your domain with us is necessary but not sufficient.
If your site sends a Content-Security-Policy, its frame-src
must also name our origin, or the browser blocks the frame before it loads.
The symptom is a console message and an empty frame:
URL parameters
| Parameter | Meaning |
|---|---|
key | Your embed key. If it is missing, the book
identifies your brand from the page embedding it, matched against your
domain allow-list — so a snippet pasted without the key
still paints your skin on a listed domain. Elsewhere it loads unbranded.
The launch token always needs the key. |
lang | Starting language of the book — any of the 27 codes listed under
Languages (en sq de it fr es el tr pt bg ar fa ja ru zh bn pl ro sr me nl hu cs sk sv da et), e.g. &lang=de. Your page and the book
are different origins, so this is the only way to pass your visitor's choice
through; the player can still switch inside the book. |
embed=1 | Skip the book's own top bar and left rail. Use this when your page already has a header, or the chrome is doubled. |
launch | A signed, short-lived token identifying a player already signed in on your site. The book exchanges it for a session so the punter is not asked to log in twice — see Signing players in. Model B only. |
preview_theme | URL-encoded JSON of token overrides, for previewing a skin before saving. Styling only. |
Theme tokens
The book is built on CSS custom properties. Your skin is a set of overrides for them,
served with the book and applied to :root at boot. Set one from the
dashboard and everything using it repaints — there is no per-page styling to chase.
Values are validated on both sides: a token must be a hex colour
or a short length (px, rem, em, %).
Anything else — url(...), a closing brace, a whole rule — is dropped
rather than escaped, because these values land in a stylesheet.
Token reference
Blank inherits the default. Thirty-one tokens across six groups.
| Group | Tokens |
|---|---|
| Brand | accent accent-ink brand
green blue |
| Surfaces | bg surface surface-2
surface-3 hover border track
disabled |
| Shell | shell shell-line nav-txt
nav-sub |
| Text | text text-2 text-dim
text-faint |
| Status | live up down
win-green hl-pink |
| Layout | radius row-h odd-w
sidebar-w slip-w |
up and down are the price-movement flashes; live
is the in-play badge; odd-w and row-h control the density of
the board.
Account models
There are two ways to run players, and the choice decides how money moves. Pick one before you launch — switching later means migrating balances.
A. Book-side accounts
Players register and sign in inside the book. They sit in your own agent tree, and bets settle against the balance you fund from your operator credit line. Nothing is required from your site: embed the iframe and you are done.
B. Seamless wallet
Your site stays the source of truth for both identity and money. Your existing players sign in on your site, and the book debits and credits your wallet for every bet and settlement. This needs endpoints on your side — see below.
Being signed in on your site does not sign a
player into the book on its own. They are separate systems with separate databases,
and a third-party iframe cannot read your session. The hand-off that connects them is
the launch token — see Signing players in.
Signing players in
Model B only. Your player is signed in on your site; this is how they arrive in the
book already signed in, without a second login. Your site mints a short-lived
launch token and puts it in the iframe URL — the book redeems it for a
session by itself, so there is nothing to call from your page.
1. Mint the token
Four dot-separated fields. The signature is an HMAC-SHA256, hex, keyed with your
wallet API key (not the callback token), over the first three fields
joined by |. The key is generated the first time you save a wallet URL and
callback token, and is shown under Manage Account → General → Seamless wallet,
with Copy and Rotate:
| Field | Meaning |
|---|---|
player_id | Your own id for the player — the same value the wallet calls will quote back to you. Stable per player. |
expiry | Epoch milliseconds. Must be in the future and no more than 10 minutes ahead; mint it per page load, not per session. |
session | Your session id for this login. Stored against the player and quoted back on every wallet call, so ending a session on your side lets you stop bets on ours. May be empty, but then you lose that control. |
2. Put it in the iframe URL
Mint it server-side when you render the page. Never expose the wallet API key to the browser — anyone holding it can sign a token for any of your players.
3. What the book does
On first sight we provision a shell player under your tree, named
<slug>_<player_id>. It carries no balance of its own — every
stake and settlement goes to your wallet endpoints.
A missing, expired or malformed launch is not a hard
failure: the book simply loads signed out rather than breaking the page. So if players
are being asked to log in, check the token before suspecting the embed.
Your site owns sign-in
Once your seamless wallet is live, the book treats your site as the only place a
player signs in. It shows no Log In or Sign Up of its own, and sign-up on our side is
closed. Each page load trusts only the launch token in its URL:
- No token (the player is signed out on your site, or never signed in): the book loads signed out and drops any session it held from an earlier visit, so no previous player's balance can appear.
- Token that does not redeem (for example an expired one on a frame reload): the book keeps its session only if it belongs to the player that token names.
When the player signs out on your site without a page reload, call
WinHouseEmbed.logout() (the loader). If you build the
iframe yourself, post { type: "winhouse:logout" } to it. When a signed-out
player taps "Log in" inside the book, the book posts
{ type: "winhouse:login-required" } to your page. The loader turns that into a
winhouse:login-required event on window, or sends the player to
data-login-url if you set it.
Server-to-server alternative
If minting an HMAC client-side is awkward, ask for the session directly. Authenticate with the wallet API key as a bearer token — it travels in a header so it never lands in an access log next to the payload. Same provisioning, same response body:
If you have set a server IP, this call must come from that
address; otherwise it answers 403 with the address it saw in
ip. Optionally add X-WH-Domain: example.com — the site the
player is on — so the launch is attributed to that site in your reports, exactly as a
browser launch is (see several sites).
Errors
| Status | Meaning |
|---|---|
400 | Key is not a well-formed ifr_ key, or the
launch token does not have four fields. |
401 | Expired, dated too far ahead, or the signature does not
match — nearly always the wrong secret, or fields joined with something other than
|. |
404 | Unknown or suspended key. |
409 | No wallet configured for this account. SSO is model B only; on model A players sign in inside the book. |
Seamless wallet (model B)
Two endpoints on your side, called server-to-server. You give us one
base URL and we append the two paths to it, so
https://your.site/api/winhouse becomes
…/api/winhouse/user-data and …/api/winhouse/balance-change.
Two different secrets, and mixing them up is the most
common integration failure. The callback token travels in the
?token= query string and only proves the call came from us — compare it in
constant time. The wallet API key never travels; it is the HMAC key you
verify signature with, and the same key that signs
launch tokens.
Player lookup
username is your own player_id, the same one you signed into
the launch token. A reply we cannot read as a number is treated as "balance unknown" —
we never assume zero.
Live streaming only for depositors (optional)
Deposits happen on your platform, so you decide who may watch live streams. Add
"deposited": true or false to the same reply:
With false, the player sees "Live streaming is available after your first
deposit" instead of the video. Return true once they deposit, and the stream
opens within about 15 seconds. We also accept has_deposit, or a count/total
such as deposit_count or total_deposits (greater than 0 = deposited). If you leave
the field out, everyone who is signed in can watch, as before. Once your replies include the
field, a user-data call that fails keeps the stream locked instead of opening it.
Balance change
Verifying the signature
HMAC-SHA256, hex, keyed with your wallet API key, over five fields
concatenated with no separator, in exactly this order. An absent field
contributes an empty string, and amount is stringified as sent
(-25, not -25.00, when that is what is on the wire):
Reconstruct the base from the parsed body, not the raw JSON text — field order in the document is not part of the contract.
Rules your endpoint must follow
- Idempotent. Store
transaction_id. A repeat with the same id and the same payload returns the original result. A repeat with the same id and a different payload is a conflict — answer409. - Atomic. Lock the player row and apply the change in one transaction; a network retry must not double-debit.
- Reject overdraft. A debit larger than the balance returns
422and changes nothing. - Verify the signature on every call, and compare the callback token with a constant-time comparison.
- Answer promptly. A slow reply is indistinguishable from a lost one and will be retried — see below.
How we treat your reply
This decides whether a stake is retried, so it is worth getting right.
| Your reply | What we do |
|---|---|
2xx | Applied. We read balance if present. |
401 403 404 409 422 |
A deliberate refusal. Final — the bet is rejected and not retried. |
Timeout, 5xx, unreachable |
In doubt, not failed. The transaction stays pending and is
retried later with the same transaction_id. This is precisely why
idempotency is not optional. |
Retries happen. Treat every write as "may arrive twice, possibly out of order" — the idempotency key is what makes that safe.
Bet slips API (back office & "My Bets")
Every bet slip your players place in the book can be read back from your server — to list them in your own back office, or to show each player their own slips on a "My Bets" page of your site. Read-only, model B only (it needs your wallet API key).
Server-to-server only. The request carries your wallet API key; never call it from the player's browser. Your page asks your backend, your backend asks us for that player's slips.
Authentication
If you have set a server IP, calls must come from it. You only ever see slips of your own players.
List slips
| Parameter | Meaning |
|---|---|
player_id | Optional. The player's id on your site (the
player_id / external id you sign players in with). Omit it in the back office
to get all players. |
status | Optional. open, pending,
won, lost, cashed_out, cancelled,
rejected. |
from, to | Optional. ISO date-times on the placement
time, e.g. 2026-10-14T00:00:00Z (to is exclusive). |
limit, offset | Paging. Default 50, max 200. Newest
first; total in the reply is the full count. |
One slip
Response
Won / lost is decided per slip; each selection carries its match status and score, not a separate result. Poll every 30–60 s for open slips if you show live minutes; settled slips do not change.
Errors
| Status | Meaning |
|---|---|
400 | Malformed key, unknown status, or a bad date. |
401 | Wrong or missing wallet API key. |
403 | Call not from your configured server IP. |
404 | Unknown key, or the slip is not one of your players'. |
409 | No wallet configured for this account yet. |
Booking codes
Players can turn a bet slip into a short booking code and load it again later —
on another phone, at a friend's, or at a cashier. In the book, under the slip, Save or Load Bet
Slip opens the panel: Get booking code saves the slip (selections, stake and
Single / Multiple / System) and shows a code such as K7M4QZT with a copy button;
typing a code and Load fills the slip. No sign-in is needed to save or load; placing the
bet follows the normal rules.
- Codes are 7 characters from
A–Zand2–9without look-alikes (no0 O 1 I L), case-insensitive. A code belongs to the book it was made on: it does not load on any other operator's book. - Current odds. Loading never uses the stored price. Every selection is read again from the board (with your odds margin and league choice applied). Selections whose event has started, whose market is closed or whose price is suspended are left out and listed with the reason; selections whose price moved are listed old → new above the Place Bet button.
- Prematch only, at most 30 selections per code.
- Expiry: the earliest kickoff among the selections, or 72 hours after the code was made, whichever comes first. An expired code answers expired; it is deleted 30 days later.
- Limits: creating codes is rate-limited per IP address and per browser.
- Share link: opening the book with
?booking=K7M4QZTin its URL loads that code.
Agent panel. winhouse.bet/agent/ → Booking codes: type a code a player brings, see the selections at current odds, remove or add selections and change the stake or mode, then Save as new code or Update the code. Place for a player places the saved code for a player of your own network, through that player's normal betting rules (balance, limits, odds checks). Agents see only their own operator's codes, and can update a code saved by another agent only when that agent is in their network.
Read a booking from your server
For your own site or print shops. Same authentication as the Bet slips API
(X-Customer-Key + Authorization: Bearer <wallet_api_key>, server IP lock).
| Status | Meaning |
|---|---|
200 | Active code; every selection with its current odds or the reason it is not available. |
400 | Malformed key or code. |
401 / 403 | Wrong wallet API key / call not from your server IP. |
404 | No such code on your book. |
409 | No wallet configured for this account yet. |
410 | Expired. The body still carries booking with the booked selections
(current_odds null, unavailable_reason expired). |
503 | Odds could not be read just now; retry. |
Live streaming add-on
Live TV in the book is an add-on, sold in plans from Starter Stream upward. Each plan is paid per 30 days from your platform credit (a sub-operator's add-on is paid by its reseller) and includes a number of viewer-hours: one player watching for one hour. Extra hours beyond the plan are billed at the plan's per-hour rate as they are used. If the credit cannot cover them, Live TV pauses on your book until you top up or upgrade, and then comes back by itself. Current prices and hours are shown in the portal under Live Streaming.
The plan renews itself every 30 days from your credit. If the credit cannot cover the next period, Live TV switches off until you choose a plan again. Upgrading takes effect at once, and you pay only the price difference for the current period. Downgrading takes effect at the next renewal. Stopping the renewal keeps Live TV on until the end of the period you have paid for.
While it is active, Show Live TV on my book lets you hide or show it without
cancelling. Without the add-on, your book shows no TV marks, filter or player, and stream
links are refused. Players also need to be signed in and to have deposited; on the seamless
wallet, you decide that with the deposited flag.
Choosing leagues
In the portal, Leagues sets which competitions your players see:
- All competitions, optionally without whole categories: youth (U23 and younger), reserve leagues, women's competitions, friendlies, e-sports/virtual.
- All except the ones I hide: pick individual leagues to remove.
- Only the ones I choose: your book shows nothing but the leagues you tick.
Hidden leagues disappear from every list, the search and match pages, and bets on them are refused even if they are sent by hand. Changes reach the book within a minute.
League order. Under League order on the same page, add the leagues you want first and arrange them with ▲ / ▼. They lead your book in that order: the top leagues, the country list (their countries move to the top), each country's league list and the match lists. Everything else follows in the standard order. Changes reach the book within a minute.
Agent panel
Your network lives at winhouse.bet/agent/ with the account issued when your customer was created — a Manager, Super Manager or Boss, depending on your plan: managers, agents, shops and players, credit down the chain, stake limits, market blocks, tickets, settlement and reports. Tickets and players show which of your sites they came from, and the ticket list can be filtered by site.
Your tree is scoped to you. No other operator can see it, and you cannot see theirs.
Languages
This site and the sportsbook your players see are available in 27 languages; your customer portal at iframe.winhouse.bet/portal in 26 of them (all but Japanese):
en English, de Deutsch, it Italiano, fr Français,
es Español, sq Shqip, me Crnogorski, tr Türkçe,
el Ελληνικά, sr Српски, zh 中文, pt Português,
ru Русский, da Dansk, sv Svenska, bn বাংলা,
bg Български, pl Polski, ro Română, cs Čeština,
hu Magyar, sk Slovenčina, nl Nederlands, et Eesti,
ar العربية, fa فارسی, ja 日本語.
ar and fa are laid out right-to-left. The public pages live at
/<code>/ (for example /de/) and carry
hreflang alternates, so search engines index each one on its own.
In the portal, the globe at the top right switches the language on the spot and remembers
the choice in this browser; Account Settings → Preferences saves a
default on your account so every device opens in it. ?lang=<code> on the
portal URL forces a language for that visit. Translations load on demand, one small file per
language, so the choice costs nothing on pages you do not open.
The book your players see is a separate surface with its own dictionary, in all
27 languages (en sq de it fr es el tr pt bg ar fa ja ru zh bn pl ro sr me nl hu cs sk sv da et), chosen with the
lang parameter (data-lang in the embed snippet)
or the book's own menu. Team, player and league names stay as the data feed supplies them. A player's
choice is kept in the same browser key as the portal's, so a WinHouse-hosted page and the
book it embeds stay in step.
Billing & credit
There is no setup fee and no licence. You buy prepaid credit in USDT (minimum 50, and it never expires), and once a month we draw a percentage of your GGR out of it.
GGR = stakes taken − payouts made, across your own network only. Two details decide what is counted:
- Only settled tickets count. An open bet is not billed until it resolves, and a refunded one is never billed.
- A ticket is live if any of its selections was placed in-play; otherwise it is prematch. The two are billed at different rates.
The fee is floored at zero per rate, so a month in which your players came out ahead costs you nothing and does not carry forward.
| Plan | Unlocked by | Live GGR | Prematch GGR | Account type |
|---|---|---|---|---|
| Starter | — | 7.5% | 4.5% | Manager |
| Business | USDT 899 funded | 6.5% | 3.5% | Super Manager |
| Scale | USDT 2,499 funded | 5.5% | 2.5% | Boss |
The three account types, lowest to highest: Manager — your players and their tickets; Super Manager — your own agents underneath you, their limits and their tickets; Boss — managers under you as well, plus bet settings, market blocks and bonuses for the whole network.
The plan follows your lifetime funded total, not your current balance, and is upgrade-only — spending the credit down never puts the rate back up. A plan set for you by hand pins it, so a negotiated rate survives your next top-up.
Prepaid packs and network float
Credit can be bought as a pack — Starter USDT 199, Business USDT 899, Scale USDT 2,499 — or as any custom amount from 50. A pack does one extra thing: USDT 100 of it is turned into network float for your agent tree the moment the payment settles, and the rest stays as platform credit. The Starter pack at 199 therefore gives you USDT 100 of float (converted to your book's currency at the live rate) and USDT 99 of credit. A custom top-up is credit only; you can still buy float from it yourself under Wallet → Network float.
| Pack | You pay | To network float | Stays as credit |
|---|---|---|---|
| Starter | USDT 199 | USDT 100 | USDT 99 |
| Business | USDT 899 | USDT 100 | USDT 799 |
| Scale | USDT 2,499 | USDT 100 | USDT 2,399 |
The float is bought with the pack's own credit, never on overdraft: if your credit is negative when a pack settles, the credit is added but the float purchase is refused and shown on the top-up — contact us and we will apply it.
What network float is for
Credit and float are two different pots, spent on two different things, and it is worth being clear about which is which. Platform credit is what you have paid us, held in USDT: the monthly GGR fee and any subscriptions come out of it, and the book stops taking bets when it is exhausted. Network float is your own betting bankroll, held in your book's currency on your top account. It is the stock of credit you are allowed to put into circulation in your agent tree.
Float moves only when you move it. Betting does not touch it:
| What happens | Your float |
|---|---|
| A pack settles, or you buy float under Wallet → Network float | Goes up |
| You credit an agent or a player | Goes down |
| You take credit back off an agent or a player | Goes up |
| A player places a bet | Unchanged |
| A player wins, loses or cashes out | Unchanged |
| We bill your monthly GGR | Unchanged — that is drawn from credit |
The usual shape is this: a player hands cash to one of your shops, the shop credits them that amount in the panel, and the credit comes out of your float on its way down the tree. The cash stays with you. Once the player is funded, their stakes and winnings move inside their own balance and your float is not involved again until they cash out — at which point taking the credit back off them returns it to you.
So you top up float when you have issued out more than you have left, not when your players are busy. At zero float the panel refuses any further deposit with Insufficient balance. Nothing else breaks: every player you have already funded carries on betting normally, and you simply cannot onboard or top up anyone new until you buy more.
Size it against what your players deposit in a cycle, not against what they stake. Stakes recirculate inside player balances; only new money entering your network consumes float. And because float tracks issuance rather than results, it tells you nothing about whether you are up or down for the month — the GGR figures in the dashboard are what answer that.
If you run on the seamless wallet (model B) you never need float at all. Your players' balances live on your own platform, no credit is ever issued here, and your only obligation to us is keeping platform credit positive.
Account type is also sold as a monthly add-on outside the ladder, billed with the month it covers (Super Manager USDT 50, Boss USDT 100). Cancelling it drops you back to whatever your funding alone earns.
The reseller panel is a one-time USDT 1,000 purchase, paid from your credit or by crypto, with no monthly fee. It lets you create sub-operators: complete white-labels of their own (embed key, template, domain, agents, players, their own portal and panel logins) that you run from the Sub-operators page of your portal. Their GGR is priced at your plan and drawn from your credit, you fund their network float from your credit, and their book stops when your credit does. What you charge them is up to you.
Your bills, the ladder and your current rates are all in the dashboard under Credit & Plans.
Suspension
Suspending an account disables the embed and the boss login together, and takes effect immediately — the config endpoint is intentionally uncached, so a suspension is a real kill switch rather than something that expires later.
A suspended key returns 404 from /tenant/config and the
book will not render.
Troubleshooting
| Symptom | Cause |
|---|---|
| Empty frame, console says "Refused to frame" | Your site's CSP frame-src does not list our origin. |
| Book loads, but with the WinHouse look instead of yours | The key in your snippet is empty or mistyped and the embedding
domain is not on your allow-list. Fix either one. |
| Frame loads but shows nothing / refuses | Your domain is not on the allow-list, or the account is still in sandbox. |
| Book worked, then stopped on one of your sites after you changed the Domain | The Domain field replaces the previous value: the site you removed is no longer allowed to frame the book. Put it back, or ask us to open the key to several domains if you run both. |
| Book asks players to log in although they are signed in on your site | On model A this is expected. On model B the launch token is missing,
expired or mis-signed — the book stays signed out rather than erroring. See
Signing players in. |
| Bets rejected, wallet endpoint returns 401 | The signature is keyed with the wallet API key,
while ?token= carries the callback token. They are
different secrets — see Seamless wallet. |
| The same stake arrives twice | A timeout is retried with the same transaction_id. Your endpoint
must be idempotent on that key. |
| Colours did not change | A token failed validation and was dropped — it must be a hex colour or a short length. |
| Chrome appears twice (two headers) | Add &embed=1 to the iframe URL. |
| No bottom tab bar and no betslip on mobile | The frame is taller than the screen, so the book's fixed bars sit below the fold.
Use embed.js, or give the frame the visible
height and drop any min-height on phones. |
| Bottom tab bar overlapped on mobile | Your own fixed bottom nav sits on top of it — set
data-bottom-gap to its height (or subtract it yourself). |
| Old snippet stopped working | The key was rotated. Copy the current one from the dashboard. |
Something not covered here? sales@winhouse.bet or reach us on Telegram.