SSPORTSBOOKDevelopers
INTEGRATION GUIDE

PHP integration

Connect your website with PHP + MySQL. Follow the setup, then integrate player sessions, wallets and bet results.

Server → Sportsbook
POST /api/integration/launch
JSON
{
  "username": "player_example",
  "currency": "TRY",
  "language": "en",
  "origin": "https://customer.example"
}
200 OKA secure, single-use launch URL
PHPServer application
MySQLDatabase
test / 12316 wallets · 100.00 each
PHP + MySQL · API reference
01

Start with PHP + MySQL#

Import the SQL, set your connection details and sign in.

  1. Download the PHP + MySQL demo below.
  2. Import demo.sql into an empty MySQL database.
  3. Enter the API and database credentials in config.php.
  4. Open the application and log in with test / 123.
Demo account Value
Username test
Password 123
Wallet balance 100.00 in each of 16 currencies

The demo covers login, currency selection, sportsbook, bet history, design controls and home page widgets. For a live integration, connect the player lookup to your existing member session.

02

Connection settings#

Use separate addresses for server requests and the player interface.

Setting Value / purpose
API https://admin.sportsbookapi.work
Sportsbook https://sports.sportsbookapi.work
site_key Your integration identifier.
site_secret Server-side HMAC credential.
origin https://customer.example — your authorized website origin, without a path.
callback_url Your public HTTPS endpoint on port 443.

Send signed API requests from your server. Do not send a browser Origin header to the server API. The launch payload’s origin identifies the website that hosts the iframe. If an IP allowlist is enabled, your outbound server IP must be authorized.

03

PHP setup#

PHP 8.1+ · cURL · PDO_MYSQL · MySQL / MariaDB · HTTPS

  1. Create an empty MySQL/MariaDB database. In phpMyAdmin, select that database and import demo.sql.
  2. Edit config.php: enter site_key, site_secret, origin and the db_* connection values.
  3. Upload the three PHP files and the JS/CSS files to your HTTPS website. Open /iframe.php.
config.php
'site_key' => 'YOUR_SITE_KEY',
'site_secret' => 'YOUR_SITE_SECRET',
'origin' => 'https://customer.example',
'db_host' => 'localhost',
'db_port' => 3306,
'db_name' => 'YOUR_DATABASE_NAME',
'db_user' => 'YOUR_DATABASE_USER',
'db_password' => 'YOUR_DATABASE_PASSWORD',

The import creates the test account and its wallets. No user creation command is needed. Use an empty demo database; do not import the SQL over existing member tables.

File Purpose
config.php API credentials, MySQL connection and signed API requests
iframe.php Login, wallets, sportsbook, account and widget pages
callback.php Callback signature, exact balance updates and duplicate protection
demo.sql Tables, test account and 16 wallets
JS / CSS Iframe controls, modals, widgets and page styles
Address Page
/iframe.php Sportsbook and login
/iframe.php?page=account Account and independent bet history/design modals
/iframe.php?page=widgets Live, upcoming and popular leagues
/callback.php Callback URL
04

Choose your wallet model#

Your site is configured for seamless or ledger mode.

Model Balance owner Integration
Seamless Your wallet The sportsbook requests the balance and sends signed wallet callbacks. The included applications implement this flow.
Ledger Sportsbook wallet Transfer funds with the wallet API. Coupon events report results; do not apply their payout a second time.

Site betting credit and a player’s wallet balance are separate accounts.

05

Sign API requests#

Every server request carries an HMAC-SHA256 signature.

Header Value
X-Site-Key YOUR_SITE_KEY
X-Timestamp UTC Unix seconds; clock difference <120 seconds.
X-Nonce A fresh 16–128 character value for every HTTP attempt.
X-Signature Lowercase hex HMAC; no sha256= prefix.
Canonical message
timestamp + "\n" +
nonce + "\n" +
METHOD + "\n" +
path_and_query + "\n" +
SHA256(raw_body)

