Quick start
The book is one iframe. There is no SDK, no build step and nothing to install on your server.
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.
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.
Add exact origins, one per line — scheme, host and port must match:
Wildcards are deliberately not supported. *.example.com would mean an
abandoned or hijacked subdomain becomes a valid host for your book.
We derive a frame-ancestors policy from that list:
With no domains configured it resolves to frame-ancestors 'none' — the
book fails closed rather than being embeddable anywhere.
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.
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 | Required. Your embed key. |
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. |
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. Model B is what connects them.
Seamless wallet (model B)
Two endpoints on your side, called server-to-server. Authenticate with a shared callback token and sign the payload; never trust the browser for either.
Player lookup
Balance change
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.
Retries happen. Treat every write as "may arrive twice, possibly out of order" — the idempotency key is what makes that safe.
Agent panel
Your network lives at winhouse.bet/agent/ with the boss account issued when your customer was created: managers, agents, shops and players, credit down the chain, stake limits, market blocks, tickets, settlement and reports.
Your tree is scoped to you. No other operator can see it, and you cannot see theirs.
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. |
| Frame loads but shows nothing / refuses | Your domain is not on the allow-list, or the account is still in sandbox. |
| Book asks players to log in although they are signed in on your site | Expected without model B. The two systems are separate. |
| 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. |
| Bottom tab bar unreachable on mobile | Your fixed bottom nav overlaps the frame — subtract its height from the iframe height. |
| Old snippet stopped working | The key was rotated. Copy the current one from the dashboard. |
Something not covered here? sales@winhouse.bet.