πŸŽ›οΈ Game API Β· Docs v1 Β· TND Β· RTP-controlled Get a keyDashboard

Developer documentation

Integrate a game in one call

A multi-tenant game API. Your server signs a launch request; we return a URL you drop in an <iframe>. The game runs in Tunisian Dinar under an RTP you control centrally β€” no game code, no wallet plumbing on your side.

Base URL  https://vortexsoftgaming.online Auth: HMAC-SHA256Format: form-urlencoded β†’ JSONCurrency: TND
πŸ’‘
Every endpoint below is relative to the base URL. Money and launch calls are signed and IP-whitelisted; the catalog is open. Your secret never touches the browser β€” signing happens server-side only.

Quickstart

The whole integration is: sign β†’ launch β†’ embed. From zero to a playable game:

PHP
Node.js
cURL
// 1. your credentials (from the Keys console)
$API    = 'https://vortexsoftgaming.online/api.php';
$KEY    = 'pk_xxxxxxxxxxxxxxxxxxxx';
$SECRET = 'your_api_secret';

// 2. sign the request (sorted params, HMAC-SHA256)
$p = ['api_key'=>$KEY, 'player'=>'user_42', 'game'=>'vswaysmadame'];
ksort($p);
$p['sign'] = hash_hmac('sha256', http_build_query($p), $SECRET);

// 3. launch β†’ get the iframe URL
$ch = curl_init($API.'?action=launch');
curl_setopt_array($ch,[CURLOPT_POST=>1,CURLOPT_POSTFIELDS=>http_build_query($p),CURLOPT_RETURNTRANSFER=>1]);
$res = json_decode(curl_exec($ch), true);

// 4. embed
echo '<iframe src="'.htmlspecialchars($res['launch_url']).'" allow="autoplay; fullscreen"></iframe>';

Get your keys

Open the Keys & Domains console and generate a key for your website. You choose:

FieldPurpose
api_keyPublic identifier sent with every request.
api_secretSigns requests (HMAC). Server-side only β€” shown once, regenerate anytime.
domainThe site allowed to embed the game (enforced via frame-ancestors).
allowed_ipsServer IPs / CIDR ranges allowed to call the API.
currencyPlayer wallet currency β€” TND by default.
🌐
The Keys console shows your current IP β€” add it to the whitelist so your test server can call the API immediately.

Authentication

Money and launch calls (launch, balance, deposit) must be signed. The signature proves the request came from you and wasn't tampered with. games needs only the api_key.

Signing algorithm

#Step
1Collect your parameters including api_key, excluding sign.
2Sort the keys ascending (ksort).
3Build a URL-encoded query string: k1=v1&k2=v2…
4sign = HMAC_SHA256(query_string, api_secret) as lowercase hex.
5POST all params plus sign.
// worked example
params  = { api_key:"pk_abc", game:"vswaysmadame", player:"user_42" }
sorted  = "api_key=pk_abc&game=vswaysmadame&player=user_42"
sign    = hmac_sha256(sorted, api_secret)   // e.g. 9f3c1a…
⚠
Sign on your server, never in client JavaScript β€” the secret must stay private. A wrong or missing signature returns bad_signature.

IP whitelist & domain lock

Two independent guards, both set per operator in the Keys console:

API β€” IP whitelist

When enforcement is on, only the listed server IPs (or IPv4 CIDR ranges) may call launch/balance/deposit. A blocked call returns ip_not_whitelisted and echoes the IP it saw, so you know exactly what to add.

203.0.113.7        # a single server
10.0.0.0/24        # a whole range
# blank list = no restriction (open)

Iframe β€” domain lock

The game page ships a Content-Security-Policy: frame-ancestors header built from your domain, so the game can only be embedded on your site. Set the domain and no other origin can iframe your sessions.

πŸ”Ž
Behind a proxy? The API reads REMOTE_ADDR. Set env TRUST_XFF=1 only if a trusted proxy fronts the platform, so it reads X-Forwarded-For.

Embedding the game

The launch_url is a normal page β€” put it in an iframe and give it room. It's fully responsive.

<!-- launch_url from the launch response -->
<iframe
  src="…/play.php?s=SESSION_TOKEN"
  style="width:100%;height:100vh;border:0"
  allow="autoplay; fullscreen"></iframe>

Each launch mints a fresh session bound to that one player + game. Call launch again to switch games or start a new session.

Endpoints

POST/api.php?action=launchsigned

Start a game session for a player and get the embed URL. Creates the player wallet on first use.

Parameters

ParamTypeNotes
api_key reqstringYour key.
player reqstringYour user's id (any stable string).
game reqstringGame symbol from the catalog, e.g. vswaysmadame.
start_balancenumberInitial TND balance for a new player (local wallet). Default 5000.
sign reqstringHMAC signature.