Use the uppercase method and the exact path, including a query string when present. Sign and send the same UTF-8 body bytes. A GET request uses an empty body. Generate a fresh nonce when retrying, while keeping the financial idempotency key unchanged.

PHP
$body = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$timestamp = (string) time();
$nonce = bin2hex(random_bytes(24));
$message = implode("\n", [$timestamp, $nonce, 'POST', $path, hash('sha256', $body)]);
$signature = hash_hmac('sha256', $message, $siteSecret);
06

Create a player session#

POST /api/integration/launch

Create a fresh launch when a player opens the sportsbook. The returned link lasts 60 seconds and can be used once. Member identity comes from your authenticated server session.

JSON
{
  "guest": false,
  "username": "player_example",
  "external_user_id": "42",
  "currency": "TRY",
  "language": "en",
  "origin": "https://customer.example",
  "callback_url": "https://customer.example/callback.php"
}
Field Required Meaning
guest No true for browsing without a member; no betting. Defaults to false.
username Member 1–80 letters, digits, spaces or _.@-.
external_user_id No Your own member identifier.
currency No Selected member wallet; defaults to site currency.
language No Interface language. Send en or tr explicitly.
origin Yes Authorized HTTPS website origin.
callback_url Conditional Required for seamless members if not configured. This address is shared by the entire site.
JSON
{
  "ok": true,
  "data": {
    "url": "https://sports.sportsbookapi.work/?site_key=YOUR_SITE_KEY&lang=en#/home?launch=LAUNCH_TOKEN",
    "launch_token": "LAUNCH_TOKEN",
    "site_key": "YOUR_SITE_KEY",
    "expires_at": "2026-09-14T12:01:00.000Z"
  }
}

For a guest launch, set guest:true and omit the member fields. Keep one stable callback URL for the site. Never reuse a launch link for a second iframe.

07

Send an API request#

Use the included signing function or implement the HTTP contract yourself.

PHP
$config = require 'config.php';
$launch = sportsbookRequest($config, 'POST', '/api/integration/launch', $payload);
$iframeUrl = $launch['url'];

Use your authenticated member identity to build the payload. The member password is never sent to the sportsbook API.

08

Display the sportsbook#

The demo renders the main iframe automatically.

To embed it in another page, load the SDK and obtain a fresh launch from your server:

HTML
<div id="sportsbook" style="height:85vh;min-height:640px"></div>
<script src="/sportsbookapi.js"></script>
Browser JavaScript
const response = await fetch("/iframe.php", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: new URLSearchParams({ action: "launch", csrf: csrfToken }),
});
const result = await response.json();
if (!response.ok || !result.ok) throw new Error("Launch failed");
const sportsbook = SportsbookAPI.mount("#sportsbook", {
  sportsOrigin: "https://sports.sportsbookapi.work",
  launchUrl: result.url,
  language: "en",
});

csrfToken comes from the authenticated host session. Without the SDK, set iframe src to the returned URL and implement the message contract below.

09

Home page widgets#

Place live matches, upcoming matches and popular leagues anywhere on your website.

Browser JavaScript
const widget = SportsbookAPI.mountWidget("#live-matches", {
  section: "live",
  sportsPage: "/iframe.php",
  launchEndpoint: "/iframe.php",
  csrfToken,
  language: "en",
});
// Remove the widget when its host component is removed.
// widget.destroy();
Option Meaning
section live, upcoming, popular-leagues, all
sportsPage Your full sportsbook page on the same HTTPS origin.
launchEndpoint Your server endpoint; receives action=widget-launch.
getLaunchUrl Optional async function returning a fresh guest launch URL instead of launchEndpoint.
onNavigate Receives {url,path,section}. Return false synchronously to handle navigation in your router.

Match, odds and league clicks open the matching detail on your full sports page. The widget itself does not add a selection to a betslip. Height adjusts to content. Every widget needs its own guest launch.

The destination receives a validated sports_path query parameter. The provided SDK and host script open this route. For a custom router, use SportsbookAPI.routeFromLocation() and sportsbook.navigateTo(path).

