WE CREATE GREAT GAMES TOGATHER AS A TEAM

Join Us

API Guide

Veto Play API Guide

Controller Base Path: /api/game-client

Document Scope: This integration includes 4 APIs: 2 provided by Veto Play and 2 that must be provided by the client.

Encryption rule: /game-list does not require encryption. For /launch, /balance, and /coin-transaction, keep wrapper fields such as clientUid and timestamp in plain text and encrypt only the inner payload.

Base URL

https://api.example.com/api/game-client

Integration Overview

No. Method API Provided By Purpose
1 GET /game-list Veto Play Returns the available game list for the client.
2 POST /launch Veto Play Launches the selected game and returns the game launch URL.
3 POST /balance Client Checks the player's exact balance from the client before bet deduction logic runs.
4 POST /coin-transaction Client Requests player coin deduction or addition and returns either the updated balance on success or a failure response.

Usage Flow

Step Method Endpoint Provided By Encryption Purpose
1 GET /game-list Veto Play Not required Fetch the available game list using required clientUid.
2 POST /launch Veto Play Required for payload only Launch the selected game and receive the session token and launch URL.
3 POST /balance Client Client defined Fetch the player's exact balance from the client before bet deduction.
4 POST /coin-transaction Client Client defined Send the debit request when the player clicks play and return success with balance or failure.
5 POST /coin-transaction Client Client defined After the game result, send the credit request only when the win amount is greater than 0 and return success with balance or failure.

1. Get Games

Method: GET

Endpoint: /api/game-client/game-list?clientUid=<YOUR_PURCHASED_CLIENT_UID>

Encryption: Not required

Purpose: Returns the configured game list.

Required Query Param: clientUid

Sample Request:

GET /api/game-client/game-list?clientUid=<YOUR_PURCHASED_CLIENT_UID>

Sample Response:

{
  "success": true,
  "http_status": 200,
  "game_type": "all",
  "total": 21,
  "games": [
    {
      "game_uuid": "pyramid_slot",
      "game_icon": "https://cdn.example.com/games/slot1.png",
      "game_name": "Pyramid Slot",
      "game_category": "slot",
      "status": 1
    },
    {
      "game_uuid": "pirates_slot",
      "game_icon": "https://cdn.example.com/games/slot1.png",
      "game_name": "Pirates Slot",
      "game_category": "slot",
      "status": 1
    }
  ]
}

2. Launch Game

Method: POST

Endpoint: /api/game-client/launch

Encryption: Required for the inner payload

Plain Payload Before Encryption

{
  "user_name": "Veto_user_name",
  "user_name_to_display": "player_name",
  "game_uuid": "pyramid_slot",
  "coins": 1000.00,
  "redirect_url": "https://client.example.com/game-exit"
}

Request Body After Encryption

{
  "clientUid": "<YOUR_PURCHASED_CLIENT_UID>",
  "payload": "<encrypted payload>"
}

Request Rules

Field Required Description
clientUid Yes Client identifier sent in plain text.
payload Yes Encrypted string created from the inner JSON payload.

Inner Payload Fields

Field Required Description
user_name Yes Unique user ID.
game_uuid Yes Unique game ID. Example: pyramid_slot
user_name_to_display Yes Player name shown inside the game.
coins Yes Player coin balance.
redirect_url Yes Failover URL used when the game exits or cannot continue.

Encryption Note

Convert the inner payload JSON to a string, encrypt it using AES-256-GCM and your assigned 32-byte key, then place the encrypted result into the outer payload field.

Sample Response

{
  "success": true,
  "http_status": 200,
  "session_token": "e0cbb392f715482580df8177ad19c058",
  "game_uuid": "pushpa_rani",
  "user_name": "test_player_01",
  "user_name_to_display": "player_name",
  "game_launch_url": "https://games.example.com/launch?token=e0cbb392f715482580df8177ad19c058",
  "coins": 7657.8
}

Response Fields

Field Required Description
success Yes Returns true when the game launch request is successful.
http_status Yes HTTP status code. Example: 200
session_token Yes Session token generated for the launched game session.
game_uuid Yes Unique game ID.
user_name Yes Unique user ID.
user_name_to_display Yes Display player name shown inside the game.
game_launch_url Yes Game launch URL returned by the API.
coins Yes Player coin balance returned in the launch response.

3. Client API - Balance

Method: POST

Endpoint: /balance

Direction: This API must be provided by the client end.

Purpose: Checks the player's exact balance from the client before bet deduction logic runs.

Behavior: This endpoint is used only to read the current balance. It must not deduct or add coins.

Request Body

{
  "clientUid": "<YOUR_PURCHASED_CLIENT_UID>",
  "timestamp": "1744112345678",
  "payload": "<AES_ENCRYPTED_BASE64>"
}

