Skip to content

Data structures ​

This page lists the wire types for the Game Studio API V2. The @hoelle/apiv2-definitions package publishes these types. This page groups the types into request bodies, replies, and shared/nested types.

API V2 request bodies ​

V2_TestPingRequestBody ​

ts
export interface V2_TestPingRequestBody {
  testData: unknown;
}

V2_StartGameRoundRequestBody ​

ts
export interface V2_StartGameRoundRequestBody {
  token: string;
  rngResult: GameRNGResult;
  debitInformation: DebitInformation;
  creditInformation?: CreditInformation;
  endGame: boolean;
  closeOpenGame?: boolean;
  useJackpot?: boolean;
  betData?: BetData;
  externalGameProviderRoundId?: string;
}

Note: externalGameProviderRoundId is optional. If you use it, do not exceed 32 characters. hizi.io then uses the value as the gameround hash. /startGameOrAddBet needs this field to recognise a later bet in the same gameround, so set it on the first bet of any gameround that holds more than one bet.

Not currently implemented

The engine ignores useJackpot now. The jackpot feature is specified, but it is not yet live. See Jackpot data types.

V2_EndGameRoundRequestBody ​

ts
export interface V2_EndGameRoundRequestBody {
  token: string;
  gameRound: string;
  externalGameProviderTransactionId?: string;
}

V2_GetGameRoundDetailsRequestBody ​

ts
export interface V2_GetGameRoundDetailsRequestBody {
  token: string;
  gameRound: string;
}

V2_AddWinRequestBody ​

ts
export interface V2_AddWinRequestBody {
  token: string;
  gameRound: string;
  rngResult: GameRNGResult;
  collect?: boolean;
  externalGameProviderTransactionId?: string;
  jackpotPayout?: V2_JackpotPayout[];
}

Not currently implemented

The engine ignores jackpotPayout now. See Jackpot data types.

V2_WagerWinRoundRequestBody ​

ts
export interface V2_WagerWinRoundRequestBody {
  token: string;
  gameRound: string;
  rngResult: GameRNGResult;
  wagerInformation: WagerInformation;
}

V2_CollectWinRoundRequestBody ​

ts
export interface V2_CollectWinRoundRequestBody {
  token: string;
  gameRound: string;
  collectInformation: CollectInformation;
}

V2_GetUncollectedAmountRequestBody ​

ts
export interface V2_GetUncollectedAmountRequestBody {
  token: string;
  gameRound: string;
}

V2_AddSpinCounterGameStateRequestBody ​

ts
export interface V2_AddSpinCounterGameStateRequestBody {
  token: string;
  gameRound: string;
  counterType: string;
  rngResult: GameEventRNGResult;
  gameStateResult: object | string;
}

V2_GetAvailableSpinCounterRequestBody ​

ts
export interface V2_GetAvailableSpinCounterRequestBody {
  token: string;
  gameRound: string;
  counterType: string;
}

V2_GetRandomResultRequestBody ​

ts
export interface V2_GetRandomResultRequestBody {
  token: string;
  rngEndPoint: string;
  rngPayload: {
    count?: number;
    min?: number;
    max: number;
  };
}

V2_GetTokenForGameRoundRequestBody ​

ts
export interface V2_GetTokenForGameRoundRequestBody {
  gameRound: string;
}

V2_GetTokenDataRequestBody ​

ts
export interface V2_GetTokenDataRequestBody {
  token: string;
}

V2_GetPlayerDataRequestBody ​

ts
export interface V2_GetPlayerDataRequestBody {
  token: string;
  currency?: string; // filters only when present and not empty
  stake?: number;    // filters only when present and not zero
}

V2_SetPlayerDataRequestBody ​

ts
export interface V2_SetPlayerDataRequestBody {
  token: string;
  data: Omit<V2_PlayerData, 'playerId' | 'gameId' | 'gameMode'>;
}

Note: The data field is a V2_PlayerData without playerId and gameId. The RGS reads the player and the game from the token, so the request cannot set them. V2_PlayerData has no gameMode field, so that third key of the Omit has no effect.

Note: The type keeps updated, but the RGS sets that value itself.

V2_GetLastGamesRequestBody ​

ts
export interface V2_GetLastGamesRequestBody {
  token: string;
  maxRecords?: number; // default is 50
  maxDays?: number; // default is 30
}

V2_GetOperatorSettingsQuery ​

ts
export interface V2_GetOperatorSettingsQuery {
  game: string;
  operator: string;
  currency: string;
}

V2_VoidGameRoundRequestBody ​

ts
export interface V2_VoidGameRoundRequestBody {
  gameRound: string;
  token: string;
}

Note: The published type declares token as optional. The engine requires it at runtime. Always send it.