10

Bet history and design controls#

Open either modal on a page without the main sportsbook iframe.

Browser JavaScript
const options = {
  launchEndpoint: "/iframe.php",
  csrfToken,
  language: "en",
};
// Use each call in its own button handler.
SportsbookAPI.openBets(options);
SportsbookAPI.openDesign(options);

openBets requires member login and sends action=player-bets-launch. openDesign sends action=design-launch. Each opening obtains its own fresh launch.

11

Browser message contract#

For integrations using their own iframe and modal components.

Validate both event.origin and event.source. Host commands use source:"sportsbook-host"; iframe events use source:"sportsbook-iframe".

Command → iframe Payload
host-context {url: location.href, viewportWidth: innerWidth}
navigate {page: "home" | "sports" | "live" | "esports" | "results"}
navigate-route {path: "/sports/live?sport=1&game=123"}
set-language {language: "en"}
set-design {settings: {...}}
refresh-balance {}
relaunch-accepted Acknowledge request-relaunch, then obtain a fresh launch.
Event ← iframe Action
ready / request-host-context Send host-context.
view Update navigation with page and language.
balance Display balance and currency; do not alter your wallet from a browser message.
coupon-status Refresh the member view if needed.
bets-ready / design-ready / widget-ready The standalone view is ready.
close-bets / close-design Close your modal.
design-change Pass settings to your main iframe if present.
open-match Navigate to the supplied sports route on your full page.
widget-resize Apply height in pixels.
widget-navigate Navigate to your full sports page with path.
request-relaunch The visitor pressed Refresh page. Reload the host page or request a fresh launch.

Standalone views use view=player-bets, view=design or view=home-widget in the launch URL query. Widgets also use section=live|upcoming|popular-leagues|all. Keep the launch token in the URL fragment.

12

Receive callbacks#

Server-to-server messages keep your wallet and bet records up to date.

Header Meaning
X-Site-Key Your site identifier.
X-Callback-ID Matches event_id.
X-Callback-Timestamp UTC Unix seconds for this delivery attempt.
X-Coupon-Signature sha256= + HMAC-SHA256(secret, timestamp + "." + raw_body)
  1. Read the original body bytes and verify the signature and timestamp.
  2. Validate site_key, username and currency.
  3. For a wallet change, lock the wallet and check idempotency_key within one database transaction.
  4. Apply amount once, store the response and commit; then return JSON.
PHP
$raw = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_CALLBACK_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_COUPON_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $raw, $siteSecret);
if (!preg_match('/^\d{10}$/D', $timestamp) || abs(time() - (int) $timestamp) > 120 || !hash_equals($expected, $signature)) {
    http_response_code(401);
    exit;
}

The callback handler receives the raw body before a JSON parser. Signature verification uses the sha256= prefix here; API request signing does not.

13

Event reference#

Only wallet events change a seamless wallet balance.

What does coupon.settled.1 mean?

coupon identifies a bet notification, settled means a settlement update, and 1 is the revision number. It does not mean won or lost. The same event name can describe a won, lost or refunded bet. A later correction may arrive as coupon.settled.2.

Event example raw_payload.status What to display Wallet action
coupon.accepted open Accepted · awaiting results No change; stake was already reserved.
coupon.settled.1 won Won No change; apply the paired wallet.settlement.1 amount only.
coupon.settled.1 lost Lost No second stake debit.
coupon.settled.1 refunded Refunded Return is applied through wallet.settlement.1.
coupon.settled.2 open Reopened after a correction · awaiting results Apply the signed correction in wallet.settlement.2.
coupon.cashout.1 open Partial cashout · remaining bet is open Credit wallet.cashout.1 amount once.
coupon.cashout.1 cashout Full cashout Credit wallet.cashout.1 amount once.

Settlement and cashout share the revision counter. The next settlement after a cashout may therefore end in .2 or a higher number. Do not infer a result from event suffixes, sequence or amount. Use raw_payload.status; apply money only from the signed wallet event.

