Seamless Wallet API
The Wallet API is the primary integration point between your casino and the Velo RGS. Your server must implement these endpoints so the RGS can debit bets, credit wins, and query balances in real time.
Authentication & Signing
All requests are signed with HMAC-SHA256. The RGS sends these headers on every call:
| Header | Description |
|---|---|
X-Api-Key | Your operator API key |
X-Sign | HMAC-SHA256(request_body, API_SECRET) |
X-Game-Id | Game identifier (e.g., velo_btc_5min) |
Content-Type | application/json |
TIP
Verify the X-Sign header on every incoming request to ensure it originated from the Velo RGS. Reject any request with an invalid signature.
Endpoints
POST /wallet/authenticate
Validate a player's session token and return their profile. Called when a player opens the game.
Request Body:
{
"token": "player-session-jwt-or-token",
"game_id": "velo_btc_5min"
}Response:
{
"player_id": "player_abc123",
"username": "JohnDoe",
"currency": "USD",
"balance": 1500.00,
"session_token": "session_xyz789"
}The session_token returned here will be included in all subsequent debit/credit/rollback requests, allowing you to validate the session is still active.
POST /wallet/debit
Debit the player's balance for a bet placement.
Request Body:
{
"player_id": "player_abc123",
"transaction_id": "550e8400-e29b-41d4-a716-446655440001",
"round_id": "184721",
"game_id": "velo_btc_5min",
"amount": 100.00,
"currency": "USD",
"session_token": "session_xyz789"
}Response (success):
{
"transaction_id": "550e8400-e29b-41d4-a716-446655440001",
"balance": 1400.00
}Idempotency
If you receive a duplicate transaction_id, return the original success response without debiting again. The RGS uses the bet UUID as the idempotency key.
POST /wallet/credit
Credit the player's balance for a win or early cashout.
Request Body:
{
"player_id": "player_abc123",
"transaction_id": "550e8400-e29b-41d4-a716-446655440002",
"ref_transaction_id": "550e8400-e29b-41d4-a716-446655440001",
"round_id": "184721",
"game_id": "velo_btc_5min",
"amount": 182.00,
"currency": "USD",
"reason": "settle",
"is_round_finished": true,
"session_token": "session_xyz789"
}| Field | Type | Description |
|---|---|---|
ref_transaction_id | string | Links back to the original debit (bet) |
reason | string | "settle" (round ended) or "cashout" (early exit) |
is_round_finished | boolean | true = no more transactions for this round. false = round still active (cashout) |
Response:
{
"transaction_id": "550e8400-e29b-41d4-a716-446655440002",
"balance": 1582.00
}Zero-Win Credits
When a player loses, the RGS sends a credit with amount: 0.00 to explicitly close the bet on your side. This ensures every debit has a matching credit for clean reconciliation.
POST /wallet/rollback
Reverse a debit that failed to complete (e.g., bet insertion error, oracle failure).
Request Body:
{
"player_id": "player_abc123",
"transaction_id": "550e8400-e29b-41d4-a716-446655440003",
"ref_transaction_id": "550e8400-e29b-41d4-a716-446655440001",
"round_id": "184721",
"amount": 100.00,
"currency": "USD",
"reason": "bet_insert_failure",
"session_token": "session_xyz789"
}| Rollback Reason | Description |
|---|---|
oracle_failure | Price oracle was unavailable during settlement |
bet_insert_failure | Bet was debited but failed to record in game state |
round_voided | Round cancelled due to price divergence or system error |
Response:
{
"transaction_id": "550e8400-e29b-41d4-a716-446655440003",
"balance": 1500.00
}POST /wallet/balance
Returns the player's current balance. Called periodically for balance display.
Request Body:
{
"player_id": "player_abc123",
"game_id": "velo_btc_5min"
}Response:
{
"balance": 1500.00
}Transaction Flow
A complete round lifecycle produces this sequence of wallet calls:
1. Player opens game
→ POST /wallet/authenticate
2. Player places bet ($100 on UP)
→ POST /wallet/debit (amount: 100.00)
3a. Player wins (round settles UP)
→ POST /wallet/credit (amount: 182.00, reason: "settle", is_round_finished: true)
3b. Player loses (round settles DOWN)
→ POST /wallet/credit (amount: 0.00, reason: "settle", is_round_finished: true)
3c. Player cashes out early
→ POST /wallet/credit (amount: 145.00, reason: "cashout", is_round_finished: false)Early Cashout
When is_round_finished: false, the round is still running for other players. Your accounting system should keep the round open until it receives a credit with is_round_finished: true.
Error Codes
Your wallet API should return structured error responses for failures:
{
"error_code": "INSUFFICIENT_FUNDS",
"message": "Player balance is insufficient for this bet"
}| Error Code | HTTP Status | Description |
|---|---|---|
INSUFFICIENT_FUNDS | 400 | Player cannot afford the bet |
PLAYER_NOT_FOUND | 400 | Unknown player ID |
PLAYER_BLOCKED | 400 | Player account is suspended or blocked |
SESSION_EXPIRED | 400 | Session token is no longer valid |
DUPLICATE_TRANSACTION | 400 | Transaction already processed (return original result) |
BET_LIMIT_EXCEEDED | 400 | Bet exceeds configured limits |
Retry Behavior
The RGS retries on 5xx errors with exponential backoff (200ms → 400ms → 800ms, max 3 attempts). 4xx errors are never retried — the RGS reads your error_code and handles it gracefully.
Security Checklist
- [ ] Verify
X-SignHMAC on every request - [ ] Store
API_SECRETsecurely (env variables, vault) - [ ] Use HTTPS (TLS 1.2+) for all endpoints
- [ ] Implement idempotency on
transaction_id - [ ] Validate
session_tokenon debit/credit/rollback - [ ] Set reasonable response timeout (< 2 seconds)