Skip to content

Game WebSocket API

The game WebSocket is the primary integration point between Velo's RGS and your frontend. It delivers real-time game state — round lifecycle, live odds, bet confirmations, and settlement results — over a single persistent connection.

No Price Feed Integration Needed

Velo handles all price sourcing internally (Binance for live prices, Pyth Network for settlement). Your frontend only needs to connect to this WebSocket and render the game state it receives. You do not need to integrate any price feeds yourself.

Connection

wss://your-rgs-host/ws/game/btc?gsid=YOUR_GAME_SESSION_ID

The gsid (game session ID) is obtained from the Game Launch API. It authenticates the player and links the WebSocket to their wallet session.

Message Format

All messages are JSON with a top-level type field:

json
{
  "type": "round_start",
  "round": { "id": 43, "entryPrice": 71310.25, ... }
}

Server → Client Messages

snapshot

Sent once on connection — contains the current game state so your UI can render immediately:

json
{
  "type": "snapshot",
  "history": [
    { "price": 71280.00, "timestamp": 1710437280000 },
    { "price": 71282.25, "timestamp": 1710437280200 }
  ],
  "round": {
    "id": 42,
    "entryPrice": 71284.50,
    "startTime": 1710437400000,
    "endTime": 1710437700000,
    "duration": 300000,
    "status": "active"
  },
  "odds": { "up": 1.82, "down": 2.05 }
}

player_info

Sent after snapshot — contains the player's balance and any active bets to restore:

json
{
  "type": "player_info",
  "player_id": "550e8400-...",
  "username": "JohnDoe",
  "balance": 1500.00,
  "currency": "USD",
  "active_bets": [
    { "id": "bet-uuid", "side": "up", "stake": 100, "odds": 1.82, "result": "pending" }
  ]
}

price_update

Live price tick, sent 5× per second. Use this to drive the chart:

json
{
  "type": "price_update",
  "price": 71290.75,
  "remaining": 142000,
  "timestamp": 1710437558000
}

odds_update

Updated payout multipliers, sent approximately every second:

json
{
  "type": "odds_update",
  "up": 1.82,
  "down": 2.05,
  "sigma": 0.42,
  "players_online": 34,
  "pool_up": 2400.00,
  "pool_down": 1800.00
}
FieldDescription
up / downPayout multiplier for each side
sigmaCurrent annualized volatility
players_onlineConnected WebSocket clients
pool_up / pool_downTotal stakes on each side

round_start

New 5-minute round begins:

json
{
  "type": "round_start",
  "round": {
    "id": 43,
    "entryPrice": 71310.25,
    "startTime": 1710437700000,
    "endTime": 1710438000000,
    "duration": 300000,
    "status": "active"
  }
}

round_lock

10-second lock buffer activates — no more bets accepted:

json
{
  "type": "round_lock",
  "round": {
    "id": 43,
    "entryPrice": 71310.25,
    "startTime": 1710437700000,
    "endTime": 1710438000000,
    "duration": 300000,
    "status": "locked"
  }
}

round_settle

Round settled via Pyth Network oracle — includes the verifiable proof URL:

json
{
  "type": "round_settle",
  "round": {
    "id": 43,
    "entryPrice": 71310.25,
    "settlementPrice": 71342.80,
    "startTime": 1710437700000,
    "endTime": 1710438000000,
    "duration": 300000,
    "status": "settled",
    "result": "up",
    "pythVerificationUrl": "https://hermes.pyth.network/..."
  }
}

bet_confirmed

Sent to the player who placed the bet:

json
{
  "type": "bet_confirmed",
  "bet_id": "550e8400-...",
  "round_id": 184721,
  "side": "up",
  "stake": 100.00,
  "odds": 1.82,
  "balance": 1400.00
}

bet_settle

Sent per-player when their bet settles:

json
{
  "type": "bet_settle",
  "bet_id": "550e8400-...",
  "player_id": "player-uuid",
  "result": "win",
  "payout": 182.00,
  "balance": 1582.00
}

cashout_result

Sent after a successful early cashout:

json
{
  "type": "cashout_result",
  "bet_id": "550e8400-...",
  "cashout_value": 145.00,
  "pyth_price": 71325.50,
  "pyth_verification_url": "https://hermes.pyth.network/...",
  "balance": 1545.00
}

Client → Server Messages

place_bet

Place a bet on the current round:

json
{
  "type": "place_bet",
  "side": "up",
  "stake": 100.00,
  "odds": 1.82
}

INFO

The player_id is resolved from the gsid session — you don't need to send it.

cashout_request

Request an early cashout on an active bet:

json
{
  "type": "cashout_request",
  "bet_id": "550e8400-...",
  "side": "up",
  "stake": 100.00,
  "odds": 1.82
}

pause

Operator pauses gameplay (AML/fraud/responsible gaming). All bet attempts are rejected until resumed.

json
{ "type": "pause" }

Response: { "type": "paused" }

resume

Operator resumes gameplay after a pause.

json
{ "type": "resume" }

Response: { "type": "resumed" }

balance_update

Operator notifies the game of an external deposit or withdrawal. The game forwards this to the player's UI.

json
{
  "type": "balance_update",
  "stake": 2500.00
}

Response: { "type": "balance_update", "balance": 2500.00 }

TIP

The stake field is reused to carry the new balance value. The game forwards it as balance to the client.

Client Example

javascript
const ws = new WebSocket('wss://your-rgs-host/ws/game/btc?gsid=YOUR_GSID');

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  switch (msg.type) {
    case 'snapshot':
      initChart(msg.history);
      if (msg.round) setRound(msg.round);
      break;
    case 'player_info':
      setBalance(msg.balance);
      restoreBets(msg.active_bets);
      break;
    case 'price_update':
      updateChart(msg.price);
      break;
    case 'odds_update':
      updateOdds(msg.up, msg.down);
      break;
    case 'round_start':
      resetRound(msg.round);
      break;
    case 'round_settle':
      showResult(msg.round);
      break;
    case 'bet_confirmed':
      confirmBet(msg);
      break;
    case 'bet_settle':
      settleBet(msg);
      break;
  }
};

// Place a bet
ws.send(JSON.stringify({
  type: 'place_bet',
  side: 'up',
  stake: 100,
  odds: 1.82
}));

B2B Integration Documentation