10.00 stake at odds of 1.55

Stage Event amount Meaning
Placement wallet.reserve -10.00 Deduct the stake once.
Acceptance coupon.accepted 0.00 status=open, total_stake=10.00, possible_win=15.50.
If won wallet.settlement.1 → coupon.settled.1 +15.50 → 0.00 Credit 15.50, then record status=won.
If lost wallet.settlement.1 → coupon.settled.1 0.00 → 0.00 No further debit; record status=lost.
If voided wallet.settlement.1 → coupon.settled.1 +10.00 → 0.00 Return 10.00; record status=refunded.

These are alternative outcomes for a single bet with no previous cashout or settlement. Wallet settlement amounts are payout differences; after a correction they may be negative.

Event amount Meaning
wallet.balance — Read current balance; no coupon snapshot or balance movement.
wallet.reserve − stake Reserve the stake before placement. A failed reservation prevents placement.
coupon.accepted 0.00 The bet was accepted. status=open; stake is in raw_payload.total_stake.
wallet.refund + amount Return a reserved stake when placement fails definitively.
placement.unknown 0.00 Placement outcome is uncertain and requires confirmation. Do not refund automatically.
wallet.settlement.N +/−/0 Apply the difference between the new cumulative payout and the previously recorded payout.
coupon.settled.N 0.00 Store the updated result and revision. The status can be won, lost, refunded or open after a correction.
wallet.cashout.N + amount Credit this cashout payment.
coupon.cashout.N 0.00 Full cashout: status=cashout. Partial cashout: status=open.

N is the shared settlement/cashout revision number. Not every internal placement transition creates a callback. There is no separate coupon.rejected callback; a rejected reservation is acknowledged directly, and a definitive failure after reservation produces wallet.refund.

14

Bet and placement statuses#

Read raw_payload.status for the result; use status_label only for display.

status Display Meaning
open Awaiting result Accepted bet; the remaining stake is active.
won Won At least one payable line won. A system bet can still have a net loss.
lost Lost Remaining bet lost. Earlier partial cashout payments can keep payout above zero.
refunded Refunded / void The remaining bet was refunded.
cashout Cashed out The full remaining position was closed by cashout.

An accepted bet waiting for results uses open; it does not use a separate pending status. Partial cashout also remains open.

Before acceptance

status Meaning
awaiting_wallet Waiting for the reserve callback response.
queued Waiting in the placement queue.
preparing Selections, odds and limits are being validated.
processing Placement is being processed.
failed The placement failed. Check error_code and the corresponding refund event.
unknown The placement outcome has not been confirmed. Do not place the same bet again automatically.

These are placement states, not won/lost results. Callback snapshots show the state at the time of that event. A result correction can reopen or change a settled bet; always process the revision and wallet delta.

15

Coupon payload fields#

One event envelope and one raw_payload snapshot.

