Appearance
Endpoints
The hizi RGS platform provides all endpoints. The initial login() call returns the backendURL and token. The SDK sends requests as JSON POST bodies to the backendURL.
login
Exchange the short-lived launch token for a session token and the URLs for all later calls. The game's launch URL provides the launch token. The response also carries the operator's platform settings (gameSettings). Your frontend must follow these settings, such as stake limits, enabled features, UI behaviour, and regulatory flags.
Request:
typescript
await login({ loginURL, launchToken });Response: IConnectReply
typescript
{
token: string; // Session token for subsequent API calls
backendURL: string; // URL for game API calls
refreshURL: string; // URL for refreshing the session
logoutURL: string; // Logout URL
webSocketURL?: string; // WebSocket URL (optional)
balance?: IBalanceReply; // Player balance
gameSettings?: IGameSettings; // Operator platform settings - read this!
tokenData?: ITokenData; // Token metadata (playerId, currency, mode, …)
freePlaysAvailable?: IFreePlayInfo[]; // Available free plays
}Read gameSettings before showing the game
gameSettings values differ by operator and by jurisdiction. These values must control your UI. Your frontend must clamp and validate stakes. Your frontend must also respect every enabled and disabled flag. The engine does not enforce these settings again for you.
Typical fields to apply:
- Use
minStake,maxStake, andmaxPackageStaketo clamp the stake selector and buy-feature prices. - Use
customStakes,defaultStakeIndex, andforceDefaultStaketo override the game's own stake list. - Use
maxExposureto cap the maximum win that you show or allow. - Use
autoplayEnabled,autoplayLossLimitRequired, andautoplayShowTotalStaketo control the autoplay UI. - Use
gambleEnabled,turboEnabled,stopEnabled,partialCollectEnabled, andpackageBuyEnabledto enable or disable feature buttons. - Use
displayRTP,displayXRTP,showExactRTP,displayWinOdds, anddisplayJackpotOddsto control the disclosure of RTP and odds. - Use these fields to control presentation:
forceOrientation,disableFullScreenMobile,hideCompanyLogo,displayClock,abbreviateAmounts,displayNetPosition,hideDemoBalance, anddisplaySessionTimer. - Use
historyURL,homeURL,topupURL,lossLimitURL,homeEnabled, andredirectTargetfor external navigation. - If
reportAnimationEndistrue, callreportAnimationEndafter every win animation. - Use
operatorHandlesErrors,translateErrors,preventRedirect, andrefreshDisabledto handle errors and sessions.
See IGameSettings for the full field list. Operators may also supply extra fields beyond the typed ones. The index signature [key: string]: unknown exposes these extra fields.
Stake limits precedence
Always intersect the game's own stake list (loadConfig → config.stakes) with gameSettings.minStake and gameSettings.maxStake. Use gameSettings.customStakes when the operator provides it. The operator's limits override the game's defaults.
loadConfig
Load the game configuration including available stakes, RTP, and buy-features.
Request:
typescript
await loadConfig({ backendURL, token });Under the hood, this sends:
json
{
"op": "loadConfig",
"token": "<session-token>"
}Response: ILoadConfigReply
typescript
{
config: {
gameCode: string;
gameType?: string; // Set for rules-engine games (e.g. 'mines', 'crash', 'keno', 'roulette'). Absent for fixed-odds slot/plinko games.
stakes?: number[]; // Available stake amounts (optional)
rtp: number; // Return to player percentage
maxPayoutCap?: number; // Maximum payout cap
maxWagerableWin?: number; // Maximum win amount eligible for wagering
minWagerableWin?: number; // Minimum win amount eligible for wagering
version: string; // Engine version
buyFeatures?: IBuyFeatureOption[]; // Available buy-features (with `id` added)
wagerFeatures?: string[]; // Relative wager features (e.g. ["color-red", "color-black", ...])
wagerStakeFeatures?: string[]; // Absolute cashout wager features (e.g. mines/frogger steps)
progressionCounters?: IProgressionCounterConfig[]; // Progression counter configs
progressionCounterValues?: Record<string, number>; // Current counter values (0.0–1.0)
[key: string]: unknown; // Additional fields from loadConfig.json
};
tokenData: ITokenData; // Updated token data
balance?: IBalanceReply; // Player balance
gameResult?: IGameResult; // Last game result (if resuming)
gameRoundInfo?: IGameRoundInfo; // Game round info (if resuming)
freePlaysAvailable?: IFreePlayInfo[]; // Available free plays
previousResults?: IGameResult[]; // Previous game results
amountToCollect?: number; // Uncollected amount
}Key fields:
| Field | Description |
|---|---|
config.gameType | Set for rules-engine games (for example 'mines', 'crash', 'keno', 'roulette'). Absent for fixed-odds slot or Plinko games. Use this field to select game-specific UI. |
config.stakes | Array of available stake amounts, in minor currency units. Optional. Some games use custom stakes set by the operator. |
config.rtp | Return to player percentage (for example, 95 for 95%) |
config.buyFeatures | Available buy-feature options. See buy-features |
config.wagerFeatures | Available wager feature names (absent if the game has no wager features). See gamble-features |
config.progressionCounters | Progression counter configuration. See Progression Counters |
config.progressionCounterValues | Current counter values per player (0.0–1.0 range) |
gameResult | The last game result if the player has an incomplete round to resume |
placeBet
Place a bet to receive a game result. You can also continue an in-progress round with this endpoint.
Request:
typescript
// New spin
await placeBet({ backendURL, token, stake, config });
// Continue multi-step round
await placeBet({ backendURL, token, config });
// Buy feature
await placeBet({
backendURL,
token,
stake,
featureToBuy: featureId,
config,
});config is the object that loadConfig() returns (configResponse.result.config). Passing config enables automatic decompression of the scenario field. Without config, the engine returns scenario in its compressed (minified) form.
Under the hood:
json
{
"op": "placeBet",
"token": "<session-token>",
"stake": 100,
"featureToBuy": "freespin"
}Options: IPlaceBetOptions
| Field | Type | Required | Description |
|---|---|---|---|
backendURL | string | Yes | Backend URL from login response |
token | string | Yes | Session token |
stake | number | No | Stake amount. Required for the first call of a gameround. |
useTicket | boolean | No | Use a freeplay ticket |
useTicketFeatureType | string | No | Feature type of the ticket |
featureToBuy | string | No | Feature to buy (for example, 'freespin'). The engine derives the price from the stake. |
config | ILoadConfigConfig | No | Config from loadConfig(). Required to decompress the scenario field. |
playerChoiceIndex | number | No | Index of the selected option when engineData.playerChoice is set |
additionalData | Record<string, unknown> | No | Additional game-specific parameters |
Response: IPlaceBetReply
typescript
{
result: IGameResult; // The game result
tokenData: ITokenData; // Updated token data
balance?: IBalanceReply; // Updated balance
gameRoundInfo?: IGameRoundInfo; // Game round status
amountToCollect?: number; // Uncollected amount
}The key payload is result, an IGameResult:
typescript
{
// Your scenario data (from hizi engine generator)
scenario: Record<string, unknown>;
// Engine state
engineData: {
// Fixed-odds (entries-DB) games only - omitted by rules-engine games
// such as blackjack and crash.
entryIndex?: number;
scenarioInfo?: IScenarioInfo;
spinInfo?: ISpinInfo[];
playerChoice?: TPlayerChoiceAward[];
currentFeature?: string;
nextFeature?: string;
progressionCounters?: Record<string, number>;
canCollect?: boolean;
inProgress: boolean;
buyFeatureId?: string; // Id of the feature this round was opened by buying, if any
};
// Cumulative win (multiplier of stake)
totalWin: number;
}TIP
If the round opened with featureToBuy, every reply for that round echoes back which feature it was. This includes every continuation placeBet call and the closing collect call. The field is result.engineData.buyFeatureId. Use this field to attribute the round's total win to the bought feature. You do not need to track the feature on the client side. The field is absent (undefined) for a round that did not open by buying a feature. Older engine versions also duplicated this field at the reply root as buyFeatureId. That copy no longer exists. Read the field from engineData instead.
Decision logic after you receive a response:
| Condition | Action |
|---|---|
engineData.playerChoice is set | Present options to the player. Then call placeBet with playerChoiceIndex: N. |
engineData.inProgress === true | Call placeBet({ backendURL, token }) to continue |
engineData.inProgress === false and totalWin > 0 | If the game has wager features, call collect() to cash out. Otherwise, the round ends automatically. You do not need to take action. |
engineData.inProgress === false and totalWin === 0 | The round is complete. Enable the next spin. |
TIP
Games without wager features always end the round automatically when the game completes. A game has no wager features when both config.wagerFeatures and config.wagerStakeFeatures are absent. The engine credits winnings automatically. You do not need to call collect().
collect
Collect winnings after a completed round. This endpoint is available only for games with wager features. A game has wager features when config.wagerFeatures or config.wagerStakeFeatures is present. Games without either wager feature type end the round automatically. The engine credits winnings automatically for these games.
Request:
typescript
// Collect full amount
await collect({ backendURL, token });
// Collect partial amount
await collect({ backendURL, token, amount });Under the hood:
json
{
"op": "collect",
"token": "<session-token>",
"collectAmount": 5000
}Options: ICollectOptions
| Field | Type | Required | Description |
|---|---|---|---|
backendURL | string | Yes | Backend URL from login response |
token | string | Yes | Session token |
amount | number | No | Amount to collect. If you omit this field, the engine collects the full available amount |
additionalData | Record<string, unknown> | No | Additional game-specific parameters (for example, the crash betHash from crashCollectData()) |
Response: ICollectReply
typescript
{
amountCredited: number; // Amount credited to balance
amountToCollect: number; // Amount that was requested
balance?: IBalanceReply; // Updated balance
tokenData: ITokenData; // Updated token data
result?: IGameResult; // Final game result - closed engineData (and buyFeatureId, if bought); see placeBet
}WARNING
Only call collect when:
- The game has wager features (
config.wagerFeaturesorconfig.wagerStakeFeaturesis present) engineData.canCollect === truetotalWin > 0(there are winnings to collect)
If you call collect on a game without wager features, the engine returns an error.
pfVerify
Replay any past round from its revealed seeds. If the round had player actions, replay those too. pfVerify reruns the exact game logic that the live round used. It returns the full result and the per-call RNG audit. You can compare this audit against what you recorded at round time.
This endpoint works only for provably-fair rounds. A provably-fair round runs with config.rng === 'pf'. The endpoint never touches the wallet, progression counters, or operator caps. It is pure compute.
Request:
typescript
import { pfVerify } from '@hizi.io/engine-sdk';
const reply = await pfVerify({
backendURL,
token, // current session token (auth + gameId routing)
serverSeed: pf.revealedServerSeed,
clientSeed: pf.clientSeed,
stake: 100, // the stake the round opened with
featureToBuy: 'freespin', // if the round opened on a buy feature
initialData: { /* … */ }, // blackjack side bets
bets: [ /* … */ ], // roulette / crash opening bets
playerNumbers: [ /* … */ ], // keno picks
actions: [
{ playerChoiceIndex: 0 }, // fixed-odds wager choice
{ pickPosition: 12 }, // mines pick
{ action: { kind: 'hit' } }, // blackjack action (TRulesAction shape)
],
});Under the hood, the SDK POSTs to backendURL:
json
{ "op": "pfVerify", "token": "<session-token>", "serverSeed": "…", "clientSeed": "…", "…": "…" }Options: IPfVerifyOptions
| Field | Type | Required | Description |
|---|---|---|---|
backendURL | string | Yes | Backend URL from the login response. |
token | string | Yes | Session token. The engine uses it only to resolve the gameId to the game config. The endpoint makes no wallet calls. |
serverSeed | string | Yes | The revealed server seed from the round's pf block. |
clientSeed | string | Yes | The client seed for that round. |
startNonce | number | No | Defaults to 0. Set it if your round opened mid-stream against an existing provably-fair session. |
stake | number | No | Required by games that need the stake to settle. Examples: blackjack settlement math, and Frogger or other fixed-odds wager games. |
featureToBuy | string | No | Mirror the round's opening featureToBuy value. Examples: the Mines mine count, or a Slot bonus buy. |
initialData | Record<string, unknown> | No | Mirror the round's opening payload. Currently this is blackjack's { sideBets }. |
bets | unknown[] | No | Roulette's IRouletteBet[] or Crash's IBet[]. These are the round's opening bets. |
playerNumbers | number[] | No | Keno: the player numbers, if the round was opened with explicit picks. |
actions | IPfVerifyAction[] | No | Continuation actions, in order. The shape depends on the game. See the game's Provably Fair section under Games. |
Response: IPfVerifyReply
typescript
{
rngData: IRngDataEntry[]; // per-call audit, same shape as the live `pf.rngData`
steps: IGameResult[]; // per-step game outcomes, terminal step last (length 1 for one-shots)
}Two fields, two checks:
- Audit replay: compare
rngDataelement by element against the round's savedpf.rngData. Rows of type'int'must match exactly. Rows of type'double'must match within a float tolerance. A swapped server seed produces different draws. A passing comparison proves the revealed seed is the seed that the round committed to. - Result replay: compare each
steps[i].scenarioandsteps[i].totalWinvalue to what the live round returned at the matching step. For one-shot games, this is juststeps[0]. For multi-step rounds (blackjack, Mines, Hi-Lo), this is the full per-step chain.
If both checks match, only (serverSeed, clientSeed, actions) determined the round. The engine could not have rigged the outcome.
engineData is preserved
Each step is a full IGameResult. steps[i].engineData carries the engine's per-step flow-control state: playerChoice (fixed-odds wager-feature offerings), inProgress, and nextFeature. Use this data to verify the round's flow, not just the final outcome. For example, confirm that a fixed-odds round showed the expected wager choices.
Defence-in-depth commit check
For an explicit commitment check on top of the audit replay, compute SHA-256(serverSeed) on the client. Compare the result to the serverSeedHash you saved before the round opened. This takes one crypto.subtle.digest call. The engine does not need to return this value.
Scope
pfVerify skips the operator-side post-processing that the live placeBet call runs. This includes progression counters, gameSettings.maxExposure caps, and supplemental stake debits. You cannot derive these from the provably-fair commitment. Verification covers only the RNG draws and the game logic that uses them.
Crash
Crash player-cashout timing depends on the wall clock, not on the seed. pfVerify for Crash returns only the committed scenario.maxMultiplier. This is the entire seed-derived surface. The operator audits bet settlements.
See Provably Fair for the underlying HMAC-SHA512 protocol. That page also explains how the protocol derives the seeds from (serverSeed, clientSeed, nonce).
refresh
Refresh an expired session token. Call this when API requests return SESSIONINVALID or NOTLOGGEDON errors.
Request:
typescript
await refresh(refreshURL);The initial login() response provides the refreshURL (result.refreshURL).
Response: IConnectReply
typescript
{
token: string; // New session token
backendURL: string; // Backend URL (may change)
refreshURL: string; // New refresh URL
logoutURL: string; // Logout URL
webSocketURL?: string; // WebSocket URL
balance?: IBalanceReply; // Player balance
gameSettings?: IGameSettings; // Platform settings
tokenData?: ITokenData; // Token metadata
freePlaysAvailable?: IFreePlayInfo[]; // Available free plays
}TIP
After a successful refresh, update your stored token, backendURL, and refreshURL with the new values from the response.
reportAnimationEnd
Notify the backend that the game animation has finished. Use this endpoint when the operator requires animation-end reporting (see gameSettings.reportAnimationEnd).
Request:
typescript
await reportAnimationEnd({ backendURL, token });updateBalance
Request an updated balance from the backend.
Request:
typescript
await updateBalance({ backendURL, token });