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);
  }
}