API V2 replies ​

V2_GameAPIReply ​

ts
export interface V2_GameAPIReply {
  tokenData: V2_GameToken;
  balance?: GameAPIBalanceReply;
  gameRoundInfo?: {
    hash: string;
    status: string;
    stake: number;         // amount actually staked, in player currency minor units (already multiplied)
    baseStake?: number;    // equals stake for a normal round; on buy-feature rounds records the underlying stake. NOT stake / currencyMultiplier
    mode: string;
    currency: string;
    game: string;
    currencyMultiplier?: number;
    commonRoundHash?: string;
  };
  commonGameRoundInfo?: CD_InfoReply; // common-draw round info, only for common-draw games
  gameState?: Array<V2_GameAPIGameState>;
  amountToCollect?: number;
  amountCredited?: number;
  freePlayInfo?: {
    used: number;
    granted: number;
    won: number;
    isLast: boolean;
    promotions?: {
      protocolVersion: number;
      data: unknown;
    };
    serial: string;
  };
  freePlaysAvailable?: {
    currency: string;
    stake: number;
    count: number;
    feature?: string;
    serial: string;
  }[];
  passThroughData?: PassThroughData; // operator-specific pass-through payload
  promoWinInfo?: PromoWinInfo;
}

export interface PromoWinInfo {
  referenceId: string;
}

export interface PassThroughData {
  protocol: number; // OperatorProtocol enum value, e.g. 1 = HOELLE_NATIVE
  clientMessage?: NativeClientMessage;
}

export interface NativeClientMessage {
  title: string;
  msg: string; // the text to display to the player
  stopAutoPlay?: boolean;
  buttons?: {
    label: string;
    url?: string;
  }[];
  operatorHandlesDisplay?: boolean;
}