Field Meaning
schema_version 2
event_id Unique event identifier.
idempotency_key Deduplication key for this site and event.
bet_id Groups all events belonging to a bet.
sequence Ordering within one bet, not across the entire site.
occurred_at UTC event time.
amount Wallet delta of this event; accepted/settled notifications use zero.
raw_payload.total_stake Original total stake.
raw_payload.possible_win Potential payout at placement, not confirmed winnings.
raw_payload.payout Cumulative payout, including cashout. Do not credit it again.
raw_payload.bet_type single / combo / system
raw_payload.revision Result/cashout revision.
raw_payload.remaining_ratio Fraction of original stake still active.
raw_payload.total_odds Combined decimal odds of the selected outcomes.
raw_payload.odds_format / odds_format_code / odds_format_label Saved odds display format, numeric code and display label.
raw_payload.displayed_total_odds Total odds formatted for display.
raw_payload.selection_count / cashout_count Number of selections and completed cashouts.
raw_payload.client_reference Reference associated with the original placement request.
raw_payload.settlement Settlement source, selection results, note and revision; null before settlement.
raw_payload.settlement_locked Whether the result is held by an administrative settlement lock.
raw_payload.error_details Additional odds-change information for ODDS_CHANGED; otherwise null.
raw_payload.lines Selection IDs, stake, odds and possible_win per line.
raw_payload.cashout_summary Total paid, remaining stake and cashout history.
raw_payload.wallet_state Wallet workflow state at snapshot time; separate from the bet result.
raw_payload.error_code / error_message Failure information when applicable.
created_at / updated_at / settled_at UTC timestamps; settled_at is null while open.
Accepted bet · complete example
JSON
{
  "event": "coupon.accepted",
  "amount": "0.00",
  "bet_id": "cpn_example",
  "currency": "TRY",
  "event_id": "evt_example_coupon_accepted",
  "sequence": 10,
  "site_key": "YOUR_SITE_KEY",
  "username": "player_example",
  "occurred_at": "2026-09-14T08:38:51.276Z",
  "raw_payload": {
    "lines": [
      {
        "odds": "2",
        "stake": "10.00",
        "possible_win": "20.00",
        "selection_ids": [
          "301"
        ]
      }
    ],
    "payout": "0.00",
    "status": "open",
    "bet_type": "single",
    "revision": 0,
    "created_at": "2026-09-14T08:38:51.200Z",
    "error_code": null,
    "selections": [
      {
        "line": null,
        "scope": "sports",
        "esports": false,
        "is_live": false,
        "visible": true,
        "event_id": "101",
        "sport_id": "1",
        "start_at": "2026-09-15T08:38:50.000Z",
        "away_team": "Away 1",
        "home_team": "Home 1",
        "league_id": "3",
        "market_id": "201",
        "country_id": "2",
        "sport_name": "Football",
        "is_finished": false,
        "league_name": "Premier League",
        "market_name": "Match Result",
        "market_type": "P1XP2",
        "sport_alias": "Soccer",
        "country_name": "England",
        "placed_score": null,
        "selection_id": "301",
        "current_score": null,
        "displayed_odds": "2.00",
        "effective_odds": "2",
        "selection_name": "Home",
        "full_time_score": null,
        "score_updated_at": null,
        "current_game_time": null,
        "current_game_state": null
      }
    ],
    "settled_at": null,
    "settlement": null,
    "total_odds": "2.00",
    "updated_at": "2026-09-14T08:38:51.270Z",
    "odds_format": "decimal",
    "total_stake": "10.00",
    "possible_win": "20.00",
    "status_label": "Open",
    "wallet_state": "debited",
    "cashout_count": 0,
    "error_details": null,
    "error_message": null,
    "cashout_summary": {
      "history": [],
      "total_amount": "0.00",
      "remaining_stake": "10.00",
      "remaining_possible_win": "20.00"
    },
    "remaining_ratio": "1.000000000000",
    "selection_count": 1,
    "client_reference": "example-placement-reference",
    "odds_format_code": 0,
    "odds_format_label": "Decimal",
    "settlement_locked": false,
    "displayed_total_odds": "2.00"
  },
  "schema_version": 2,
  "idempotency_key": "cpn_example:coupon.accepted"
}
Settled bet · complete example
JSON
{
  "event": "coupon.settled.1",
  "amount": "0.00",
  "bet_id": "cpn_example",
  "currency": "TRY",
  "event_id": "evt_example_coupon_settled_1",
  "sequence": 103,
  "site_key": "YOUR_SITE_KEY",
  "username": "player_example",
  "occurred_at": "2026-09-14T08:38:51.292Z",
  "raw_payload": {
    "lines": [
      {
        "odds": "2",
        "stake": "10.00",
        "possible_win": "20.00",
        "selection_ids": [
          "301"
        ]
      }
    ],
    "payout": "20.00",
    "status": "won",
    "bet_type": "single",
    "revision": 1,
    "created_at": "2026-09-14T08:38:51.200Z",
    "error_code": null,
    "selections": [
      {
        "line": null,
        "scope": "sports",
        "esports": false,
        "is_live": false,
        "visible": true,
        "event_id": "101",
        "sport_id": "1",
        "start_at": "2026-09-15T08:38:50.000Z",
        "away_team": "Away 1",
        "home_team": "Home 1",
        "league_id": "3",
        "market_id": "201",
        "country_id": "2",
        "sport_name": "Football",
        "is_finished": false,
        "league_name": "Premier League",
        "market_name": "Match Result",
        "market_type": "P1XP2",
        "sport_alias": "Soccer",
        "country_name": "England",
        "placed_score": null,
        "selection_id": "301",
        "current_score": null,
        "displayed_odds": "2.00",
        "effective_odds": "2",
        "selection_name": "Home",
        "full_time_score": null,
        "score_updated_at": null,
        "current_game_time": null,
        "current_game_state": null
      }
    ],
    "settled_at": "2026-09-14T08:38:51.283Z",
    "settlement": {
      "note": "",
      "source": "provider",
      "results": {
        "301": 3
      },
      "revision": 1
    },
    "total_odds": "2.00",
    "updated_at": "2026-09-14T08:38:51.283Z",
    "odds_format": "decimal",
    "total_stake": "10.00",
    "possible_win": "20.00",
    "status_label": "Won",
    "wallet_state": "confirmed",
    "cashout_count": 0,
    "error_details": null,
    "error_message": null,
    "cashout_summary": {
      "history": [],
      "total_amount": "0.00",
      "remaining_stake": "10.00",
      "remaining_possible_win": "20.00"
    },
    "remaining_ratio": "1.000000000000",
    "selection_count": 1,
    "client_reference": "example-placement-reference",
    "odds_format_code": 0,
    "odds_format_label": "Decimal",
    "settlement_locked": false,
    "displayed_total_odds": "2.00"
  },
  "schema_version": 2,
  "idempotency_key": "cpn_example:coupon.settled.1"
}
16

