Skip to content

SlottyClient Reference

The SlottyClient class is the main entry point for the Slotty Labs SDK. It provides access to all API modules.

Constructor

typescript
import { SlottyClient } from '@slottylabs/sdk';

const client = new SlottyClient(config: SlottyClientConfig);

SlottyClientConfig

typescript
interface SlottyClientConfig {
  /** API key (sk_sandbox_* or sk_production_*) */
  apiKey: string;

  /** Webhook secret for signature verification (optional) */
  webhookSecret?: string;

  /** API base URL (optional, auto-detected from key prefix) */
  baseUrl?: string;

  /** Request timeout in milliseconds (default: 10000) */
  timeout?: number;

  /** Custom fetch implementation (optional, for testing) */
  fetch?: typeof fetch;
}

Default Base URL

If baseUrl is not provided, it defaults to https://api.slottylabs.com for both environments — the platform derives the environment (sandbox vs production) from your API key.


client.auth

Authentication and SSO token management.

createSSOToken()

Creates a single-use SSO launch token for a player.

typescript
const result = await client.auth.createSSOToken(request: CreateSSOTokenRequest): Promise<CreateSSOTokenResponse>;

CreateSSOTokenRequest

typescript
interface SSOTokenRequest {
  /** Operator's external player ID */
  playerId: string;

  /** Player currency code (e.g. "USD", "EUR", "BTC") */
  currency: string;

  /** Jurisdiction code (e.g. "CW", "MT", "GI") */
  jurisdiction: string;

  /** Locale code (e.g. "en", "de", "es") — optional, default "en" */
  locale?: string;

  /** Target game ID (optional — pins the token to one game) */
  gameId?: string;

  /** Launch in demo (play-money) mode (optional, default: false) */
  demo?: boolean;
}

SSOTokenResponse

typescript
interface SSOTokenResponse {
  /** Single-use JWT launch token (30s TTL) */
  launchToken: string;
}

Example

typescript
const { launchToken } = await client.auth.createSSOToken({
  playerId: 'player-123',
  currency: 'USD',
  jurisdiction: 'CW',
  locale: 'en',
  gameId: 'slotty-slots',
});

// Use launchToken in a game launch URL within 30 seconds

client.games

Game catalog and launch URL management.

getLaunchUrl()

Generates a game launch URL with the given token and options.

typescript
const url = client.games.getLaunchUrl(
  gameId: string,
  launchToken: string,
  options?: LaunchUrlOptions,
): string;

LaunchUrlOptions

typescript
interface LaunchUrlOptions {
  /** Locale code (default: "en") */
  lang?: string;

  /** Lobby URL to redirect on exit */
  lobby?: string;

  /** Enable demo mode */
  demo?: boolean;

  /** Channel: "desktop" or "mobile" */
  channel?: 'desktop' | 'mobile';
}

Example

typescript
const launchUrl = client.games.getLaunchUrl('slotty-slots', launchToken, {
  lang: 'en',
  lobby: 'https://yourcasino.com/lobby',
  channel: 'desktop',
});
// Returns: https://games.slottylabs.com/launch/slotty-slots?token=eyJ...&lang=en&lobby=...&channel=desktop

list()

Returns the full game catalog available to your tenant.

typescript
const games = await client.games.list(): Promise<GameListResponse>;

GameListResponse

typescript
interface GameListResponse {
  games: GameSummary[];
  total: number;
}

interface GameSummary {
  id: string;
  name: string;
  type: 'single_step' | 'multi_step' | 'session_based';
  volatility: 'low' | 'medium' | 'high' | 'very_high';
  maxWin: number;
  rtpVariant: string;
  enabled: boolean;
  thumbnailUrl: string;
}

getDetails()

Returns detailed information about a specific game.

typescript
const game = await client.games.getDetails(gameId: string): Promise<GameDetails>;

GameDetails

typescript
interface GameDetails {
  id: string;
  name: string;
  type: 'single_step' | 'multi_step' | 'session_based';
  volatility: 'low' | 'medium' | 'high' | 'very_high';
  maxWin: number;
  rtpVariant: string;
  rtpRange: { min: number; max: number };
  enabled: boolean;
  thumbnailUrl: string;
  description: string;
  features: string[];
  minBet: number;
  maxBet: number;
  currencies: string[];
  version: string;
}

client.wallet

Player wallet operations.

getBalance()

Returns the current balance for a player.

typescript
const balance = await client.wallet.getBalance(playerId: string, currency: string): Promise<PlayerBalance>;

PlayerBalance

typescript
interface PlayerBalance {
  balance: string;   // Minor-unit string (e.g. "12500" = €125.00)
  currency: string;
}

Example

typescript
const { balance, currency } = await client.wallet.getBalance('player-123', 'EUR');
console.log(`Balance: ${balance} ${currency}`);

getJackpots()

Returns your casino's progressive jackpot pool(s) — one pot per currency. Use it to render the live pot in your own lobby or site UI (poll every 30–60s); pair with the round.jackpot_won webhook for win notifications. See the Progressive Jackpots guide.

