Skip to content

Data model & enums

The field-level rules behind the wire types used across @moose/provider-sdk and the Wallet API. This page is the semantics; the SDK reference has the exact TypeScript declarations.

Amounts & currency

  • Amounts are always integers in the currency's minor unit (e.g. cents for USD) — never floats. 300 means $3.00. This applies everywhere an amount appears: TransactionRequest.amount, TransactionResponse.balance, BalanceResponse.balance, and every amountMinor/balanceMinor field in @moose/game-client-sdk.
  • currency must be an uppercase, 3-letter ISO-4217 code (e.g. "USD", not "usd") — the platform's validator is case-sensitive. A malformed or lowercase code is rejected with 400.

TransactionType

ts
type TransactionType = 'BET' | 'WIN' | 'ROLLBACK'

A fourth value, ADJUSTMENT, exists in the platform's canonical model but is rejected with 400 on the provider-facing endpoint — it's an admin-only operation for manual corrections, not part of your integration.

TransactionRequest

FieldTypeNotes
transactionIdstringGenerated by you. Reuse verbatim across retries of the same logical attempt — this is the idempotency anchor. ProviderClient's own internal retries already do this automatically.
sessionTokenstringIdentifies the session verifySession resolved. There is no separate operatorId field on the wire — the operator is resolved from this token, server-side.
typeTransactionType'BET' | 'WIN' | 'ROLLBACK'
roundIdstringGroups the transactions belonging to one round.
roundCompletebooleantrue on whichever of BET/WIN ends the round. Meaningful only for BET/WIN; ignored for ROLLBACK.
originalTransactionIdstring?Required when type === 'ROLLBACK' (the BET's transactionId being reversed). Forbidden (rejected) for every other type.
playerRefstringMust match the session's player — the platform validates this.
amountnumber (int64)Minor units, >= 0. A zero-amount WIN (no payout) is valid.
currencystringUppercase ISO-4217, must match the session's currency.
gameIdstringMust match the session's game.
metadataobject?Opaque, capped at 8 KiB — see below.

Metadata

metadata is a provider-supplied JSON object the platform stores and forwards to the operator verbatim, without interpreting it. Typical use: attaching jackpot detail to a WIN (pool ID, tier, jackpot amount).

  • Must be a JSON object — an array, string, number, or null is rejected.
  • Capped at 8 KiB; exceeding it is rejected with 400.
  • Optional — omit it when there's nothing to attach.
  • The platform never reads any key inside it. It's accepted on any transaction type, not just WIN.
ts
// A documentation-only convention for a jackpot WIN's metadata — the
// platform does NOT validate against this shape. Any JSON object is
// accepted; this is purely a naming convention for interoperability with
// other tooling that might read a WIN's metadata later.
type JackpotMetadata = {
  jackpot?: {
    won: boolean
    tier?: string
    amountMinor?: number
    poolId?: string
  }
}

TransactionResponse

ts
type ResponseStatus = 'OK' | 'DECLINED'
type TransactionResponse = { status: ResponseStatus; balance: number }

DECLINED is only ever a valid outcome for a BET (insufficient funds, or outside the configured bet limits) — it's a normal business result, not an error, and is never retried. WIN and ROLLBACK are never declined by design: a technical failure on those types surfaces as a timeout/5xx and is retried via the same idempotency machinery instead.

VerifySessionResponse

ts
type VerifySessionConfig = {
  rtpProfile: string     // pass-through display label; the platform never interprets it
  minBetMinor: number
  maxBetMinor: number     // 0 means no upper limit
  language: string        // BCP-47 (e.g. "en", "zh-TW"), or "" if the operator didn't request one — fall back to your own default
}

type VerifySessionResponse = {
  playerRef: string
  gameId: string
  operatorId: string
  currency: string
  config: VerifySessionConfig
}

BalanceResponse & VerifyReplayResponse

ts
type BalanceResponse = { balance: number } // minor units

type VerifyReplayResponse = {
  roundId: string   // look this up in your own replay storage
  gameId: string
  playerRef: string
  currency: string
  language: string  // same convention as VerifySessionConfig.language
}

Bot-detection digests aren't part of this data model — they're posted directly from the browser (see BehaviorReporter and the behavior-ingestion endpoint), never through @moose/provider-sdk or any type in this reference.

Platform → provider webhook bodies

RevokeSessionRequest and the free-spins grant/status/cancel bodies are documented alongside their routes — see Session revoke webhook and Free spins webhook.