Skip to content
CHART777

CHART777 Game API

Offer CHART777 games on your own website. You call our API from your server; your players play inside an iframe; we charge stakes and pay wins through your wallet (seamless wallet). Base URL: https://chart777.com/api/v1/b2b

Overview

  1. Your server lists games (each has a permanent service id).
  2. When a player opens a game, your server creates a session and gets a launch URL.
  3. You show the launch URL in an iframe. The game calls your wallet for every stake and win.
  4. Each month you pay a share of your GGR (bets − wins) per game — see Pricing.

Getting access

Create a CHART777 account, open My CHART777 → API and apply with your company details. After approval you can create API keys, set your wallet URL and get the signing secret there. Keys and the secret are shown once — store them on your server only.

Authentication

Send your key in the X-Api-Key header on every request. Keys start with c777_live_. Never put a key in browser code.

curl https://chart777.com/api/v1/b2b/games \
  -H "X-Api-Key: c777_live_••••••••"

Games and service ids

GET/api/v1/b2b/games

The games you can offer, with your cost rate and certification.

[
  {
    "serviceId": 1007,
    "title": "Miners Fortune",
    "rtp": 96.1,
    "volatility": "high",
    "rate": 0.10,          // your cost: share of GGR
    "certified": true,
    "certLab": "…", "certNumber": "…"
  }
]

Launching a game

POST/api/v1/b2b/sessions

Create a session for one of your players. playerId is your own id for the player (we never see personal data). Amounts are integer minor units of currency (100 = 1.00).

POST /api/v1/b2b/sessions
X-Api-Key: c777_live_••••
Content-Type: application/json

{ "serviceId": 1007, "playerId": "p-123456", "currency": "USD", "locale": "en" }

→ 200
{ "sessionId": "cm…", "serviceId": 1007, "expiresAt": "2026-10-28T12:00:00Z",
  "launchUrl": "https://chart777.com/embed/en/1007?session=…" }

Show it in an iframe:

<iframe src="LAUNCH_URL" allow="autoplay; fullscreen" style="width:100%;aspect-ratio:16/9;border:0"></iframe>

A session lasts 2 hours by default; create a new one each time the player opens the game.

Seamless wallet

For every action the game sends a POST to your wallet URL (HTTPS). Verify the signature, apply the action, and answer with the player's balance.

POST https://your-site.example/chart777/wallet
X-Chart777-Timestamp: 1761400000
X-Chart777-Signature: hex(HMAC_SHA256(secret, timestamp + "." + rawBody))

{
  "requestId": "…",
  "action": "debit",               // balance | debit | credit | rollback
  "sessionId": "cm…", "playerId": "p-123456", "currency": "USD", "serviceId": 1007,
  "roundId": "cm…",
  "transactionId": "cm…:bet",      // debit/credit/rollback only — unique, retried with the same id
  "referenceTransactionId": "…",   // rollback: the debit being reversed
  "amount": 1000,                  // minor units
  "roundFinished": true            // on credit
}

→ 200 { "balance": 99000 }
→ 200 { "error": { "code": "INSUFFICIENT_FUNDS", "message": "Not enough balance" } }
  • balance — return the current balance.
  • debit — take the stake. Refuse with INSUFFICIENT_FUNDS, PLAYER_BLOCKED or SESSION_EXPIRED when needed.
  • credit — add the win (also sent with amount: 0 to close a losing round).
  • rollback — return a debit that we could not confirm (no answer / timeout). If you never applied that debit, just answer with the balance.
  • Idempotency: the same transactionId can arrive more than once (we retry wins until you confirm). Apply it once and answer with the balance every time.
  • Reject requests whose timestamp is more than 5 minutes old or whose signature doesn't match.
  • Answer within 8 seconds.

Signature check in Node.js:

import { createHmac, timingSafeEqual } from 'node:crypto';
const expected = createHmac('sha256', SECRET).update(req.headers['x-chart777-timestamp'] + '.' + rawBody).digest('hex');
const ok = timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers['x-chart777-signature']));

PHP:

$expected = hash_hmac('sha256', $_SERVER['HTTP_X_CHART777_TIMESTAMP'] . '.' . file_get_contents('php://input'), $secret);
$ok = hash_equals($expected, $_SERVER['HTTP_X_CHART777_SIGNATURE']);

Rounds and usage

GET/api/v1/b2b/rounds?from=2026-10-01&to=2026-11-01&page=1

Your rounds, newest first (100 per page): bet, win, status (SETTLED, CREDIT_PENDING, FAILED) and the server seed hash for audits.

GET/api/v1/b2b/usage?month=2026-10

Per game and month: rounds, bets, wins, GGR, your rate and the cost.

{ "month": "2026-10", "totalCost": 12345,
  "lines": [ { "serviceId": 1007, "currency": "USD", "rounds": 812, "bets": 4100000, "wins": 3920000,
               "ggr": 180000, "rate": 0.10, "cost": 18000 } ] }

Pricing

Cost = GGR × rate, per game and month (a month with negative GGR costs nothing for that game). Your rate is shown in /games and in your API page; it can differ per game. Invoices are issued monthly from the usage report.

Errors and limits

Errors use HTTP status codes and a JSON body { "ok": false, "error": { "code": "…", "message": "…" } }. Common codes: UNAUTHENTICATED (missing/invalid key), FORBIDDEN (account not active), VALIDATION_FAILED, GAME_UNAVAILABLE, RATE_LIMITED. Rate limit: 300 requests per minute per IP address.