typescript
const { pools } = await client.wallet.getJackpots(currency?: string): Promise<{ pools: JackpotPool[] }>;

JackpotPool

typescript
interface JackpotPool {
  id: string;
  name: string;              // e.g. "USDT Progressive Jackpot"
  currency: string;
  currentAmount: string;     // Current pot, minor-unit string
  maxAmount: string;         // Guaranteed-payout ceiling, minor-unit string
  status: string;            // 'active' | 'paused'
  lastHitAt: string | null;  // ISO 8601 of the last win
  lastHitAmount: string | null;
  totalHits: number;
}

Example

typescript
const { pools } = await client.wallet.getJackpots('USDT');
if (pools[0]) {
  const usdt = Number(pools[0].currentAmount) / 1e6;
  console.log(`Jackpot: ${usdt.toFixed(2)} USDT`);
}

deposit()

Operator-initiated deposit into a player's wallet.

typescript
const result = await client.wallet.deposit(
  playerId: string,
  amount: string,      // Minor-unit string
  currency: string,
  options?: { idempotencyKey?: string; description?: string },
): Promise<{ transactionId: string; balance: string; currency: string }>;

Example

typescript
const { transactionId, balance } = await client.wallet.deposit(
  'player-123', '100000', 'EUR',
  { idempotencyKey: 'dep-20260707-001', description: 'Manual top-up' },
);

withdraw()

Operator-initiated withdrawal. HMAC-signed automatically by the SDK. Enters the admin approval queue; completion/failure arrives via webhooks.

typescript
const result = await client.wallet.withdraw(
  playerId: string,
  amount: string,       // Minor-unit string
  currency: string,
  addressId: string,    // Saved withdrawal address ID
  options?: { idempotencyKey?: string },
): Promise<WithdrawResult>;

WithdrawResult

typescript
interface WithdrawResult {
  withdrawalId: string;
  status: string;        // "pending_approval"
  balanceAfter: string;  // Minor-unit string after funds locked
}

Example

typescript
const { withdrawalId, status } = await client.wallet.withdraw(
  'player-123', '50000', 'EUR', 'addr_abc123',
  { idempotencyKey: 'wd-20260707-001' },
);

getTransactions()

Fetch paginated transaction history (ledger) for a player.

typescript
const result = await client.wallet.getTransactions(
  playerId: string,
  currency: string,
  options?: { page?: number; limit?: number; type?: string },
): Promise<{ transactions: TransactionEntry[]; total: number }>;

TransactionEntry

typescript
interface TransactionEntry {
  transactionId: string;
  type: string;          // "bet", "win", "deposit", "withdrawal", "rollback", "bonus"
  amount: string;        // Minor-unit string
  currency: string;
  balanceAfter: string;  // Running balance after this tx
  description: string;
  timestamp: string;     // ISO 8601
}

Example

typescript
const { transactions, total } = await client.wallet.getTransactions(
  'player-123', 'EUR',
  { page: 1, limit: 50, type: 'bet' },
);

getBonuses()

List a player's active bonuses with live wagering progress. New in v1.4.0.

Bonuses from your campaigns (e.g. a welcome deposit match) are granted automatically on a qualifying deposit, held in a separate non-withdrawable bonus balance, and convert to real balance once the wagering requirement is met. This endpoint is for display — you don't call anything to grant a bonus.

typescript
const { active } = await client.wallet.getBonuses(playerId: string): Promise<{ active: PlayerBonus[] }>;

PlayerBonus

typescript
interface PlayerBonus {
  claimId: string;
  campaignId: string;
  campaignName: string;
  amount: string;              // Minor-unit string (bonus granted)
  currency: string;
  wageringProgress: string;    // Minor-unit string wagered so far
  wageringRequirement: string; // Minor-unit string total to clear
  progressPercentage: number;  // 0–100
  status: 'active' | 'wagering_met' | 'converted' | 'expired' | 'cancelled' | 'forfeited';
  expiresAt: string;           // ISO 8601
}

Example

typescript
const { active } = await client.wallet.getBonuses('player-123');
for (const b of active) {
  console.log(`${b.campaignName}: ${b.progressPercentage}% → ${b.status}`);
}

WARNING

Bonus funds cannot be withdrawn directly, and initiating a withdrawal forfeits any still-active (uncleared) bonus. Surface this to players before they withdraw.


getWithdrawalFee()

Preview the fees for a withdrawal before the player confirms — the platform service fee, the network (gas) fee, and the net amount sent on-chain. New in v1.5.0.

typescript
await client.wallet.getWithdrawalFee(
  playerId: string,
  params: { chain: string; currency: string; amount: string },
): Promise<WithdrawalFeeEstimate>;

WithdrawalFeeEstimate

FieldTypeDescription
grossAmountstringAmount requested (smallest unit)
feestringPlatform service fee retained
gasFeestringNetwork fee charged to the player ("0" when operator-sponsored)
netAmountstringNet sent on-chain = gross − fee − gasFee
feeTypestringpercentage | fixed | hybrid
feePctnumberApplied service-fee percentage
gasModestringoperator_sponsored | player_pays
chain / currencystringEchoed back