Match and selection details#

Each raw_payload.selections entry describes one selected outcome.

Fields Meaning
sport_id / sport_name / sport_alias Sport identity and display name.
country_id / country_name Competition region.
league_id / league_name League identity and display name.
event_id / home_team / away_team Match identity and teams.
market_id / market_name / market_type Selected betting market.
selection_id / selection_name / line Outcome identifier, label and handicap/total line when present.
effective_odds / displayed_odds Accepted decimal price and formatted display price.
is_live / scope / start_at Live/prematch context and UTC start time.
placed_score / current_score / full_time_score Score snapshots when supplied. Missing scores may be null.
current_game_time / current_game_state / score_updated_at Available game clock, period and last score update.

Scores describe the match, not the settlement of an individual market. Use the settlement results and coupon status for betting outcomes.

settlement.results[selection_id] Settlement multiplier
1 Lost: 0
3 Won: accepted selection odds
2 / 4 Stake returned: 1

The current settlement engine requires a supported result for every selection in the line. Do not derive a win/loss from an absent result.

17

Callback responses#

Acknowledge the recorded outcome of each request.

wallet.balance

JSON
{"ok":true,"balance":"100.00","currency":"TRY"}

Committed wallet or notification event

JSON
{"ok":true,"idempotency_key":"cpn_example:coupon.accepted","balance":"90.00","currency":"TRY"}

Insufficient funds for wallet.reserve

JSON
{"ok":false,"code":"INSUFFICIENT_BALANCE","idempotency_key":"cpn_example:wallet.reserve"}

Return HTTP 200 for a balance response. For durable events, return a successful 2xx response with ok:true and the matching key after commit. A definitive reserve rejection also includes the matching key. Network errors are not insufficient-balance decisions.

18

Retries and ordering#

An event can be delivered more than once.

Store a unique (site_key,idempotency_key) record with the wallet update and response in one transaction. An identical repeated body returns the stored response. If the same key has a different body, return HTTP 409 without another balance change. Verify the signature for every delivery.

Events are sent in sequence within the same bet. Different bets may arrive concurrently. The callback timeout is 10 seconds. Failed durable deliveries are retried with increasing delays, up to 20 attempts; unresolved deliveries require reconciliation. These retries are separate from a synchronous wallet.balance request.