passThroughData.clientMessage.msg, when present, is the only field meant for player display for a responsible-gambling prompt. The operator sets this text from its own curated, localized source (for example, Playtech POP's messageArray[].accountMsg). The operator-protocols component maps this text through as-is. The field is present on the reply body of the call that triggered the prompt (most commonly startGameRound). It appears only if the operator's own response included that text in the first place. The Game Studio API does not generate or guarantee this text for every error code. It is a straight pass-through. The mapping itself is generic. Any Playtech response that carries a messageArray passes through, regardless of which error code triggered it. This field is present in production for both X-H-ERROR-ID 38 (REALITYCHECK) and 11 (BETLIMITREACHED). Do not assume it is absent for either code. Whether it is included for a given decline depends on the operator's own account and responsible-gambling configuration on Playtech's side. It does not depend on the error code or on anything controllable from the Game Studio API. Treat presence as per-operator and per-account, not per-error-code. Always keep a static fallback ready for when the field is missing. Do not use the X-H-ERROR-MSG header for display, in either case. See Response Codes. This header is documented as log-only. It is not localized. When clientMessage is absent, this API provides no player-facing text for that call. The game studio needs its own static fallback copy.

buttons is carried through as-is from the operator's own protocol. Today it only ever contains a single generic acknowledgement button. The button does not distinguish between a continue action and a stop action. It has no url field to call back. Treat it as informational. Render your own dismiss control (for example, a "Home" or "OK" button). Do not try to interpret it. For X-H-ERROR-ID 38 (REALITYCHECK) specifically, retry the same startGameRound call after the player dismisses the message. There is no separate acknowledgement endpoint reachable from the Game Studio API. RGS-to-RGS studios have no v2 equivalent of the native protocol's internal reality-check callback.

V2_ConnectReply ​

ts
export interface V2_ConnectReply extends V2_GameAPIReply {
  backendUrl: string;
  refreshUrl: string;
  logoutUrl: string;
  webSocketUrl?: string;
  token: string;
  gameSettings: GameSettings;
  gameVariables: Partial<GameVariables>;
  // please contact support for available options
  operatorProtocol: number;
  featuresAvailable?: ExternalFeaturePackageDefinition[];
  tokenData: V2_GameToken;
}

export interface ExternalFeaturePackageDefinition {
  game: string;
  type: string;
  rtp: number;
  value: number;
  description?: string;
}

V2_GameAPIGetUncollectedAmountReply ​

ts
export interface V2_GameAPIGetUncollectedAmountReply {
  tokenData: V2_GameToken;
  amountToCollect?: number;
}

V2_GameAPIAddSpinCounterGameStateReply ​

ts
export interface V2_GameAPIAddSpinCounterGameStateReply extends V2_GameAPIReply {
  spinsAvailable: number;
}

V2_GameAPIGetAvailableSpinCounterReply ​

ts
export interface V2_GameAPIGetAvailableSpinCounterReply extends V2_GameAPIGetUncollectedAmountReply {
  spinsAvailable: number;
}

V2_GameAPIRngReply ​

ts
export interface V2_GameAPIRngReply {
  tokenData: V2_GameToken;
  values: number[];
  rngRequestId: string;
}

V2_GetTokenDataReply ​

ts
export interface V2_GetTokenDataReply {
  tokenData: V2_GameToken;
}

V2_GetTokenForGameRoundReply ​

ts
export interface V2_GetTokenForGameRoundReply extends V2_GetTokenDataReply {
}

V2_GetPlayerDataReply ​

ts
export interface V2_GetPlayerDataReply {
  data: V2_PlayerData[];
}

V2_SetPlayerDataReply ​

ts
export interface V2_SetPlayerDataReply {
  data: V2_PlayerData[];
}

V2_GetLastGamesReply ​

ts
export interface V2_GetLastGamesReply {
  gameRoundList: Record<string, unknown>[];
}

Shared and nested types ​

V2_GameToken ​

ts
export type DeviceModes = 'desktop' | 'mobile';

export interface V2_GameToken {
  operatorId: string;
  playerId: string;
  gameId: string;
  mode: string;
  currency: string;
  currentToken?: string;
  gameRound?: string; // this holds any open gameroundhash
  walletMode: string;
  language: string;
  currencyMultiplier: number;
  device?: DeviceModes;
  commonDraw?: string;
}

V2_PlayerData ​

ts
export interface V2_PlayerData {
  playerId: string;
  gameId: string;
  currency?: string; // only present when the stored entry has one
  stake?: number;    // only present when the stored entry has one
  data: unknown;     // the stored payload, any JSON value
  updated?: string;  // set by the RGS
  expires?: string;  // only present when the stored entry has one
}

Note: data is unknown, so the entry holds any JSON value. Most games store an object.

GameAPIBalanceReply ​

ts
export type GameModes = 'DEMO' | 'REAL' | 'HISTORY';

export interface BalanceEntry {
  type: string;
  currency: string;
  amount: number;
}

interface DiscountEntry {
  stake: number;
  absoluteDiscountAmount: number;
  spinsRemaining?: number;
}
export interface DiscountInfo {
  text: string;
  currency: string;
  discounts: DiscountEntry[];
  campaignId?: string;
  validFrom?: string;
  validTo?: string;
}

export interface GameAPIBalanceReply {
  totalBalance: number;
  mode: GameModes;
  currency: string;
  balances: BalanceEntry[];
  discountInfo?: DiscountInfo;
  tickets?: TicketEntry[];
  ticketInfo?: TicketWonInfo;
}

TicketEntry ​

ts
export interface TicketEntry {
  count: number;
  stake: number;
  currency: string;
  price?: number;
  feature?: string;
  serial: string;
}

TicketWonInfo ​

ts
export interface TicketWonInfo {
  used: number;
  granted: number;
  won: number;
  isLast: boolean;
  promotions?: {
    protocolVersion: number;
    data: unknown;
  };
  serial: string;
}

GameRNGResult ​

ts
export type BetData = Record<string, unknown>;

export interface GameRNGResult {
  rngCallId: string | string[];
  result: unknown;
  winAmount?: number;
  betData?: BetData;
}

GameEventRNGResult ​

ts
export interface GameEventRNGResult {
  rngCallId: string | string[];
  result: GameEventRNGResultCounter;
  winAmount?: number;
}
export interface GameEventRNGResultCounter {
  awarded?: number;
  used?: number;
}

DebitInformation ​

ts
type GameTransactionStatus = 'success' | 'error' | 'retrying';
interface GameTransaction {
  currency: string;
  status?: GameTransactionStatus;
  externalGameProviderTransactionId?: string;
}
interface UseTicketDebitInformation {
  useTicket: boolean;
  featureType?: string;
}
interface BuyFeatureDebitInformation {
  featureToBuy: string;
  featurePrice: number;
  featureResultSetSelected: number;
}

export interface DebitInformation extends GameTransaction {
  debitAmount: number;
  useTicketInfo?: UseTicketDebitInformation;
  buyFeatureInfo?: BuyFeatureDebitInformation;
  jackpotContribution?: V2_JackpotContribution[];
}

Note: externalGameProviderTransactionId identifies your own bet transaction. Do not exceed 32 characters. Give each bet in a gameround its own value. /startGameOrAddBet reads this field to tell a repeated bet from a new one.

Not currently implemented

The engine currently ignores the jackpotContribution field here and the jackpotPayout field on CreditInformation, CollectInformation, and WagerInformation below. See Jackpot data types.

CreditInformation ​

ts
export interface CreditInformation extends GameTransaction {
  creditAmount: number;
  jackpotPayout?: V2_JackpotPayout[];
}

CollectInformation ​

ts
export interface CollectInformation extends GameTransaction {
  creditAmount?: number;
  jackpotPayout?: V2_JackpotPayout[];
}

WagerInformation ​

ts
export interface WagerInformation extends GameTransaction {
  wagerAmount: number;
  winAmount?: number;
  jackpotPayout?: V2_JackpotPayout[];
}

V2_GameAPIGameState ​

ts
export interface V2_GameAPIGameState {
  hash: string;
  type: string;
  processedOn?: Date;
  result?: {
    winAmount?: number;
    info: Record<string, unknown>;
  };
  amountWagered?: number;
  collected?: number;
  reason?: string;
}

Additional data types used in responses to frontend ​

The Game Studio API sends these structures in response to connect requests from the frontend during game startup (GET V2_API_ENDPOINT/connect).

V2_GameSettings ​

Exported as GameSettings from @hoelle/apiv2-definitions.

ts
export enum ForcedOrientation {
  none = 0,
  landscape = 1,
  portrait = 2
}
export enum DisplayWinOdds {
  maxPayout = 'maxPayout',
  maxWin = 'maxWin',
}

export interface GameSettings {
  autoplayEnabled: boolean;
  autoplayLossLimitRequired: boolean;
  displayCoins: boolean;
  displayJackpotOdds: boolean;
  displayRTP: boolean;
  displayXRTP: boolean;
  forceOrientation: ForcedOrientation;
  gambleEnabled: boolean;
  historyURL: string;
  homeURL: string;
  loadMsg: string;
  maxExposure: number;
  maxStake: number;
  maxPackageStake: number;
  minStake: number;
  minLoadTime: number;
  minSpinTime: number;
  multipleInstancesAllowed: boolean;
  rcDisplayWinLoss: boolean;
  rcEnabled: boolean;
  rcInterval: number;
  stopEnabled: boolean;
  topupURL: string;
  turboEnabled: boolean;
  homeEnabled: boolean;
  dynamicMinSpinTime: boolean;
  redirectTarget: 'self' | 'parent' | 'top';
  packageBuyEnabled: boolean;
  defaultStakeIndex: number;
  operatorHandlesErrors: boolean;
  displayClock: boolean;
  isSocial: boolean;
  displayCurrency: boolean;
  customStakes: number[];
  lossLimitURL: string;
  partialCollectEnabled: boolean;
  hideCompanyLogo: boolean;
  abbreviateAmounts: boolean;
  showExactRTP: boolean;
  jurisdiction: string;
  forceDefaultStake: boolean;
  disableFullScreenMobile: boolean;
  displayPaytableOnEnterGame: boolean;
  doNotStoreSettings: string[];
  sessionTimeoutInSeconds: number;
  displayNetPosition: boolean;
  hideDemoBalance: boolean;
  preventRedirect: boolean;
  refreshDisabled: boolean;
  displayWinOdds: DisplayWinOdds[];
  displaySessionTimer: boolean | string;
  skipWinsEqualToOrLessThanStake: boolean;
  reportAnimationEnd: boolean;
  launcherType: 'reelLink' | 'online';
  autoplayShowTotalStake: boolean;
  translateErrors: boolean;
  currencyToDisplay: string;
}

V2_GameVariables ​

Exported as GameVariables from @hoelle/apiv2-definitions.

ts
export interface GameVariables {
  rcElapsed: number;
}

Jackpot data types ​

Not currently implemented

The jackpot payload below (jackpotContribution, jackpotPayout, and the V2_JackpotMode, V2_JackpotContribution, V2_JackpotPayout types, added in docs v1.8) is specified but not yet live in the game engine. The engine currently ignores these fields. The engine also ignores useJackpot on V2_StartGameRoundRequestBody. This section keeps the specification for the planned feature. Do not build against it yet.

V2_JackpotMode ​

ts
export enum JackpotMode {
  ENGINE = 'engine',
  VENDOR = 'vendor'
}

V2_JackpotContribution ​

ts
export type V2_JackpotContribution = ({
  jackpotId: string
  jackpotMode: JackpotMode.ENGINE
} | {
  jackpotId: string
  jackpotContributionAmount: number // 6 decimal digits (check JackpotContributionScale)
  jackpotMode: JackpotMode.VENDOR
})

JackpotContributionScale ​

jackpotContributionAmountMonetary value
10.000001
100.00001
1000.0001
10000.001
100000.01
1000000.1
10000001

V2_JackpotPayout ​

ts
export type V2_JackpotPayout = ({
  jackpotId: string
  jackpotMode: JackpotMode.ENGINE
} | {
  jackpotId: string
  jackpotPayoutAmount: number
  jackpotMode: JackpotMode.VENDOR
})