B2B API Integration Guide

Welcome to the Win20X Developer Documentation. Our platform enables seamlessly embedding 100+ top-tier casino game suppliers (including Aviator, Slots, Table Games, and Live dealers) directly into your website via a unified B2B gateway.

This integration is executed in an A-Z flow: retrieving providers, fetching game lists, generating launch links, and processing transactional webhooks on your player ledger.

API Credentials & Authentication

All outbound API requests from your server to our gateway must connect over HTTPS to https://api.win20x.com and present B2B credentials in the request headers.

Header Name Description
x-api-key Your B2B Client API Key (issued via your B2B Client Portal).
x-api-secret Your B2B Client API Secret (issued via your B2B Client Portal).

Note: API requests will be rejected unless the originating server IP address is whitelisted in your B2B dashboard.

1. Retrieve Game Providers

Fetch all active game suppliers integrated on the SaaS gateway.

GET /api/v1/getallproviders

Sample Response:

{
  "success": true,
  "message": "All games grouped by provider fetched successfully",
  "games": [
    "SPRIBE",
    "EVOPLAY",
    "PRAGMATIC",
    "ODIN"
  ]
}

2. Retrieve Games List

Retrieve the complete game portfolio mapping of a specific supplier.

GET /api/v1/getallgamesandprovider?provider={providerName}

Query Parameters:

Param Type Required Description
provider string Yes E.g. SPRIBE or EVOPLAY

Sample Response:

{
  "success": true,
  "message": "All games for EVOPLAY fetched successfully",
  "games": [
    {
      "id": "75f81c56565d394503f544f3431ef370",
      "name": "Aviator",
      "provider_name": "SPRIBE",
      "game_type": "crash"
    }
  ]
}

3. Generate Game Session URL

Requests a secure session launcher link to frame or load the game for your player. When you call this, player balances are automatically synchronized with our transaction ledger.

POST /api/v1/getgameurl

JSON Body Parameters:

Param Type Required Description
username string Yes Your player's unique username or ID on your system.
gameId string Yes The unique game code (from Step 2).
money number Yes The player's current balance in BDT (৳) (Decimal format).
platform number Yes 1 for Desktop, 2 for Mobile/Tablet.
currency string Yes Must pass BDT.
home_url string Yes The absolute redirect target URL when the player exits the game session.
lang string No Language (defaults to en).

Sample Response:

{
  "success": true,
  "msg": "SUCCESS",
  "url": "https://api.win20x.com/lobby/launcher?session_token=p_1_user99&game=aviator"
}

4. Inbound Transaction Callbacks

During game play (placing bets, wins, and bonus updates), our system will send HTTP POST webhooks back to your registered Inbound Callback Webhook URL. Your backend must listen to these events, update the player balance on your system in real-time, and return a successful JSON confirmation.

POST Request Payload:

{
  "bet_amount": 100.0000,
  "win_amount": 250.0000,
  "member_account": "p_1_user99",
  "game_uid": "75f81c56565d394503f544f3431ef370",
  "game_round": "round_unique_12345",
  "currency_code": "BDT",
  "api_key": "wjr4_api_key_xyz",
  "serial_number": "txn_unique_serial_556"
}

Required Response Body (JSON, HTTP Status 200):

{
  "success": true,
  "message": "Callback processed successfully"
}

Callback Security & Webhook Rules

To avoid security vulnerabilities (such as double payout exploits or replay attacks), your system must strictly follow these rules:

  1. Validate the API Key: Check that the incoming api_key in the payload matches your own B2B API Key.
  2. Player Username Masking: The incoming member_account will contain the internal masked player token we generated (e.g. p_{clientId}_{username}). Map this back to your user.
  3. Strict Idempotency Check: Log the unique transaction serial_number in your database. If you receive a webhook with a serial_number that is already marked as processed in your ledger, do not deduct or credit balances again. Simply respond with success 200 OK immediately.
  4. Atomic Ledger Updates: Calculate: New Balance = Current Balance - bet_amount + win_amount in a single database transaction.

Integration Code Snippets

PHP Callback Handler
NodeJS / Express Handler
<?php
// Inbound callback route (listen at your registered callback URL)
header('Content-Type: application/json');

$input = file_get_contents('php://input');
$data = json_decode($input, true);

// 1. Basic validation
if (!$data || !isset($data['serial_number']) || !isset($data['member_account'])) {
    echo json_encode(['success' => false, 'message' => 'Malformed payload']);
    exit;
}

$apiKey = $data['api_key'];
$memberAccount = $data['member_account'];
$betAmount = (float)$data['bet_amount'];
$winAmount = (float)$data['win_amount'];
$serialNumber = $data['serial_number'];

// 2. Validate API Key
$myApiKey = "YOUR_API_KEY"; // Set your API key here
if ($apiKey !== $myApiKey) {
    echo json_encode(['success' => false, 'message' => 'Unauthorized']);
    exit;
}

// Connect to Database
$db = new PDO('mysql:host=localhost;dbname=casino', 'db_user', 'db_pass');

try {
    $db->beginTransaction();

    // 3. Idempotency Check
    $stmt = $db->prepare("SELECT 1 FROM processed_txs WHERE serial_number = ? FOR UPDATE");
    $stmt->execute([$serialNumber]);
    if ($stmt->fetch()) {
        $db->rollBack();
        echo json_encode(['success' => true, 'message' => 'Duplicate transaction']);
        exit;
    }

    // Extract player ID from secure token (p_{clientId}_{username})
    $parts = explode('_', $memberAccount);
    $playerUsername = end($parts);

    // Lock player balance row
    $userStmt = $db->prepare("SELECT balance FROM users WHERE username = ? FOR UPDATE");
    $userStmt->execute([$playerUsername]);
    $user = $userStmt->fetch(PDO::FETCH_ASSOC);

    if (!$user) {
        $db->rollBack();
        echo json_encode(['success' => false, 'message' => 'Player not found']);
        exit;
    }

    $currentBalance = (float)$user['balance'];
    $newBalance = $currentBalance - $betAmount + $winAmount;

    if ($newBalance < 0) {
        $db->rollBack();
        echo json_encode(['success' => false, 'message' => 'Insufficient funds']);
        exit;
    }

    // Update player balance
    $updateStmt = $db->prepare("UPDATE users SET balance = ? WHERE username = ?");
    $updateStmt->execute([$newBalance, $playerUsername]);

    // Record serial number to prevent replay attacks
    $logStmt = $db->prepare("INSERT INTO processed_txs (serial_number, amount) VALUES (?, ?)");
    $logStmt->execute([$serialNumber, $winAmount - $betAmount]);

    $db->commit();
    echo json_encode(['success' => true, 'message' => 'Callback processed successfully']);

} catch (Exception $e) {
    $db->rollBack();
    echo json_encode(['success' => false, 'message' => 'Database transaction failed: ' . $e->getMessage()]);
}