19

Results and corrections#

Apply the wallet delta, then update the result record.

Example: stake 10.00 at odds 2.00 Event amount Status
1 wallet.reserve -10.00 awaiting_wallet
2 coupon.accepted 0.00 open
3 wallet.settlement.1 +20.00 won
4 coupon.settled.1 0.00 won
If corrected to lost wallet.settlement.2 -20.00 lost
Result notification coupon.settled.2 0.00 lost

For a loss without prior payout, settlement amount is 0.00. For a full refund without prior cashout, the stake is returned. Corrections can increase or decrease a previous payout, or reopen the bet. Use the amount actually delivered rather than calculating from the status alone.

20

Full and partial cashout#

Cashout payments and remaining exposure are reported separately.

Apply wallet.cashout.N.amount once. Full cashout changes status to cashout and remaining_ratio to zero. Partial cashout leaves status open; remaining_ratio, remaining_stake and remaining_possible_win decrease. Later settlement concerns the remaining portion.

payout includes cashout already paid. The following coupon.cashout.N event has amount 0.00 and updates the bet record.

21

Currencies and amounts#

Money is a decimal string in both requests and responses.

Currencies Maximum fractional precision
TRY, USD, GBP, EUR, BRL, CAD, AUD, INR, BDT, MXN, ETB, IDR 2
KWD, TND, IQD 3
TRX 8

These are precision limits, not a requirement to type that many digits. 10.50 TRX, 2.25 TRY and 3.00 KWD are valid amount formats. Site stake and payout limits also apply.

Coupon events remove unnecessary trailing zeros and keep at least two decimal places. Preserve meaningful fractions such as 1.001 and 0.00000001. Use decimal arithmetic for balances and compare status codes rather than display labels.

22

Ledger transfers#

POST /api/integration/wallet

JSON
{
  "username": "player_example",
  "currency": "TRY",
  "operation": "credit",
  "amount": "100.00",
  "idempotency_key": "transfer-example-0001"
}

credit adds funds to the sportsbook wallet; debit removes them. This endpoint is for ledger sites. The member wallet must exist after iframe bootstrap. Amount must be positive and match currency precision.

JSON
{"ok":true,"data":{"transaction_id":"txn_example","idempotency_key":"transfer-example-0001","balance":"100.00","currency":"TRY"}}

When a transfer times out, retry the same operation and financial key with a fresh signing nonce. Do not create a second transfer to compensate for an unknown result.

23

Site betting credit#

GET /api/integration/credit

JSON
{"ok":true,"data":{"site_key":"YOUR_SITE_KEY","credit":"1000.00","currency":"USD"}}

This returns your site’s betting credit, not a player balance. Sign the request with an empty body. The currency comes from your site configuration.

24

Error handling#

Use code for handling and request_id for support.

JSON
{"ok":false,"code":"SIGNATURE_INVALID","message":"Request signature is invalid.","request_id":"request_example"}
code Action
SIGNATURE_INVALID Check the secret, canonical path and exact body bytes.
SIGNATURE_EXPIRED Check the clock, timestamp and nonce format.
REPLAY Generate a fresh signing nonce; keep the financial key.
ORIGIN_FORBIDDEN / IP_FORBIDDEN Check authorized website origins and outbound server IPs.
CALLBACK_REQUIRED Configure the HTTPS callback URL.
IDEMPOTENCY_CONFLICT The key refers to a different operation. Reconcile before continuing.
INSUFFICIENT_BALANCE The requested debit cannot be funded.
PLAYER_SESSION_REQUIRED / LAUNCH_EXPIRED / LAUNCH_USED Request a fresh launch from the customer server. The Refresh page button renews through the integration page.

A 503 or connection timeout does not prove that a financial operation failed. Preserve its reference and reconcile the result before retrying a different operation. Error message language may vary; code remains the integration key.

25

Downloads#

PHP + MySQL · application and API reference