SlottyClient Reference
The SlottyClient class is the main entry point for the Slotty Labs SDK. It provides access to all API modules.
Constructor
import { SlottyClient } from '@slottylabs/sdk';
const client = new SlottyClient(config: SlottyClientConfig);SlottyClientConfig
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.
const result = await client.auth.createSSOToken(request: CreateSSOTokenRequest): Promise<CreateSSOTokenResponse>;CreateSSOTokenRequest
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
interface SSOTokenResponse {
/** Single-use JWT launch token (30s TTL) */
launchToken: string;
}Example
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 secondsclient.games
Game catalog and launch URL management.
getLaunchUrl()
Generates a game launch URL with the given token and options.
const url = client.games.getLaunchUrl(
gameId: string,
launchToken: string,
options?: LaunchUrlOptions,
): string;LaunchUrlOptions
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
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=desktoplist()
Returns the full game catalog available to your tenant.
const games = await client.games.list(): Promise<GameListResponse>;GameListResponse
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.
const game = await client.games.getDetails(gameId: string): Promise<GameDetails>;GameDetails
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.
const balance = await client.wallet.getBalance(playerId: string, currency: string): Promise<PlayerBalance>;PlayerBalance
interface PlayerBalance {
balance: string; // Minor-unit string (e.g. "12500" = €125.00)
currency: string;
}Example
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.
const { pools } = await client.wallet.getJackpots(currency?: string): Promise<{ pools: JackpotPool[] }>;JackpotPool
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
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.
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
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.
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
interface WithdrawResult {
withdrawalId: string;
status: string; // "pending_approval"
balanceAfter: string; // Minor-unit string after funds locked
}Example
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.
const result = await client.wallet.getTransactions(
playerId: string,
currency: string,
options?: { page?: number; limit?: number; type?: string },
): Promise<{ transactions: TransactionEntry[]; total: number }>;TransactionEntry
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
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.
const { active } = await client.wallet.getBonuses(playerId: string): Promise<{ active: PlayerBonus[] }>;PlayerBonus
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
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.
await client.wallet.getWithdrawalFee(
playerId: string,
params: { chain: string; currency: string; amount: string },
): Promise<WithdrawalFeeEstimate>;WithdrawalFeeEstimate
| Field | Type | Description |
|---|---|---|
grossAmount | string | Amount requested (smallest unit) |
fee | string | Platform service fee retained |
gasFee | string | Network fee charged to the player ("0" when operator-sponsored) |
netAmount | string | Net sent on-chain = gross − fee − gasFee |
feeType | string | percentage | fixed | hybrid |
feePct | number | Applied service-fee percentage |
gasMode | string | operator_sponsored | player_pays |
chain / currency | string | Echoed back |
Example
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.
const result = await client.players.getRounds(
playerId: string,
options?: { page?: number; limit?: number; gameId?: string },
): Promise<{ rounds: PlayerRoundEntry[]; total: number }>;PlayerRoundEntry
interface PlayerRoundEntry {
roundId: string;
gameId: string;
status: string;
betAmount: string;
winAmount: string;
startedAt: string;
completedAt: string | null;
paytableVariant: string;
}Example
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.
const stats = await client.players.getStats(playerId: string): Promise<PlayerStats>;PlayerStats
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
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.
const result = await client.test.createPlayer(request: CreateTestPlayerRequest): Promise<CreateTestPlayerResponse>;CreateTestPlayerRequest
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
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.
await client.test.forceOutcome(request: ForceOutcomeRequest): Promise<void>;ForceOutcomeRequest
interface ForceOutcomeRequest {
playerId: string;
gameId: string;
outcome: SlotsOutcome | SafeSmashOutcome | BitKeyRushOutcome | FoxOutcome | CatapultOutcome;
}getHealth()
Returns the health status of all platform services.
const health = await client.test.getHealth(): Promise<HealthCheckResponse>;HealthCheckResponse
interface HealthCheckResponse {
status: 'healthy' | 'degraded' | 'unhealthy';
checks: Record<string, 'ok' | 'error'>;
timestamp: string;
version: string;
}SlottyApiError
Custom error class thrown for all API errors.
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
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);
}
}