Appearance
Wallet / Trade Callbacks
Wallet / Trade callbacks (during gameplay)
Once the iFrame is loaded, gameplay drives four callbacks from TS into your wallet API.
The three wallet callbacks are HMAC-SHA256 signed (/authenticate is unsigned — the launch token is the credential) — see "Message Integrity" below. Every request carries X-Sig-Version: v2, X-Timestamp, X-Nonce, X-Signature headers.
/getbalance
Called before /opentrade to verify sufficient funds.
Request:
json
{
"token": "<walletToken>",
"amount": "100",
"currency": "USD"
}Response:
json
{ "balance": "2180", "currency": "USD", "status": "Ok" }If the player has insufficient funds, you can still return status:"Ok" with the real balance — TS will do the comparison and refuse the trade. Alternatively, return {status:"InsufficientFunds", balance, currency} if you want to fail fast.
/opentrade — Tap
Request:
json
{
"token": "<walletToken>",
"amount": "10",
"currency": "USD",
"externalTradeType": "tap",
"externalTradeId": "12345",
"data": [{
"userID": "alice",
"currency": "USD",
"instrumentID": "139",
"tStart": "2026-05-13T12:00:00.000Z",
"tEnd": "2026-05-13T12:00:02.000Z",
"pMin": "65430.00",
"pMax": "65432.00",
"stake": "10",
"payoutRatio": "1.7"
}]
}Field reference:
| Field | Meaning |
|---|---|
token | walletToken from Step 2 |
amount | Stake to reserve from the player's wallet (matches data[0].stake) |
currency | ISO alpha currency code (always lowercase for Tap) |
externalTradeType | Always "tap" |
externalTradeId | TS's trade ID. Use as the idempotency key. |
data[0].userID | Your userId for this player |
data[0].currency | Same as top-level currency |
data[0].instrumentID | Numeric instrument ID (e.g., 30102 = Bitcoin, see asset list TS provides) |
data[0].tStart / data[0].tEnd | ISO-8601 UTC with ms precision. tEnd − tStart is the tap size the player chose (2 / 4 / 8 s) |
data[0].pMin / data[0].pMax | The cell's price band (pMax − pMin is the cell height set by TS's σ-adaptive engine). Opaque to you — for audit only. |
data[0].stake | Stake amount |
data[0].payoutRatio | The profit multiplier shown to the player when they tapped. Locked at open time. Grid changes after open do not affect this number. |
Response:
json
{ "balance": "990", "currency": "USD", "status": "Ok" }balance is the new balance after reserving the stake.
/closetrade — Tap
Request:
json
{
"token": "<walletToken>",
"amount": "17.00",
"currency": "USD",
"externalTradeType": "tap",
"externalTradeId": "12345",
"data": [{
"tradeID": "12345",
"userID": "alice",
"stake": "10.0000000000",
"payout": "70",
"rebate": "0",
"instrumentID": "139",
"expiryPrice": "65431.50",
"touchPrice": "65431.40",
"pnl": "7.00",
"returnedAmount":"17.00"
}]
}Settlement math — TS computes amount based on outcome:
| Outcome | amount |
|---|---|
| Win (price touched the cell) | stake + payout = stake × (1 + payoutRatio − 1) |
| Tie (cancelled / window-boundary) | stake (refund) |
| Loss | 0 |
Always update balance from the amount field — don't recompute from pnl, don't read returnedAmount. TS has done the math.
data.touchPrice is informational only — use it for player history / reporting. NEVER feed it into wallet math.
Response: same shape as /opentrade:
json
{ "balance": "1007", "currency": "USD", "status": "Ok" }Balance consistency rules
- Pre-trade: TS calls
/getbalancebefore/opentrade. - Open: reduce available balance by
amount. Place a reservation. - Close:
- Win: credit
amount(which equalsstake + payout). - Tie: credit
amount(which equalsstake— refund of the reservation). - Loss: credit
0(release the reservation without crediting). - Atomicity:
/opentradeand/closetradeMUST be atomic on your side. Use row-level locking, optimistic versioning, or whatever fits your stack. - Idempotency:
externalTradeIdis the idempotency key. TS may retry on timeout / network error — your handler MUST return the same response without double-applying. - Cancellations: occasional cancelled settlements with no prior open signal are normal at trading-window boundaries. Treat them as no-ops.
Error handling
Return a JSON body with status and optional code / message:
json
{ "status": "InsufficientFunds", "balance": "9.50", "currency": "USD", "code": "W001" }Suggested status enum:
| Status | When to use |
|---|---|
Ok | Operation accepted |
InsufficientFunds | Balance below requested amount |
Unauthorized | Bad / unknown walletToken |
InvalidDigest | HMAC signature mismatch (verifier rejected) |
InvalidToken | Token well-formed but unrecognized (e.g. expired walletToken) |
RateLimited | Throttled |
TemporaryError | Retryable upstream condition (DB down, etc.) — TS will retry with backoff |
For TemporaryError, TS retries with exponential backoff for a bounded window (~30 s). Anything else TS treats as terminal and surfaces to the player.