Domains & embedding
How players reach the game: the launch call returns a fully-formed, platform-provided game_url you embed on your site — there is no domain of yours to configure. Merchant-owned custom domains (CNAME) are deprecated and no longer accepted for new registration.
Players reach the game at a platform-provided host — not a domain of yours. The launch call returns a fully-formed game_url that you embed exactly as returned, and the launch token carries the tenant, the player and (for a single-market launch) the market itself, so identity never rides on the Host. You do not point a CNAME, and you do not own or register a player domain. There is nothing to provision here: being launch-ready is a property of your merchant record.
Merchant-owned custom domains (CNAME) are deprecated
This page used to describe a per-merchant custom domain — one CNAME you pointed at our edge, reviewed and activated before the first launch — as a prerequisite for every merchant. That model is being retired. New owned-domain registration and activation is closed: a request to add one answers 410 owned_domain_registration_closed. Existing owned domains that were already enabled keep serving during a migration and drain window, so nothing running today breaks — but no new ones can be added, and launches on those merchants already return a platform-provided game_url.
The rest of this page documents how you embed the platform-provided game_url. The legacy custom-domain behaviour is summarised at the end, marked as deprecated — read it only if you are operating a domain enabled before this changed.
How players reach the game
Mint a launch token with a signed B2B call and read game_url from the response. The host inside it is provided by the platform at mint time — a platform host, the same shape for every merchant — and you embed the URL exactly as returned.
https://<game-host>/?lt=<launch_token> # lobby launch
https://<game-host>/market/<market_id>?side=1#lt=<token> # single-market deep link
https://<game-host>/event/<event_id>#lt=<token> # event deep link
; <game-host> is a platform-provided address. It is not yours, you do not configure it,
; and the exact host can differ per environment and per launch. Do not hard-code it —
; always read it from the launch response.Because the token carries the tenant, the game runs wherever the platform serves it — the session is host-free, so there is no Host binding to satisfy and no per-merchant domain to keep enabled. A launch that names a market_id returns a single-market deep link, and one that names an event_id an event deep link (the token rides in the URL fragment in both). That decides where the player lands and nothing more — the session it produces is a normal, full-catalogue one for your merchant. See Launch & sessions for the full contract.
The player surface is still same-origin within the frame: the client, the player API under /c-api/* and the realtime feed all live on the platform host the iframe was served from, routed there by our edge, so the browser makes no cross-origin call out of the frame. You configure no path rules, proxy nothing, and maintain no route table that can drift out of step with ours. The one thing that is different from hosting on your own subdomain is that the platform host is not under your domain, so your parent-domain cookies are not sent to it — a property worth knowing, and a smaller attack surface than the old model carried.
Being launch-ready
There is no domain to register, but a launch can still be refused. Two conditions have to hold, and only the first is anything to do with you — it is a property of your merchant record on the operator side rather than anything you deploy:
- • A completed profile. Your merchant has a settlement currency and a
site_key. Thesite_keyis what anonymous, read-only market browsing on a platform host uses to resolve your merchant, via a?mch=<site_key>selector; anything that touches money goes through a launch-token session instead, never the selector. - • A host available to serve it. The platform must have a host available for the launch at mint time. This is supplied by the platform, not by you; its momentary absence is transient rather than a configuration state — see
launch_pool_emptybelow.
Short of the first, POST /b2b/v1/auth/session refuses with merchant_domain_not_ready (409). This is the same error code as the old model but with a new meaning: it no longer reports a missing enabled CNAME — it reports a merchant that has not reached go-live. Usually this is a configuration state — no site_key — and retrying does nothing until the profile is completed. One sub-case is transient, though: if the shared host pool is momentarily empty, that surfaces here as 409 as well (not 503, unlike the mint call), so a 409 from this endpoint on an otherwise-complete profile can still clear on a bounded retry. The launch (mint) call is different: it does not run the site_key / go-live gate, so a merchant missing only a site_key can still mint a launch token. When the platform temporarily has no host available at mint time you get launch_pool_empty (503) instead — a transient issue that a short backoff and retry can clear.
Sandbox and production are separate systems with separate merchant profiles, so being launch-ready in one grants nothing in the other. See Environments & endpoints for what else is separate between the two.
Embedding the frame
Declare the parent origins you embed the game from — every site, including any preview deployment you intend to test from — with the operator during onboarding. The platform host emits frame-ancestors at the edge from the declared origins, and the client we serve additionally checks the actual embedding parent against the origins declared for your merchant. A page whose origin was never declared is blocked by the browser with a frame-ancestors violation in the console. Add every origin to your declaration rather than expecting a permissive default.
When it does not work
The failures cluster into a few kinds, and the status code tells them apart — read that before the message.
| Field | Type | Description | |
|---|---|---|---|
| session refused before any URL is returned | 409 | optional | merchant_domain_not_ready — raised by POST /b2b/v1/auth/session (the go-live gate), not by minting a launch token: the merchant is not go-live ready, its setup is not complete (for example no site_key). Usually a configuration state where completing the profile is the fix (a momentarily empty host pool surfaces here too, and that clears on a bounded retry). Note the new meaning: it is no longer about a missing CNAME. |
| launch mint refused, merchant looks ready | 503 | optional | launch_pool_empty — the platform temporarily had no host available to serve this launch; transient and unrelated to your request — a short backoff and retry is reasonable. This, not the 409, is what a launch-token mint returns when the host is unavailable. |
| the iframe is blocked in the browser console | CSP | optional | Refused to frame … because an ancestor violates … frame-ancestors. The page doing the framing is not on the allowlist the operator holds for your parent sites. A new marketing domain, a preview deployment on a generated hostname, or a page moved to a different origin all need that allowlist updated first. |
| a blank frame after the URL loads once | 401 | optional | The launch token was already spent or has expired — a refresh, a cached URL, or a second load of the same one. A game_url is good for exactly one load; mint a fresh token per launch rather than re-rendering the old one. |
| trying to add a custom domain | 410 | optional | owned_domain_registration_closed — merchant-owned custom domains are deprecated and new registration/activation is no longer accepted. There is nothing to retry; the platform returns the game_url you embed, and there is no domain of yours to point. |
Where this sits in the integration
Launch-readiness gates everything the player touches and nothing your servers touch. The B2B surface you sign against and the money path keep working on a merchant that is not yet launch-ready — which is exactly why an integration can look healthy from your backend while no player can be launched. Once the profile is complete, return to the Quick Start and mint a launch token.
| POST | /c-api/v1/session/exchange | Runs on the platform host inside the frame. Redeems a host-free launch token for a session; the token carries the tenant, so there is no Host binding to satisfy. |
| GET | /c-api/v1/markets | Anonymous, read-only market data on a platform host, attributed to your merchant by the ?mch=<site_key> selector. Money paths never use the selector — they require a launch-token session. |
| WS | /c-api/v1/ws/ticks?ticket=… | Realtime feed. Accepted for a session served on the platform host; the host-free session is not bound to a merchant-owned Host. |
| POST | /b2b/v1/auth/launch-token | Builds game_url on a platform host. Returns launch_pool_empty (503) if the platform has no host available at that instant; unlike POST /b2b/v1/auth/session it does not run the go-live / site_key check and never returns merchant_domain_not_ready. |
Legacy: merchant-owned custom domains (deprecated)
Before this change, each merchant served the game from its own host — a single play.your-brand.com CNAME pointed at our edge, reviewed and activated by the operator, with game_url minted on that one enabled domain and the tenant resolved from the Host. This section is kept for merchants operating a domain that was enabled before the change; it is not a path new integrations can take.
- • No new registration or activation. Submitting or activating an owned domain now answers
410 owned_domain_registration_closed. The self-service domain UI in the merchant console is being withdrawn. - • Existing enabled domains still serve, for now. A domain that was already enabled keeps resolving and keeps serving its host-bound sessions through the migration and drain window, so no live player is cut off. New launches on that merchant already return a platform-provided game_url, and the owned host is drained once its remaining sessions expire.
- • The
sa1entry credential is retiring with it. The sa1 credential bound itshfield to an enabled host, which the current model does not use. Move any sa1 entry to a host-free launch token — see Launch & sessions and the sa1 note on Signature self-check. B2B request signing (server-to-server HMAC) is unrelated and unchanged.
If you operate an enabled owned domain and need to plan its retirement, raise it with your onboarding contact rather than disabling the CNAME yourself while sessions are still open on it.