API key, approved source IP and merchant domain.
Your catalog.
Your players. Your wallet.
Load categories, providers and games from one API. Launch a game inside your website and apply authenticated wallet events to your own player accounts.
https://casinos.betapidata.onlineSix-digit game IDs and CDN artwork URLs.
Your callback owns the player's available balance.
Authenticate every API request
Obtain your merchant API key and register your backend's outbound public IP, player-site hostname, HTTPS lobby and wallet callback URL. Send these headers from your server:
Authorization: Bearer YOUR_CASINO_API_KEY
X-Merchant-Domain: merchant.example
Accept: application/jsonUse the bare approved hostname in X-Merchant-Domain, without a scheme or path. Keys are private. An approved domain header does not replace the source-IP check. If you send an Origin header, its hostname must match the merchant domain.
The Casino API uses its own merchant key and callback signature format. Do not reuse the Exchange API's headers or signing algorithm.
Your account currency and access mode are configured per merchant. Cache catalog data in your system instead of fetching the entire catalog on each page view. The service currently limits authenticated requests to 180 per minute per merchant; handle HTTP 429 with backoff.
Build your game lobby
/v1/catalog/categoriesReturns {"success":true,"data":[...]}. Each category includes category_id, name, sort_order, icon_frames and icon_url.
/v1/catalog/providers?category_id=4The category filter is optional; use IDs returned by the catalog. Providers include provider_id, provider_code, display_name, icon_url, sort_order, game_count and a subproviders array. Child providers include subprovider_id, brand_id, name and icon_url.
/v1/catalog/games?page=1&limit=50| Query field | Behavior |
|---|---|
| page / limit | Page starts at 1. Default limit 50, maximum 100. |
| category_id | Filter by category ID. |
| provider_id | Filter by provider ID. |
| subprovider_id | Filter by child-provider ID. |
| q | Search game names, up to 80 characters. |
| hot=1 | Return only featured hot games. |
{
"success": true,
"data": [],
"pagination": { "page": 1, "limit": 50, "total": 0, "pages": 0 }
}Each game includes game_id, game_name, image_url, image_status, category/provider references and provider names. Use the returned CDN URLs for artwork; do not construct upstream image URLs. Load further catalog pages on your backend when synchronizing all games.
/v1/games/100001Returns one active game's details under data. The ID above is illustrative: launch an actual six-digit ID returned by your catalog.
Create a player game session
/v1/launchProduction merchants use this endpoint. Authenticate the player in your own system first, then send JSON from your backend with the authentication headers above and Content-Type: application/json.
| JSON field | Requirement |
|---|---|
| game_id | Required six-digit integer from the catalog. |
| player_id | Required stable positive numeric player reference of 1–6 digits, without leading zeroes. Send your own merchant-scoped player ID. |
| currency_code | Three-letter currency matching the merchant configuration, such as BDT. Defaults to the configured currency if omitted. |
| language | Optional game language, such as en. |
| platform | Optional device flag, such as web. |
curl --request POST 'https://casinos.betapidata.online/v1/launch' \
--header "Authorization: Bearer $CASINO_API_KEY" \
--header 'X-Merchant-Domain: merchant.example' \
--header 'Content-Type: application/json' \
--data '{
"game_id": 100001,
"player_id": "123456",
"currency_code": "BDT",
"language": "en",
"platform": "web"
}'Successful response
{
"success": true,
"launch_id": 123,
"game_id": 100001,
"game_name": "Example game",
"transfer_id": "LAUNCH_REFERENCE",
"game_url": "HTTPS_GAME_SESSION_URL",
"demo_mode": false,
"betting_enabled": true
}The response is illustrative. Treat game_url as a private session URL and open only the value returned by a successful backend response. Do not invent a URL from a game ID or expose your API key to the player.
Test mode
/v1/test/launchUse the same JSON fields with a merchant configured in test mode. Test games start with zero credit and wagers are disabled. A successful test launch verifies access and display only; it does not prove production wallet settlement works.
Open the game in your website
<iframe
title="Casino game"
src="GAME_URL_FROM_YOUR_BACKEND"
allow="fullscreen; autoplay"
referrerpolicy="no-referrer"
style="width:100%;height:100dvh;border:0"
></iframe>Provide your own close control and game title around the iframe. Keep API and callback processing on your server. Display a friendly “This game is unavailable. Please try again later.” message for failed launches and log diagnostic details privately. Browser same-origin restrictions prevent your page from reading a different site's iframe document or reliably detecting every error inside that document.
Process signed wallet events
We POST JSON to your registered HTTPS callback. The callback hostname must be approved for your merchant, resolve to a public address and present a valid TLS certificate. Redirect responses are not followed.
Content-Type: application/json
Idempotency-Key: STABLE_EVENT_KEY
X-Betapidata-Timestamp: UNIX_SECONDS
X-Betapidata-Signature: LOWERCASE_HEX_HMAC_SHA256
X-Betapidata-Request-Id: REQUEST_REFERENCEExample bet event
{
"merchant_code": "YOUR_MERCHANT_CODE",
"player_id": "123456",
"player_uid": "player123",
"game_id": 100001,
"game_name": "Example game",
"action": "bet",
"bet_amount": 10,
"win_amount": 0,
"txn_id": "UNIQUE_TRANSACTION_REFERENCE",
"game_round": "ROUND_REFERENCE",
"currency_code": "BDT",
"timestamp": "2026-10-26 12:00:00"
}player_id and player_uid contain your original player reference. Store long transaction and round IDs as strings. Check the merchant, player and currency before applying any balance change.
| Action | Apply once to the player's wallet |
|---|---|
| bet | Deduct bet_amount; refuse insufficient available funds. |
| win | Credit win_amount. |
| bet_win | Apply win_amount - bet_amount atomically, checking funds for the bet. |
| refund | Credit refund_amount once after validating the original deduction. The supplied bet/win fields may carry the refund value; do not apply them as another bet or win. |
| deposit_required | Informational notice. Do not change the wallet. Return current balance. |
Successful response
{ "balance": 123.45, "status": true }Return a numeric, finite, non-negative balance after your database transaction commits. HTTP 2xx is required; data.balance is also accepted. A failure must not claim success or overwrite your stored balance with zero. The numeric balance is the player's wallet balance, not the merchant's service wallet.
Verify the raw callback body
The signing key is the binary SHA-256 digest of your Casino API key. Sign X-Betapidata-Timestamp + "\n" + raw_request_body with HMAC-SHA256 and compare its lowercase hexadecimal digest in constant time. This is different from the Exchange signature format.
<?php
$raw = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_BETAPIDATA_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_BETAPIDATA_SIGNATURE'] ?? '';
$apiKey = getenv('CASINO_API_KEY');
if (!is_string($raw) || strlen($raw) > 65536
|| !is_string($apiKey) || $apiKey === ''
|| !ctype_digit($timestamp)
|| abs(time() - (int)$timestamp) > 300
|| !preg_match('/^[a-f0-9]{64}$/D', $signature)) {
http_response_code(401);
exit;
}
$key = hash('sha256', $apiKey, true);
$expected = hash_hmac('sha256', $timestamp . "\n" . $raw, $key);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit;
}
$event = json_decode($raw, true, 32, JSON_THROW_ON_ERROR);
Authenticate the original bytes before decoding JSON. Re-encoding the request changes the signature input. A valid signature alone does not replace transaction deduplication or player/currency checks.
Protect every debit, credit and refund
- Keep a unique database key for merchant plus
txn_id. Validate that repeated IDs have the same financial payload. - Lock the player's wallet row, validate the event, apply the amount with exact decimal arithmetic and store the transaction result in one atomic commit.
- For a duplicate successful transaction, acknowledge it without changing funds again.
- Keep failed and uncertain events for reconciliation. A timeout may happen after your wallet committed; a retried event must not debit or credit twice.
- Link refunds to the original transaction or round. Validate cumulative refunded amounts and never credit the same refund twice.
Only an authenticated, validated refund event or a reconciled confirmed reversal should release a deducted amount. A launch error or lost network response alone is not proof that a wager failed.
Handle failures on your backend
{ "success": false, "error": "currency_mismatch" }| Status / error | Action |
|---|---|
| 401 · unauthorized | Check your private merchant key. |
| 403 · source_ip_not_allowed | Confirm the actual outbound server IP is approved. |
| 403 · merchant_domain_required / merchant_domain_not_allowed / origin_mismatch | Check the hostname header and domain configuration. |
| 403 · merchant_inactive / merchant_mode_not_allowed | Check activation and select the endpoint for your merchant mode. |
| 404 · game_not_found | Refresh the catalog; the game may no longer be active. |
| 422 · invalid_launch_request / currency_mismatch | Correct the game ID, player reference or configured currency. |
| 402 · ggr_wallet_limit_reached | Contact the merchant account owner to restore service credit. |
| 429 · rate_limited | Back off, reduce concurrent requests and cache catalog data. |
| 5xx | Show a friendly unavailable message; keep diagnostics private. Avoid repeated automatic launches. |
Do not display raw provider responses, credentials or internal diagnostics to players. For help, contact @devzorvix with the request reference and time, without sharing secret keys.