Bet
Live{base}/api/betWhen 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
| Field | Type | Required | Description |
|---|---|---|---|
| X-Api-Key | string | Yes | The API key best-system issued to you (verify it matches) |
| X-Signature | string | Yes | hex(HMAC-SHA256(secret, raw body)) — verify against the raw bytes, never re-serialize. Mismatch → code 30002 |
Request bodyapplication/json
| Field | Type | Required | Description |
|---|---|---|---|
| request_id | string | Yes | Id of this request |
| player_username | string | Yes | The player's username on your system |
| currency | string | Yes | The player's currency code in ISO 4217, e.g. THB |
| product_code | string | — | Game-provider code (e.g. PGSOFT) |
| timestamp | number | Yes | Send time in unix milliseconds |
| txns | object[] | Yes | Bets to debit — each txn's amount is the stake to deduct |
| └ txn_id | string | Yes | Transaction 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_id | string | Yes | Game round id |
| └ amount | number | Yes | Bet amount (stake) |
| └ game_code | string | — | Game code |
| └ is_feature | boolean | — | free/feature spin (default false) — may arrive with amount=0 (process as a zero-value bet: reply code 0, no debit) |
| └ status | string | — | 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_info | string | — | Info about the bet — e.g. LIVE_CASINO carries player/banker, SLOT carries the game name |
| └ bet_amount | number | — | The vendor's stake. Same value as this callback's amount |
| └ skip_balance_update | boolean | — | true = skip deducting from the member — typically in SPORT when the provider is reviewing the player's bet (default: false) |
| └ is_feature_buy | boolean | — | Whether the member bought a feature spin (default: false) |
// สล็อตปกติ — 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
| Field | Type | Required | Description |
|---|---|---|---|
| code | number | Yes | 0 = success · see the Seamless codes page |
| request_id | string | Yes | Echoed from the request |
| username | string | Yes | Echo of player_username (defensive) |
| currency | string | Yes | Echoed from the request |
| balance_before | number | Yes | Balance before processing the whole txns[] batch |
| balance_after | number | Yes | Balance after processing the whole batch |
| timestamp | number | Yes | When you processed it (unix ms) |
{
"code": 0,
"request_id": "2f6d9c81-4b3e-4a5d-9c0e-7a1b2c3d4e5f",
"username": "foobar",
"currency": "THB",
"balance_before": 1000,
"balance_after": 800,
"timestamp": 1783236600090
}Possible error codes
| code | Name | HTTP | Message |
|---|---|---|---|
| 10001 | SEAMLESS_USER_NOT_FOUND | 200 | Player not found on the agent system |
| 10002 | SEAMLESS_INSUFFICIENT_BALANCE | 200 | Insufficient balance for the debit |
| 20002 | SEAMLESS_DUPLICATE_TXN | 200 | Duplicate transaction (txn_id already processed) |
| 30002 | SEAMLESS_INVALID_SIGNATURE | 401 | Invalid X-Signature |
| 40003 | SEAMLESS_FORBIDDEN | 200 | Forbidden (api-key/IP) |
| 50001 | SEAMLESS_INTERNAL_ERROR | 200 | Internal error on the agent system |