The contract between the iGains platform and your wallet. Versioned, complete, and the same thing our test suite checks.
Version 1 · published 12 September 2026 · changes to this contract get a new version; v1 semantics never change underneath you.
Your platform mints a signed launch URL per player; the game runs on iGains. Whenever money must move, iGains calls your wallet — four JSON endpoints you host. You never call iGains during play. Balances live with you; iGains is stateless about funds. This is the seamless-wallet pattern used across the industry, so an adapter you already have for another studio is usually most of the work.
Every call is a POST with a JSON body and three headers:
x-igains-ts: unix milliseconds
x-igains-nonce: random hex
x-igains-signature: HMAC-SHA256(wallet_secret, "POST\n{path}\n{ts}\n{nonce}\n{body}") as lowercase hex
{path} is the URL path only (for example /debit); {body} is the exact raw request body. Verify with a timing-safe comparison and reject timestamps older than about five minutes. Your wallet secret is shown once in the console and can be rotated there at any time.
→ { "token": "<your player token>" }
← 200 { "playerRef": "<your stable player id>", "currency": "USDC", "balanceMinor": 1000000 }
playerRef is required: it becomes the player identity in reporting, disputes and leaderboards. balanceMinor is required. An unknown token may be auto-provisioned (recommended for sandboxes) or refused with a non-2xx response.
→ { "token": "…", "ref": "bet_<uuid>", "amountMinor": 2500, "currency": "USDC" }
← 200 { "balanceMinor": 997500 } success (balance after the debit)
← 2xx/4xx { "ok": false, "error": "insufficient_funds" } decline — the bet is refused, no rollback follows
Idempotency is mandatory. The same ref can arrive more than once; move money the first time, and on any repeat return the same balance without moving money again. A 2xx without balanceMinor, a timeout, or a non-JSON response is treated as ambiguous: iGains immediately sends /rollback for the same ref and refuses the bet.
→ { "token": "…", "ref": "win_<betId>", "amountMinor": 4900, "currency": "USDC" }
← 200 { "balanceMinor": 1002400 }
The amount is the player’s total proceeds, stake included (a 10.00 bet cashed at 2.00× at 98% RTP credits 19.60). Same idempotency rule. Never refuse a credit for balance reasons — it is the player’s money. iGains retries five times with backoff; after that the credit is recorded as failed with its ref and amount preserved and surfaces on your Reconciliation page for replay.
→ { "token": "…", "ref": "bet_<uuid>" } the ORIGINAL debit ref
← any 2xx JSON, for example { "ok": true } (balanceMinor optional; "ok": false refuses)
Refund the debit if it happened; acknowledge either way; idempotent. A rollback can arrive before its debit is recorded on your side (our timeout fired while you were still processing) — persist the cancellation so a late debit for that ref is refused or immediately reversed. A bet is either credited or rolled back, never both.
Debits are bet_<uuid>; the matching credit is win_<betId>; a rollback repeats the debit ref. Amounts are integers in minor units (cents for two-decimal currencies) and every call carries a currency code matching an instance configured for you in the console. Multi-currency operators may serve every currency from one endpoint or set a per-currency URL override.
The console’s wallet check and test suite call your wallet with a sandbox player. By default the token starts with igains_test_; create a sandbox player on first sight with any balance. If you already have a test account, enter its token in the console under Connect your wallet API and we use that instead. Test calls never carry real money and never appear in production launches.
Seven signed vectors, sent exactly as production sends them: session check, playerRef presence, a 1.00 debit, an idempotent replay of the same ref, a 1.00 credit, rejection of a negative amount, and a rollback of a separate, uncredited debit. Each line shows the HTTP status, and on hover the explanation plus your wallet’s exact response.
Signed with your launch secret: sort all parameters except sig alphabetically, join as key=value with & (raw values), HMAC-SHA256, hex. Optional exp (unix ms) expires the link; rotating the launch secret revokes all outstanding links. Full snippets in five languages live on your console’s Integration page.
v1 — 12 September 2026. Initial published contract. Rollback body carries token alongside ref; any 2xx JSON acknowledges a rollback; sandbox token configurable.