Game API
Crunchy-owned games plug into the casino's existing game flow as a first-party source (CRUNCHY_OWNED). The casino frontend never computes an outcome; it launches a session, sends bets, and renders what the server returns. All amounts are integers in minor units (cents, or 10⁻⁶ USDT).
1 · Catalog
GET/api/v1/gamesRequires a bearer token. Returns every ACTIVE Crunchy-owned game in the normalized aggregator shape. Reel strips are never included.
{
"source": "CRUNCHY_OWNED",
"count": 20,
"games": [{
"id": "crunchy-fruits", "source": "CRUNCHY_OWNED", "provider": "Crunchy Time Studio", "first_party": true,
"name": "Crunchy Fruits", "category": "SLOTS", "family": "CRUNCHY_FRUITS",
"rtp": 0.965, "volatility": "MEDIUM", "max_win_multiplier": 5000,
"layout": { "reels": 5, "rows": 5, "paylines": 10 },
"math_version": "1.0.0", "real_money_enabled": false, "demo_enabled": true,
"launch": { "method": "POST", "path": "/api/v1/games/crunchy-fruits/session" }
}]
}2 · Launch a session
POST/api/v1/games/:gameId/sessionRequires Authorization: Bearer <player access token>. The session is bound to the exact active math version; if the game is updated, the next spin returns MATH_VERSION_CHANGED and the client must relaunch.
POST /api/v1/games/crunchy-fruits/session
{ "currency": "USD", "mode": "DEMO" } // mode: DEMO | REAL (REAL requires real_money_enabled)
201 → {
"session_id": "…", "expires_at": "…", "currency": "USD", "mode": "DEMO", "balance": 100000,
"bets": { "min_bet": 20, "max_bet": 50000, "bet_levels": [20, 50, 100, …], "default_bet": 100 },
"game": { …client-safe config: symbols, paylines, paytable, features, art palette… }
}3 · Spin
POST/api/v1/sessions/:sessionId/spinThe server validates the session, currency, bet and funds, creates a round, draws a cryptographically secure outcome, evaluates paylines, wilds, scatters, free spins, bonus rounds and multipliers, applies the max-win cap, settles the wallet atomically and records an audit trail. Repeating the same idempotency_key returns the original settled round.
POST /api/v1/sessions/{session_id}/spin
{ "bet_amount": 100, "currency": "USD", "idempotency_key": "c7a2…" }
200 → {
"round_id": "…", "balance": 99940, "outcome_reference": "sha256…", "duplicate": false,
"outcome": {
"base": { "reel_stops": [12, 3, 44, 7, 21], "grid": [["CHERRY", …], …], "line_wins": [{ "payline_id": 1, "symbol_id": "SEVEN", "count": 3, "positions": [[0,2],[1,2],[2,2]], "win": 40 }], … },
"free_spins": { "triggered": false, … }, "bonus": { "triggered": false, … },
"base_win": 40, "free_spin_win": 0, "bonus_win": 0, "multiplier": 1, "total_payout": 40, "capped": false
}
}
Errors: 401 UNAUTHORIZED · 402 INSUFFICIENT_FUNDS · 403 REAL_MONEY_DISABLED · 409 SESSION_EXPIRED | MATH_VERSION_CHANGED | ROUND_IN_PROGRESS · 400 BET_* validation codes4 · Session state & close
GET / DELETE/api/v1/sessions/:sessionIdReturns balance and the last 20 rounds; DELETE closes the session.
Wallet interface
serverWalletAdapterThe engine never touches balances directly. Demo mode uses the test wallet. Real-money mode supports USDT, USDC, BTC, and ETH through Crunchy Time's private append-only crypto ledger. settleRound(user, asset, round_id, bet, payout) performs one atomic, idempotent wager and payout per round. Spins settle internally; blockchain deposits and withdrawals remain fail-closed until custody, network, confirmation, and signing rules are configured.