What the host controls
Knowing where the line is keeps you from designing around something you cannot change, and from debugging something that is not yours.
Yours
| Where | |
|---|---|
| Battles and seats | The API |
| Your result webhook | Console → Settings → Webhook |
| Your provider credentials | Console → Settings → SoftSwiss |
| Your game allowlist | Console, if you have access; otherwise ask |
| Your console users and their roles | Console |
| Your API keys | Console, if granted apikeys.write; otherwise ask |
The host's
| Why it is not yours | |
|---|---|
| The viewer signing key | One key signs for every casino on the instance. Rotating it affects everyone, so it is super-user only |
| The three lobby windows | Platform-scoped. They describe how the install runs a battle, not a casino's credentials |
| Recorder capacity | Shared. Your peak competes with everyone else's |
| Upgrade timing | Their deploy schedule |
| Mail configuration | Instance-wide. It is resolved at boot and cannot be per-casino |
| The console's domain | The session cookie is SameSite=Strict, so the console and the API must share a registrable domain. That is settled by the host's DNS |
What this means in practice
You cannot have a different lobby window. If your product wants lobbies open for an hour and the platform runs ten minutes, that is a conversation with the host rather than a setting. Design your UI around their values, and ask for them up front.
A signing-key rotation is invisible if handled well. The host appoints a new key and
leaves the old one verifying until it retires, so tokens already in browsers keep working.
Viewers suddenly getting 401 on the socket means the rotation was done without a window,
which is a host problem; re-minting is your mitigation.
Capacity is shared. 503 unavailable means the instance is at its in-flight battle cap,
which may be someone else's traffic. Retry with backoff and jitter, and raise it with the host
if it becomes routine.
Upgrades can fail battles in flight. A battle mid-recording depends on already-running
recorders, so in-flight battles may end as battle.failed when the host deploys. Your backend
has to handle that anyway, but knowing their schedule lets you avoid promoting a tournament
into it.
Diagnosing which side a problem is on
| Symptom | Side |
|---|---|
403 game_not_allowed | Yours, or the allowlist. Wait 30 s for the cache first |
403 missing scope: ... | The host's. Your key needs that scope |
403 tenant suspended | The host's. A relationship question |
500 failed to mint viewer token | The host's. The instance has no signing key |
ws_url points at the REST port | The host's. The public WS base URL is unset |
| WebSocket connects then drops in ~60 s | The host's. Load balancer idle timeout |
| Recordings arrive but look like a slideshow | The host's. Recorders without GPU acceleration |
503 unavailable under load | The host's capacity |
| No webhook arriving | Yours first. Check the endpoint is reachable and the secret is set |
409 already in an active battle | Yours. A previous battle has not reached a terminal state |
Quote the middle rows verbatim when you report them. 500 failed to mint viewer token in
particular reads like an application bug and is a missing key.
Questions worth asking on day one
- What are the three lobby window values?
- Which scopes does my key carry?
- Which game ids are allowed for my tenant?
- Is a viewer signing key configured? (Ask them to mint a token and confirm.)
- What is the load balancer idle timeout, relative to a long battle?
- What is your upgrade schedule, and how are we told?
- How are signing-key rotations announced?
- What is the in-flight battle cap, and how close is the instance to it at peak?
The answers change what you build, so ask before rather than after.
Next
- Onboarding checklist
- Tenancy: the tenant/platform split in full
- Errors: every code and what to do