Example

typescript
const est = await client.wallet.getWithdrawalFee('player-123', {
  chain: 'ethereum', currency: 'USDT', amount: '100000000', // 100 USDT
});
console.log(`Net ${est.netAmount} (fee ${est.fee}, network ${est.gasFee}, mode ${est.gasMode})`);

TIP

This is a preview; the same split is applied when you call withdraw(...), whose response also returns fee, gasFee, and netAmount.


client.players

Player statistics and round history. New in v1.3.0.

getRounds()

Fetch paginated round history for a player, optionally filtered by game.

typescript
const result = await client.players.getRounds(
  playerId: string,
  options?: { page?: number; limit?: number; gameId?: string },
): Promise<{ rounds: PlayerRoundEntry[]; total: number }>;

PlayerRoundEntry

typescript
interface PlayerRoundEntry {
  roundId: string;
  gameId: string;
  status: string;
  betAmount: string;
  winAmount: string;
  startedAt: string;
  completedAt: string | null;
  paytableVariant: string;
}

Example

typescript
const { rounds, total } = await client.players.getRounds('player-123', {
  page: 1, limit: 50, gameId: 'catapult',
});

getStats()

Get aggregate statistics for a player — total bets, wins, losses, favorite game, and per-game breakdown.

typescript
const stats = await client.players.getStats(playerId: string): Promise<PlayerStats>;

PlayerStats

typescript
interface PlayerStats {
  totalRounds: number;
  totalWagered: string;    // Minor-unit string
  totalWon: string;        // Minor-unit string
  netResult: string;       // Minor-unit string (negative = net loss)
  favoriteGame: string | null;
  biggestWin: string | null;
  gamesPlayed: Record<string, { rounds: number; wagered: string; won: string }>;
}

Example

typescript
const stats = await client.players.getStats('player-123');
console.log(`Total wagered: ${stats.totalWagered}, Net: ${stats.netResult}`);
console.log(`Favorite game: ${stats.favoriteGame}`);

client.test

Sandbox testing utilities. Only available with sk_sandbox_* API keys.

createPlayer()

Creates a test player with a starting balance.

typescript
const result = await client.test.createPlayer(request: CreateTestPlayerRequest): Promise<CreateTestPlayerResponse>;

CreateTestPlayerRequest

typescript
interface CreateTestPlayerRequest {
  externalId: string;
  currency: string;
  /** Starting balance in integer minor units, as a string (e.g. "1000000" = $10,000.00) */
  startingBalance: string;
  username?: string;
}

CreateTestPlayerResponse

typescript
interface CreateTestPlayerResponse {
  player: {
    id: string;
    externalId: string;
    username: string;
    currency: string;
  };
  wallet: {
    id: string;
    balance: number;
    currency: string;
  };
  ssoToken: string;
}

forceOutcome()

Forces a specific outcome for the next round. See Sandbox Testing for game-specific outcome formats.

typescript
await client.test.forceOutcome(request: ForceOutcomeRequest): Promise<void>;

ForceOutcomeRequest

typescript
interface ForceOutcomeRequest {
  playerId: string;
  gameId: string;
  outcome: SlotsOutcome | SafeSmashOutcome | BitKeyRushOutcome | FoxOutcome | CatapultOutcome;
}

getHealth()

Returns the health status of all platform services.

typescript
const health = await client.test.getHealth(): Promise<HealthCheckResponse>;

HealthCheckResponse

typescript
interface HealthCheckResponse {
  status: 'healthy' | 'degraded' | 'unhealthy';
  checks: Record<string, 'ok' | 'error'>;
  timestamp: string;
  version: string;
}

SlottyApiError

Custom error class thrown for all API errors.

typescript
class SlottyApiError extends Error {
  /** HTTP status code */
  statusCode: number;

  /** Slotty error code (e.g. "80001") */
  code: string;

  /** Human-readable error message */
  message: string;

  /** Unique request ID for support */
  requestId: string;

  /** Original response body */
  body: Record<string, unknown>;
}

Example Error Handling

typescript
import { SlottyClient, SlottyApiError } from '@slottylabs/sdk';

try {
  const { launchToken } = await client.auth.createSSOToken({
    playerId: 'player-123',
    currency: 'USD',
    jurisdiction: 'CW',
    locale: 'en',
  });
} catch (err) {
  if (err instanceof SlottyApiError) {
    switch (err.code) {
      case '80001':
        console.error('Invalid API key');
        break;
      case '80003':
        console.error('Rate limited — retry after backoff');
        break;
      case '80010':
        console.error('Player not found');
        break;
      default:
        console.error(`API Error ${err.code}: ${err.message}`);
    }
    console.error(`Request ID: ${err.requestId}`);
  } else {
    // Network error, timeout, etc.
    console.error('Unexpected error:', err);
  }
}