Environments & base URLs
Two independent sets of URLs are involved in an integration — one you point at the platform, and two-to-three the platform points at you. It's easy to mix these up since they're configured on opposite sides.
Current environments
| Environment | Platform base URL | Behavior-ingestion endpoint |
|---|---|---|
| Staging | https://api.staging.stakegate.io | https://behavior.staging.stakegate.io/v1/client/behavior |
| Production | Coming soon | Coming soon |
Staging is live now — point ProviderClientOptions.baseUrl and BehaviorReporterOptions.ingestUrl at the values above to integrate against it today. Production will use the same names without the .staging. segment (e.g. api.stakegate.io) once it launches; this table will be updated when that happens.
Want to see a working integration first? https://demo.staging.stakegate.io runs this platform's own reference game studio against the staging environment above — open it in a browser to play through launch → spin → settlement using the same APIs described in this guide.
The platform's base URL (you → platform)
Your integration contact gives you the platform's base URL — this is what you pass as ProviderClientOptions.baseUrl. No trailing slash. Every signed call ProviderClient makes is ${baseUrl}${path} (e.g. https://platform.example.com/v1/wallet/transaction).
If your integration contact operates more than one platform deployment (for example, a pre-production environment you test against before your integration goes live, separate from where real players play), each deployment has its own baseUrl and its own tenant ID/secret pair. Treat each as a fully separate integration — a secret issued for one deployment does not work against another, and there's no shared identity between them. Confirm with your integration contact which baseUrl you should be pointed at for a given stage of your integration.
The behavior-ingestion endpoint
A third, separate URL: your integration contact also gives you a behavior-ingestion endpoint, which you pass as BehaviorReporterOptions.ingestUrl (@moosehq/game-client-sdk/behavior-reporter). This one is different from every other URL on this page in two ways:
- It's called directly by the game client's browser — not by your server. Nothing you run relays this call.
- It's authenticated by the player's session token, sent as an
X-Session-Tokenheader, not a provider HMAC signature — a browser can't hold your secret, so this endpoint doesn't use it. CORS is allowed from any origin, since games are hosted on domains the platform doesn't know ahead of time.
If your integration contact operates more than one platform deployment, each one has its own ingestUrl, same as baseUrl — don't assume the production and pre-production values are the same host with a different path.
URLs you register with the platform (platform → you)
The platform needs to know where to send players and where to send signed calls back to you. These are configured with your integration contact, per game (for the first two) or per provider tenant (for the third):
| Setting | Used for | Required? |
|---|---|---|
launchBaseUrl | Your game's entry page. The platform appends ?session=<token> and the operator loads the result into the iframe. See Getting the session token. | Yes — every game needs one |
replayBaseUrl | Your round-replay page. The platform appends ?replay=<token>. See Round replay. | Only if you support round replay. A replay-link request for a game with no replayBaseUrl configured fails with 400 on the operator's side. |
Webhook baseUrl | Where the platform sends signed calls to your server: session revoke and free-spins grant/status/cancel. See Platform → provider webhooks. | Only if you implement these webhooks |
Clock sync
Every signed call — in either direction — is checked against a clock-skew tolerance. Keep the clock on any server that signs or verifies requests synced via NTP. See Signing & authentication for the exact tolerance and how a skewed clock shows up as an unexplained 401.
Rate limits
Requests are rate-limited per provider tenant. Exceeding your limit returns 429 with a Retry-After header — see Errors & retry for the exact response shape and how ProviderClient surfaces it. If your integration's expected traffic needs a higher limit than your default, raise it with your integration contact before going live rather than after you start seeing 429s in production.