Bet

Live
POST{base}/api/bet

When the player plays or places a bet, our system sends a request to your Callback URL (configured in the Backoffice) — check the player's balance; if sufficient, deduct the member's balance and reply success to our system so play can continue.

Process the whole txns[] batch in one DB transaction (atomic) — if any txn fails, roll back the batch and reply an error with balance_before == balance_after

If the same txn_id arrives again, do not apply it a second time; reply the current balance with code 0, or reply 20002. The only exception is a transaction that follows a /rollback of that round: it carries a corrected result and must be applied (see "re-settle after rollback" on the Contract page).

A 0 amount is real — a feature spin, a bought feature, a tip, or a stake the provider could not supply. Do not reject it: process it as a zero-value transaction and reply code 0 without moving the balance.

Always reply HTTP 200 even for business errors

Headers

FieldTypeRequiredDescription
X-Api-KeystringYesThe API key best-system issued to you (verify it matches)
X-SignaturestringYeshex(HMAC-SHA256(secret, raw body)) — verify against the raw bytes, never re-serialize. Mismatch → code 30002

Request bodyapplication/json

FieldTypeRequiredDescription
request_idstringYesId of this request
player_usernamestringYesThe player's username on your system
currencystringYesThe player's currency code in ISO 4217, e.g. THB
product_codestring—Game-provider code (e.g. PGSOFT)
timestampnumberYesSend time in unix milliseconds
txnsobject[]YesBets to debit — each txn's amount is the stake to deduct
└ txn_idstringYesTransaction ID · on a retry do not re-apply (reply current balance with code 0) · Sport: a confirmed (OPEN) ticket is relayed again with the same txn_id carrying status="OPEN" + skip_balance_update=true — reply code 0 + current balance, never debit twice (see the sportsbook section on the Contract page)
└ round_idstringYesGame round id
└ amountnumberYesBet amount (stake)
└ game_codestring—Game code
└ is_featureboolean—free/feature spin (default false) — may arrive with amount=0 (process as a zero-value bet: reply code 0, no debit)
└ statusstring—Vendor bet status. OPEN normally. WAITING for a sport bet before the provider confirms, then re-sent with the same txn_id as OPEN with skip_balance_updateOPEN | WAITING | SETTLED | REFUND | REJECT | ROLLBACK | VOID | TIPS
└ play_infostring—Info about the bet — e.g. LIVE_CASINO carries player/banker, SLOT carries the game name
└ bet_amountnumber—The vendor's stake. Same value as this callback's amount
└ skip_balance_updateboolean—true = skip deducting from the member — typically in SPORT when the provider is reviewing the player's bet (default: false)
└ is_feature_buyboolean—Whether the member bought a feature spin (default: false)
Request example
// สล็อตปกติ — status "OPEN" (ไม่มี WAITING / ไม่มี skip)
{
  "request_id": "2f6d9c81-4b3e-4a5d-9c0e-7a1b2c3d4e5f",
  "player_username": "foobar",
  "currency": "THB",
  "product_code": "PGSOFT",
  "timestamp": 1783236600000,
  "txns": [
    {
      "txn_id": "T-001",
      "round_id": "R-1",
      "amount": 200,
      "game_code": "10300",
      "is_feature": false,
      "status": "OPEN",
      "play_info": "Rise of Dragon"
    }
  ]
}

// กีฬา (1/2) — วางบิล status "WAITING" (หัก stake ตามปกติ)
{
  "request_id": "3f7a1c92-8b2e-4d5a-9e0f-1a2b3c4d5e6f",
  "player_username": "foobar",
  "currency": "THB",
  "product_code": "SABA",
  "timestamp": 1783236600100,
  "txns": [
    {
      "txn_id": "S-88001",
      "round_id": "SB-1",
      "amount": 100,
      "game_code": "SBO-FOOTBALL",
      "status": "WAITING",
      "play_info": "Man Utd vs Chelsea"
    }
  ]
}

// กีฬา (2/2) — ค่ายยืนยันบิล: relay /bet ซ้ำด้วย txn_id เดิม + status "OPEN" + skip_balance_update
// ห้ามหักซ้ำ → dedupe ต่อ txn_id แล้วตอบ code 0 + balance ปัจจุบัน
{
  "request_id": "4a8b2d03-9c3f-4e6b-8f10-2b3c4d5e6f70",
  "player_username": "foobar",
  "currency": "THB",
  "product_code": "SABA",
  "timestamp": 1783236600600,
  "txns": [
    {
      "txn_id": "S-88001",
      "round_id": "SB-1",
      "amount": 100,
      "game_code": "SBO-FOOTBALL",
      "status": "OPEN",
      "skip_balance_update": true
    }
  ]
}

Expected Response

Fields in data

FieldTypeRequiredDescription
codenumberYes0 = success · see the Seamless codes page
request_idstringYesEchoed from the request
usernamestringYesEcho of player_username (defensive)
currencystringYesEchoed from the request
balance_beforenumberYesBalance before processing the whole txns[] batch
balance_afternumberYesBalance after processing the whole batch
timestampnumberYesWhen you processed it (unix ms)
Response example
{
  "code": 0,
  "request_id": "2f6d9c81-4b3e-4a5d-9c0e-7a1b2c3d4e5f",
  "username": "foobar",
  "currency": "THB",
  "balance_before": 1000,
  "balance_after": 800,
  "timestamp": 1783236600090
}

Possible error codes

codeNameHTTPMessage
10001SEAMLESS_USER_NOT_FOUND200Player not found on the agent system
10002SEAMLESS_INSUFFICIENT_BALANCE200Insufficient balance for the debit
20002SEAMLESS_DUPLICATE_TXN200Duplicate transaction (txn_id already processed)
30002SEAMLESS_INVALID_SIGNATURE401Invalid X-Signature
40003SEAMLESS_FORBIDDEN200Forbidden (api-key/IP)
50001SEAMLESS_INTERNAL_ERROR200Internal error on the agent system