Examples
The SDK includes five runnable example scripts that demonstrate common integration patterns. Each example is a standalone TypeScript file you can run with npx tsx.
Running Examples
Set your API key and base URL, then run any example:
export KINGSTONE_API_KEY=ks_sandbox_your_key_here
export KINGSTONE_BASE_URL=http://localhost:3001/api
npx tsx examples/quick-start.tsQuick Start
File: examples/quick-start.ts
The simplest possible integration. Initializes the client, lists available games, executes a spin, and reads the outcome.
import { KingstoneClient, KingstoneApiError } from '@kingstone/sdk';
const client = new KingstoneClient({
apiKey: process.env.KINGSTONE_API_KEY || 'ks_sandbox_REPLACE_ME',
sandbox: true,
});
// List available games
const { games } = await client.listGames();
console.log(`Found ${games.length} game(s)`);
// Execute a spin on the first game
const game = games[0];
const result = await client.spin({
gameId: game.gameConfigId,
playerId: 'demo-player-1',
wagerUsd: game.minWagerUsd ?? 0.25,
});
console.log(`Prize tier: ${result.outcome.prizeTier}`);
console.log(`Payout: $${result.outcome.payoutUsd.toFixed(2)}`);
console.log(`Combo: ${result.presentation.comboString}`);Express Integration
File: examples/express-integration.ts
Shows how to build an Express route handler that proxies spin requests to KINGSTONE. Your frontend calls your server, and your server calls KINGSTONE. This keeps the API key on the server side.
Key pattern:
const kingstone = new KingstoneClient({
apiKey: process.env.KINGSTONE_API_KEY!,
sandbox: true,
});
// POST /api/spin — your frontend calls this
async function handleSpin(req, res) {
const { gameId, wagerUsd } = req.body;
const playerId = req.user.id; // from your auth middleware
const result = await kingstone.spin({ gameId, playerId, wagerUsd });
res.json({
won: result.outcome.payoutUsd > 0,
payout: result.outcome.payoutUsd,
combo: result.presentation.comboString,
reelSymbols: result.presentation.reelSymbols,
animationHints: result.presentation.animationHints,
balance: result.balance.balanceUsd,
});
}Webhook Handler
File: examples/webhook-handler.ts
Demonstrates receiving and verifying HMAC-SHA256 signed webhook deliveries. Includes the full verification function and an Express route setup.
Key pattern:
import { createHmac, timingSafeEqual } from 'node:crypto';
function verifyWebhookSignature(rawBody: string, signature: string, secret: string): boolean {
const prefix = 'sha256=';
if (!signature.startsWith(prefix)) return false;
const received = signature.slice(prefix.length);
const computed = createHmac('sha256', secret).update(rawBody).digest('hex');
const a = Buffer.from(received, 'hex');
const b = Buffer.from(computed, 'hex');
if (a.length !== b.length || a.length === 0) return false;
return timingSafeEqual(a, b);
}Settlement Reconciliation
File: examples/settlement-reconciliation.ts
Shows the daily reconciliation workflow: fetch reports, compare against your records, and acknowledge or dispute.
Key pattern:
const { reports } = await client.listSettlements({ page: 1, limit: 5 });
const report = reports[0];
// Compare against your database
const yourSpins = await db.spins.count({ date: report.reportDate });
if (yourSpins === report.totalSpins) {
await client.acknowledgeSettlement(report.reportDate);
} else {
await client.disputeSettlement(report.reportDate, `Mismatch: ${yourSpins} vs ${report.totalSpins}`);
}Error Handling
File: examples/error-handling.ts
Covers all error types (authentication, validation, rate limits, server errors) with a retry utility for transient failures.
Key pattern:
async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3, baseDelayMs = 1000): Promise<T> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
if (error instanceof KingstoneApiError && error.retryable && attempt < maxRetries) {
const delay = baseDelayMs * Math.pow(2, attempt);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
throw new Error('Unreachable');
}
// Use it
const games = await withRetry(() => client.listGames());Sample PAR Sheet
File: examples/sample-par-sheet.json
A minimal valid 3-reel PAR sheet for sandbox testing. Use this as a starting point for the PAR sheet upload flow. It defines 5 symbols, 7 prize tiers (T0-T6), and 8 combinations with a certified RTP of 92.5%.
Next Steps
- Read the full Error Handling guide for detailed error strategies
- Review the Client Usage reference for all available methods
