Lleva 500 juegos provably fair a tu casino
Una clave API. Wallet de POL integrada. Sin cuota de alta ni mensualidad: solo nos quedamos con un 15% de revenue share del GGR que generan tus jugadores. ¿No programas? Descarga nuestro script de casino gratuito y sal en vivo en 5 minutos.
POST /api/v1/sessions
{
"player_id": "42",
"username": "alice",
"game": "banana-splash"
}
→ { "launch_url": "https://…/embed.php?token=…" }Obtén tus claves
Regístrate, completa tu marca y sitio: tu API key y secret se crean al instante.
Conecta tu wallet
Añade la URL de callback de tu wallet (o instala el script gratuito, que la incluye) y ejecuta la prueba integrada.
Salir en vivo
Lista los juegos con GET /games y lánzalos con POST /sessions. Paga la factura de revenue share semanal en POL.
Overview
The Polygon Casino Partner API lets you put all of our provably fair games on your own website. It is free: we earn a revenue share of the gross gaming revenue (GGR) your players generate. Players keep their balance on your site — our game server talks to your wallet endpoint (“seamless wallet”) to take bets and pay wins in POL.
- Create a partner account and copy your API key and API secret.
- Implement the wallet callback on your server and save its URL in the panel.
- Call
GET /gamesto list games, thenPOST /sessionsto get alaunch_urland open it in an iframe. - Pay the revenue share invoice each period. Unpaid invoices suspend the API automatically.
Prefer not to code? Download the free casino script from the panel — it implements everything below.
Base URL & authentication
Base URL: https://polygoncasinos.net/api/v1Fallback (no URL rewriting): https://polygoncasinos.net/api/v1/index.php?route=games
Every request must include three headers:
| Header | Value |
|---|---|
X-API-Key | Your public key, e.g. pk_your_api_key |
X-Timestamp | Current unix time in seconds (must be within ±5 minutes) |
X-Signature | hex( HMAC_SHA256( secret, timestamp + "." + raw_body ) ) — for GET requests the body is an empty string |
All responses are JSON: {"ok":true,...} or {"ok":false,"error":"CODE","message":"..."} with a matching HTTP status. Amounts are POL with 8 decimals.
PHP example
function pc_api(string $method, string $route, ?array $body = null) {
$key = 'pk_your_api_key'; $secret = 'sk_your_secret';
$raw = $body === null ? '' : json_encode($body);
$ts = (string) time();
$sig = hash_hmac('sha256', $ts . '.' . $raw, $secret);
$ch = curl_init('https://polygoncasinos.net/api/v1/' . $route);
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_POSTFIELDS => $body === null ? null : $raw,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', "X-API-Key: $key", "X-Timestamp: $ts", "X-Signature: $sig"]]);
return json_decode(curl_exec($ch), true);
}
$games = pc_api('GET', 'games');
$s = pc_api('POST', 'sessions', ['player_id' => '42', 'username' => 'alice', 'game' => 'banana-splash', 'return_url' => 'https://yoursite.com/lobby']);
echo '<iframe src="' . $s['launch_url'] . '" allow="fullscreen" style="width:100%;height:760px;border:0"></iframe>';
Node.js example
const crypto = require('crypto');
async function pcApi(method, route, body) {
const raw = body ? JSON.stringify(body) : '';
const ts = Math.floor(Date.now() / 1000).toString();
const sig = crypto.createHmac('sha256', process.env.PC_SECRET).update(ts + '.' + raw).digest('hex');
const r = await fetch('https://polygoncasinos.net/api/v1/' + route, { method, body: body ? raw : undefined,
headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.PC_KEY, 'X-Timestamp': ts, 'X-Signature': sig } });
return r.json();
}
cURL
TS=$(date +%s); SIG=$(printf '%s.' "$TS" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.* //') curl -H "X-API-Key: $KEY" -H "X-Timestamp: $TS" -H "X-Signature: $SIG" https://polygoncasinos.net/api/v1/ping
Endpoints
GET /ping
Checks your credentials. Returns your partner id, status, revenue share % and wallet URL.
GET /games
Lists all enabled games. Optional filters: ?category=slots (engine key) or ?group=slots|table|originals.
{"ok":true,"count":350,"categories":[{"key":"slots","label":"Video Slots","icon":"🎰","group":"slots"},…],
"games":[{"slug":"banana-splash","name":"Banana Splash","category":"slots","category_label":"Video Slots","group":"slots",
"theme":"banana","rtp":96.5,"min_bet":0.01,"max_bet":100,"thumbnail":"https://polygoncasinos.net/cover.php?g=banana-splash",
"is_new":false,"is_hot":false,"featured":true,"provably_fair":true}, …]}
Thumbnails are 300×400 SVG images you can hot-link.
GET /games/{slug}
Single game object.
POST /sessions
Creates a game session for one of your players and returns the iframe URL.
| Field | Type | |
|---|---|---|
player_id | string, 1-64 | Your unique player id (letters, numbers, _ - . @ :). Required. |
username | string | Display name shown in the game. Optional. |
game | slug | Game to open. Required for launching. |
return_url | url | Where the “Lobby” button sends the player. Optional. |
lang | string | Game UI language: en, tr, de, fr, es, pt, it, ru, uk, pl, nl, ro, el, sv, az, kk, ar, fa, hi, id, vi, th, ja, ko, zh (default en). Without it the player's country is not used — pass your site's language. |
Returns HTTP 201:
{"ok":true,"token":"9f1c…","launch_url":"https://polygoncasinos.net/embed.php?token=9f1c…&game=banana-splash","expires_at":"2026-10-14 18:00:00Z","player":{"id":"42","internal_id":1834}}
Open launch_url in an iframe (recommended size 100% × 760px, allow="fullscreen"). Sessions last 6 hours and are extended while the player is active.
GET /bets?from=YYYY-MM-DD&to=YYYY-MM-DD&page=1&per_page=100
All rounds played by your players (newest first): id, round_id, player_id, game, amount, payout, multiplier, created_at.
GET /players/{player_id}/bets?limit=50
Latest rounds of one player including provably-fair data (server_seed_hash, client_seed, nonce).
GET /stats?from=YYYY-MM-DD&to=YYYY-MM-DD
{"ok":true,"stats":{"bets":1520,"players":37,"turnover":812.5,"payouts":781.2,"ggr":31.3,"revshare_percent":15,"revshare_amount":4.695},"outstanding":4.695}
GET /invoices
Your revenue share invoices with status open, overdue, paid, zero or waived.
Sportsbook (football, basketball, tennis)
Pre-match and live betting on football (top European leagues, Süper Lig, Champions League, MLS…), basketball (NBA) and tennis (ATP / WTA) with singles and combos (up to 20 selections). Odds come from our own pricing model; stakes and wins use the same seamless wallet as casino games with "game": "sportsbook" and one round_id per coupon (debit when the bet is placed, credit — possibly 0 — when it is settled). Sportsbook GGR (stakes − wins of settled coupons, refunded coupons excluded) is part of your revenue share invoices.
Embedded sportsbook (easiest)
Create a session with "game": "sportsbook" and open its launch_url in an iframe — the complete sportsbook UI (lobby, live, bet slip, my bets) runs inside it:
$s = pc_api('POST', 'sessions', ['player_id' => '42', 'username' => 'alice', 'game' => 'sportsbook', 'return_url' => 'https://yoursite.com/']);
echo '<iframe src="' . $s['launch_url'] . '" style="width:100%;height:900px;border:0"></iframe>';
GET /sports/events?sport=&league=&day=&q=
sport = soccer|basketball|tennis (empty = all), league = league key (e.g. eng.1, tur.1, nba, atp), day = live|today|tomorrow|week (default week), optional q (team search), limit (max 500), tz (minutes, like JavaScript getTimezoneOffset(), for “today/tomorrow”). Returns sport and league counters and the events with all markets. Times are ISO 8601 UTC.
{"ok":true,"count":1,"sports":[{"key":"soccer","name":"Football","icon":"⚽","count":214,"live":9},…],
"leagues":[{"key":"eng.1","name":"Premier League","sport":"soccer","country":"GB-ENG","flag":"🏴","count":30},…],
"events":[{"id":31,"sport":"soccer","league":"eng.1","league_name":"Premier League","home":"Liverpool","away":"Arsenal",
"home_logo":"https://…","away_logo":"https://…","start_at":"2026-10-17T20:45:00Z","status":"pre","status_detail":"",
"clock":null,"period":0,"minute":null,"score":null,"live":false,"suspended":false,"suspend_reason":null,
"markets":[{"key":"1x2","name":"Match Result","line":null,"group":"main","main":true,"suspended":false,
"outcomes":[{"pick":"1","label":"{home}","odds":1.98},{"pick":"X","label":"Draw","odds":3.57},{"pick":"2","label":"{away}","odds":3.49}]},
{"key":"ou","name":"Total Goals","line":2.5,"group":"goals","main":true,"suspended":false,"outcomes":[{"pick":"over","label":"Over","odds":1.76},{"pick":"under","label":"Under","odds":2.07}]},…],
"more":10}]}
A selection is identified by event_id + market key + line + pick. {home} / {away} in labels are placeholders for the team / player names. Status values: pre, live, final, postponed, canceled, suspended. When suspended is true (or a market's suspended) the selection cannot be bet right now.
| Sport | Market keys (picks) |
|---|---|
| Football | 1x2 (1 X 2), dc double chance (1X 12 X2), dnb draw no bet (1 2), ou total goals with line (over under), btts (yes no), eh 3-way handicap −1/+1 (1 X 2), cs correct score (“2-1”…, other). Settled on regular time (90' + stoppage). |
| Basketball | ml moneyline (1 2), spread home line (1 2), total points (over under) — overtime included. |
| Tennis | winner (1 2), sets total sets (over under), sh set handicap ±1.5 from the home player's view (1 2). Retirements are void. |
GET /sports/events/{id}
One event with all markets (same object as above).
POST /sports/bets
| Field | |
|---|---|
player_id, username | Your player (created on first use, like POST /sessions). |
selections | [{"event_id":31,"market":"ou","line":2.5,"pick":"over","odds":1.76}, …] — odds = the price you showed the player. |
stake | POL per coupon (min 0.1, max 500; max net win per coupon 5000 POL). |
type | single (default — one coupon per selection, each with stake) or combo (one accumulator, one selection per event). |
accept | Odds changes: none (default — reject any change), higher (accept better odds), any. |
Returns HTTP 201 {"ok":true,"bets":[BET…],"bet":BET,"balance":12.5}. When prices moved you get HTTP 400 {"ok":false,"error":"ODDS_CHANGED","message":"…","changes":[{"event_id":31,"market":"1x2","line":null,"pick":"1","old":1.88,"odds":1.98}]} — show the new prices and resend. Other errors: EVENT_SUSPENDED, SELECTION_UNAVAILABLE, SAME_EVENT, MIN_STAKE, MAX_STAKE, MAX_PAYOUT, MAX_COMBO_ODDS, INSUFFICIENT_FUNDS, TOO_MANY_SELECTIONS, SPORTS_DISABLED.
BET = {"player_id":"42","id":19,"round_id":"SBccc1…","type":"single","stake":0.3,"total_odds":6.1,"potential_win":1.83,"payout":1.83,
"status":"won","live":true,"created_at":"2026-10-16T09:55:55Z","settled_at":"2026-10-16T11:58:01Z",
"selections":[{"event_id":8,"label":"Liverpool – Club Brugge · Match Result · Liverpool","market":"1x2","market_name":"Match Result",
"line":null,"pick":"1","pick_label":"{home}","odds":6.1,"status":"won","result":"4-2","score":[4,2],"start_at":"2026-10-16T14:00:00Z",
"home":"Liverpool","away":"Club Brugge","sport":"soccer","league_name":"Champions League","event_status":"final"}]}
Coupon status: open, won, lost, void (stake refunded). Void selections (postponed > 48 h, cancelled, abandoned) count as odds 1.00 inside combos.
GET /sports/bets?player_id=&status=open|settled|won|lost|void|all&from=YYYY-MM-DD&to=YYYY-MM-DD&page=1&per_page=50
Coupons of your players (newest first), default last 30 days.
Wallet callback (seamless wallet)
Our server sends POST requests with a JSON body to the wallet URL you configure. Verify every request:
signature = hex( HMAC_SHA256( api_secret, X-PC-Timestamp + "." + raw_body ) ) // compare with X-PC-Signature
Answer within 8 seconds with JSON. Every request carries a unique transaction_id: if you receive the same id again, return the same result without applying it twice (idempotency).
| action | Request fields | Your response |
|---|---|---|
balance | player_id, currency | {"ok":true,"balance":"12.50000000"} |
debit | player_id, amount, transaction_id, round_id, game, currency | Subtract the stake. {"ok":true,"balance":"…"} or {"ok":false,"error":"INSUFFICIENT_FUNDS"} |
credit | player_id, amount, transaction_id, round_id, game, currency | Add the win (amount can be 0 — it closes the round). {"ok":true,"balance":"…"} |
rollback | player_id, amount, transaction_id, ref_transaction_id, round_id, game, currency | Refund the debit ref_transaction_id if you applied it (ignore if unknown). {"ok":true,"balance":"…"} |
Error codes you may return: INSUFFICIENT_FUNDS, PLAYER_NOT_FOUND, INVALID_SIGNATURE, PLAYER_BLOCKED, TRANSACTION_CONFLICT, TRANSACTION_ROLLED_BACK, BAD_AMOUNT, UNSUPPORTED_CURRENCY. Any non-ok debit answer cancels the bet (we then send a rollback for safety). If a rollback arrives for a debit you never saw, remember its id and refuse that debit if it arrives later. Credits that fail are retried automatically in the background.
Minimal PHP wallet
$raw = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_PC_TIMESTAMP'] ?? '';
if (!hash_equals(hash_hmac('sha256', $ts . '.' . $raw, SECRET), $_SERVER['HTTP_X_PC_SIGNATURE'] ?? '') || abs(time() - (int)$ts) > 300) {
exit(json_encode(['ok' => false, 'error' => 'INVALID_SIGNATURE']));
}
$r = json_decode($raw, true);
// 1. if transaction_id already processed -> return stored response
// 2. balance / debit (check funds) / credit / rollback inside a DB transaction
// 3. store the transaction_id with the response
echo json_encode(['ok' => true, 'balance' => number_format($newBalance, 8, '.', '')]);
Revenue share & billing
- GGR = stakes − wins of your players (casino rounds + settled sportsbook coupons). Revenue share: 15% of positive GGR (custom rates possible).
- Invoices are created weekly. Negative GGR is carried over to the next period. Amounts under 0.50 POL roll into the next invoice.
- Pay in POL on Polygon to the address shown on each invoice — payments are detected automatically.
- Invoices not paid within 5 days after the period ends become overdue and the API is suspended (error
PAYMENT_REQUIRED, HTTP 402) until paid. Repeated non-payment can lead to cancellation of the partnership.
Error codes
| HTTP | error |
|---|---|
| 401 | UNAUTHORIZED, BAD_TIMESTAMP, BAD_SIGNATURE |
| 402 | PAYMENT_REQUIRED — overdue invoice |
| 403 | ACCOUNT_SUSPENDED, ACCOUNT_CANCELLED, PENDING_APPROVAL, IP_NOT_ALLOWED |
| 400 | Sportsbook: ODDS_CHANGED, EVENT_SUSPENDED, SELECTION_UNAVAILABLE, MAX_PAYOUT, INSUFFICIENT_FUNDS … (see Sportsbook) |
| 404 | NOT_FOUND, GAME_NOT_FOUND, PLAYER_NOT_FOUND, EVENT_NOT_FOUND |
| 409 | WALLET_NOT_CONFIGURED |
| 422 | INVALID_PLAYER, BAD_DATE |
| 429 | RATE_LIMITED (900 requests/minute) |
| 503 | MAINTENANCE, SERVICE_DISABLED |
Provably fair
Every player gets their own server seed (hashed), client seed and nonce. Results use HMAC_SHA256(server_seed, client_seed:nonce:round). Players can rotate seeds and verify any round from inside the game window.