Outer Request Body Fields

Field Required Description
clientUid Yes Client identifier sent in plain text.
timestamp Yes Request timestamp in milliseconds.
payload Yes AES-256-GCM encrypted inner JSON payload encoded in Base64.

Decrypted Payload

{
  "user_name": "player_001",
  "game_round": "pyramid_slot_26-04-08-12:00_abc123",
  "currency_code": "INR",
  "timestamp": "1744112345678",
  "mode": "balance",
  "coins": 0
}

Note: For /balance, send mode as balance and coins as 0.

Decrypted Payload Fields

Field Required Description
user_name Yes Unique player ID.
game_round Yes Game round reference sent by the game server.
currency_code Yes Currency code. Example: INR
timestamp Yes Current timestamp in milliseconds.
mode Yes Always send balance for this endpoint.
coins Yes Send 0 for balance requests.

Expected Response

{
  "payload": "<AES_ENCRYPTED_BASE64>"
}

Outer Response Body Fields

Field Required Description
payload Yes Encrypted response payload containing the current balance.

Decrypted Response Payload

{
  "balance": 10000.0
}

Decrypted Response Payload Fields

Field Required Description
balance Yes Current player coin balance after processing the request.

4. Client API - Coin Transaction

Method: POST

Endpoint: /coin-transaction

Direction: This API must be provided by the client end.

Purpose: Sends a debit or credit request to the client to deduct or add player coins, and each response must return either success with the updated balance or a failure response.

Behavior: When the player clicks play, Veto Play sends a debit request with the bet amount. If the client returns success, the round proceeds. After the result, Veto Play sends a credit request only when the win amount is greater than 0.

Request Body

{
  "clientUid": "<YOUR_PURCHASED_CLIENT_UID>",
  "timestamp": "1744112345678",
  "payload": "<AES_ENCRYPTED_BASE64>"
}

Outer Request Body Fields

Field Required Description
clientUid Yes Client identifier sent in plain text.
timestamp Yes Request timestamp in milliseconds.
payload Yes AES-256-GCM encrypted inner JSON payload encoded in Base64.

Decrypted Payload

{
  "user_name": "player_001",
  "game_round": "pyramid_slot_26-04-08-12:00_abc123",
  "currency_code": "INR",
  "timestamp": "1744112345678",
  "mode": "debit",
  "coins": 100
}

Note: For /coin-transaction, use mode as debit or credit. coins is the transaction amount.

Credit Request Example

{
  "user_name": "player_001",
  "game_round": "pyramid_slot_26-04-08-12:00_abc123",
  "currency_code": "INR",
  "timestamp": "1744112356789",
  "mode": "credit",
  "coins": 250
}

Credit Rule: After the game result, send coins as the win amount only when the win amount is greater than 0. If the player did not win, do not call the credit API.

Decrypted Payload Fields

Field Required Description
user_name Yes Unique player ID.
game_round Yes Game round reference sent by the game server.
currency_code Yes Currency code. Example: INR
timestamp Yes Current timestamp in milliseconds.
mode Yes Transaction type. Use debit when deducting the bet amount and credit after the result.
coins Yes Transaction amount. For debit, send the bet amount. For credit, send the win amount only when it is greater than 0.

Success Response

{
  "payload": "<AES_ENCRYPTED_BASE64>"
}

Success Rule: Both debit and credit responses must return success with the latest balance.

Outer Response Body Fields

Field Required Description
payload Yes Encrypted response payload containing the updated balance for a successful transaction.

Decrypted Response Payload

{
  "success": true,
  "balance": 9900.0
}

Decrypted Response Payload Fields

Field Required Description
success Yes Returns true when the coin transaction is completed successfully.
balance Yes Updated player coin balance after the debit or credit transaction.

Failure Response - Bet Rejected

If a debit request cannot be completed because the player has insufficient balance, return this failure response instead of a success balance response:

{
  "success": false,
  "http_status_code": 100118,
  "message": "Bet rejected due to insufficient balance"
}

Failure Rule: If the debit call fails, the bet must not proceed. If a credit call fails, return a failure response instead of success.

Encryption Logic

This section shows cross-language AES-256-GCM encryption and decryption examples for the payload field used by POST /launch, /balance, and /coin-transaction.

Encryption Standard

Algorithm: AES-256-GCM

Component Size
Key 32 bytes (256 bits)
IV (Nonce) 12 bytes
Authentication Tag 16 bytes
Payload Format Base64(IV + Ciphertext + Tag)

Shared Key Example (32 bytes):

0123456789abcdef0123456789abcdef

Payload Structure

After encryption the payload format is:

Base64(
    IV (12 bytes)
    + Ciphertext
    + AuthTag (16 bytes)
)

Example API Request:

{
  "payload": "Base64EncodedEncryptedData"
}

JavaScript (Node.js) Implementation

Encrypt:

const crypto = require("crypto");

const key = Buffer.from("0123456789abcdef0123456789abcdef");

function encrypt(data) {

    const iv = crypto.randomBytes(12);

    const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);

    let encrypted = cipher.update(JSON.stringify(data), "utf8");
    encrypted = Buffer.concat([encrypted, cipher.final()]);

    const tag = cipher.getAuthTag();

    const payload = Buffer.concat([iv, encrypted, tag]).toString("base64");

    return payload;
}

// Example
console.log(encrypt({amount:5000,currency:"INR"}));

Decrypt:

function decrypt(payload) {

    const data = Buffer.from(payload, "base64");

    const iv = data.slice(0,12);
    const tag = data.slice(data.length-16);
    const ciphertext = data.slice(12,data.length-16);

    const decipher = crypto.createDecipheriv("aes-256-gcm", key, iv);
    decipher.setAuthTag(tag);

    let decrypted = decipher.update(ciphertext);
    decrypted = Buffer.concat([decrypted, decipher.final()]);

    return decrypted.toString();
}

Java Implementation (Core Java)

Encrypt:

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;
import java.nio.ByteBuffer;

public class AESUtil {

    private static final byte[] KEY =
            "0123456789abcdef0123456789abcdef".getBytes();

    public static String encrypt(String text) throws Exception {

        byte[] iv = new byte[12];
        new SecureRandom().nextBytes(iv);

        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

        SecretKeySpec keySpec = new SecretKeySpec(KEY,"AES");

        cipher.init(Cipher.ENCRYPT_MODE,keySpec,
                new GCMParameterSpec(128,iv));

        byte[] encrypted = cipher.doFinal(text.getBytes());

        ByteBuffer buffer =
                ByteBuffer.allocate(iv.length + encrypted.length);

        buffer.put(iv);
        buffer.put(encrypted);

        return Base64.getEncoder().encodeToString(buffer.array());
    }
}

Decrypt:

public static String decrypt(String payload) throws Exception {

    byte[] decoded = Base64.getDecoder().decode(payload);

    byte[] iv = new byte[12];
    System.arraycopy(decoded,0,iv,0,12);

    byte[] cipherTag = new byte[decoded.length - 12];
    System.arraycopy(decoded,12,cipherTag,0,cipherTag.length);

    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

    SecretKeySpec keySpec = new SecretKeySpec(KEY,"AES");

    cipher.init(Cipher.DECRYPT_MODE,keySpec,
            new GCMParameterSpec(128,iv));

    byte[] plaintext = cipher.doFinal(cipherTag);

    return new String(plaintext);
}

PHP Implementation

Encrypt:

function encrypt($plaintext,$key){

    $iv = random_bytes(12);

    $ciphertext = openssl_encrypt(
        $plaintext,
        'aes-256-gcm',
        $key,
        OPENSSL_RAW_DATA,
        $iv,
        $tag
    );

    $payload = base64_encode($iv.$ciphertext.$tag);

    return $payload;
}

$key="0123456789abcdef0123456789abcdef";

echo encrypt("Hello API",$key);

Decrypt:

function decrypt($payload,$key){

    $data = base64_decode($payload);

    $iv = substr($data,0,12);
    $tag = substr($data,-16);
    $ciphertext = substr($data,12,-16);

    return openssl_decrypt(
        $ciphertext,
        'aes-256-gcm',
        $key,
        OPENSSL_RAW_DATA,
        $iv,
        $tag
    );
}

Example Cross-Language Flow

JavaScript Client
   |
   | encrypt request
   v
API Request
payload = Base64(IV + ciphertext + tag)
   |
   v
Java Server
decrypt(payload)
process request
encrypt(response)
   |
   v
PHP Client
decrypt(response)

Security Best Practices

Summary

Item Value
Encryption AES-256-GCM
Key Length 32 bytes
IV Length 12 bytes
Tag Length 16 bytes
Payload Format Base64(IV + Ciphertext + Tag)

Error Codes

http_status Meaning
200 Success
100110 Invalid clientUid or partner disabled.
100111 AES payload decryption failed.
100112 game_uuid not found in game list.
100113 Duplicate active bet.
100114 Missing required field in request.
100115 Session token invalid or expired.
100116 Input validation failed.
100117 Internal server error or partner callback failed.
100118 Bet rejected due to insufficient balance.

Error Format

When the API returns an error, the response format is:

{
  "success": false,
  "http_status_code": 100115,
  "message": "Invalid or expired session token"
}