Response

{ "ok":true,
  "token":"8c9a…4ca7",
  "launch_url":"https://vortexsoftgaming.online/play.php?s=8c9a…4ca7" }
POST/api.php?action=balancesigned

Read a player's current TND balance.

ParamTypeNotes
api_key reqstringYour key.
player reqstringPlayer id.
sign reqstringHMAC signature.
{ "ok":true, "balance":4980.50, "currency":"TND" }
POST/api.php?action=depositsigned

Credit a player's local wallet (top-up / transfer model). Not used by seamless operators β€” there the balance lives on your side.

ParamTypeNotes
api_key reqstringYour key.
player reqstringPlayer id.
amount reqnumberTND to add (positive).
sign reqstringHMAC signature.
{ "ok":true, "balance":5980.50 }
GET/api.php?action=gamesapi_key only

List the enabled game catalog to build your lobby.

GET /api.php?action=games&api_key=pk_xxx

{ "ok":true, "games":[
  { "symbol":"vswaysmadame", "name":"Madame Destiny Megaways", "provider":"pragmatic", "category":"slots" },
  { "symbol":"vs20olympgold", "name":"Gates of Olympus Super Scatter", … }
] }

Wallet models

Pick per operator in the console. Both run the same RTP control.

ModelWho holds the balanceWhen to use
localWe do. You top up via deposit and read via balance.Fastest to integrate; demo & play-money sites.
seamlessYou do. We call your callback_url on every bet/win.Real-money sites with one wallet of record.

Player balance & the insufficient-funds popup

Every one of your users is a player with a TND balance (solde). They play against it, not against unlimited demo credits β€” the platform enforces the wallet as the real spending limit on the server, on every spin.

SituationWhat happens
Player can afford the betSpin proceeds; bet + governed win are booked to the wallet.
Bet exceeds the balanceThe spin is refused server-side β€” no wager is placed, the wallet can't go negative.
Balance too low to keep playingThe game shows a built-in β€œBalance insufficient” popup that blocks play.
Player tops upThe popup's Reload re-checks the balance (it also polls every few seconds) and dismisses once funded β€” play continues.

The popup is baked into the game page β€” nothing to build on your side. To fund a player, credit their wallet:

local β†’ call deposit from your cashier seamless β†’ your wallet is the source; just approve the next bet
πŸ’‘
Start a player with an opening balance via start_balance on the first launch (default 5000 TND). After that, top up with deposit or your seamless wallet.

Seamless wallet callback

If your wallet_mode is seamless, host an endpoint at your callback_url. We POST a signed debit/credit on every bet and win; you apply it to your wallet and return the new balance.

We send (form-urlencoded)

FieldNotes
api_keyYour key (identifies the operator).
playerPlayer id.
typebet or win.
amountSigned TND β€” bet is negative, win positive.
gameGame symbol.
tokenSession token.
refIdempotency key β€” ignore duplicates.
signHMAC (verify with your secret, same algorithm).

You return

{ "ok":true, "balance":4980.50 }   // the player's new balance, TND
⚠
Verify the signature and dedupe on ref β€” a retried callback must not double-charge. A runnable reference is in integration/seamless_callback.php.

RTP control

You don't set RTP per request β€” it's governed centrally. In the Dashboard you set a target payout ratio, volatility, bet limits and a max-win cap per operator and per game. Every booked win is scaled so the wallet's realised RTP (paid Γ· staked) tracks your target. Turn the governor off for pure pass-through. Realised RTP is shown live from the ledger.

Error codes

Errors return HTTP 200 with { "ok": false, "error": "…" }.

errorMeaning & fix
bad_api_keyUnknown or disabled key. Check the value; confirm the operator is active.
bad_signatureSignature mismatch. Re-check the sort, the exact query string, and the secret.
ip_not_whitelistedCaller IP not allowed. The response's your_ip shows what to add.
unknown_gameSymbol not in catalog or disabled. Use action=games.
game_disabled_for_operatorGame turned off for you in the dashboard.
upstream_unavailableCouldn't mint the game session. Transient β€” retry.
unknown_actionBad action value.

Go-live checklist

#Step
1Generate a key for your production domain in the Keys console.
2Add your production server IPs to the whitelist and enable enforcement.
3Store the secret in server config (never in the repo or client).
4Choose local or seamless; if seamless, deploy your callback and verify signatures + idempotency.
5Confirm the game embeds only on your domain (frame-ancestors) and RTP reads correctly in the dashboard.

Live base URL https://vortexsoftgaming.online β€” all endpoints are relative to it.