8. Real money through the operator
How a casino or an aggregator runs Impakt rounds on its own wallet. Impakt never holds, moves or settles money: it decides what happened and asks the operator's wallet to debit stakes and credit wins, the way any game provider does. This is the seamless-wallet integration every aggregator already speaks.
The round
A round is a parimutuel pool on one question about the streamer's game: "Team wins this round?", "Survives this raid?", "Next bet wins?". Two sides, YES and NO. Stakes go into the pool. When the answer comes, the pool minus the operator's rake is shared among the winning side in proportion to stakes, rounded down. The rounding dust stays with the operator.
There is no market maker and no odds to certify. The pool pays out exactly what it holds minus the rake, so exposure is zero by construction. RTP is 1 - rake. A side nobody took, or a question that cannot be answered (stream dropped, feed lost), refunds every stake in full, no rake.
The answer comes from a source the operator accepts:
| Source | Trust | Where it fits |
|---|---|---|
| The game's own feed (CS2, Dota 2 Game State Integration) | The streamer's PC. Fine for play money, not alone for real money | Paired with a post-match check (Steam match data) or a dealer agreement |
| The casino's own game (the streamer plays on the operator's site) | The operator's RNG, provably fair | The natural first product: the operator already trusts its own outcomes |
| The streamer as dealer | A contracted dealer, as in live dealer studios | Verdict by the streamer, under the operator's dealer terms |
| A public official feed (match APIs) | Independent | Esports rounds settled after the fact |
The wallet calls
All calls are POST with a JSON body, from Impakt to the operator's wallet URL. Amounts are integers in the currency's minor unit. txId is unique per movement and is the idempotency key: the same txId sent twice must return the same result and move money once.
| Path | Body | Returns |
|---|---|---|
/authenticate | { token } the launch token from the operator's lobby | { playerId, currency, balance, displayName? } |
/balance | { playerId } | { balance } |
/bet | { playerId, amount, currency, txId, roundId, game: "impakt-crowd", channel } | { balance } |
/win | { playerId, amount, currency, txId, roundId, betTxId? } | { balance } |
/rollback | { playerId, txId, roundId } txId is the original bet's | { balance } |
Refusals are 4xx with { error, code } and are final (insufficient_funds, unknown_player, limit, self_excluded). 5xx and network failures are retried with the same txId, with back-off, and a movement that still fails is kept in Impakt's transaction log as failed and retried every minute until it lands. Nothing is ever silently dropped; the log is available for reconciliation.
Signatures
Every request carries:
X-Impakt-Timestamp: <unix ms>
X-Impakt-Signature: hex( HMAC-SHA256( secret, timestamp + "." + rawBody ) )
X-Impakt-Idempotency: <txId> (on bet, win, rollback)
The operator verifies the signature over the raw body and rejects a timestamp older than five minutes. One shared secret per operator, rotated by agreement. TLS on both sides.
Order of operations
Stake: debit at the operator, then record in the pool. If the pool closed in between, the debit is rolled back at once. Settle: the pool computes every payout, then each win is credited; each refund is a rollback of the original bet. A player's balance shown on the page is always the operator's answer, never Impakt's arithmetic.
The player's page
The operator's lobby opens https://impaktlive.gg/play?operator=<id>&token=<launch token>&channel=<streamer> in an iframe or a tab. The token is exchanged once for an Impakt session; the page shows the streamer's picture, the operator's balance, the pool and the two buttons. Limits, session time, reality checks and self-exclusion are the operator's and are enforced by its wallet: a refused debit is shown to the player as the operator's message.
What Impakt stores, and what it never sees
| Impakt holds | Impakt never holds | |
|---|---|---|
| Identity | the operator's opaque player id, for the session | name, email, KYC, account data |
| Money | the round's arithmetic and a log of the movements it asked for | balances, deposits, cards, payouts |
| Outcome | the events the operator or the game reported | the RNG, the seeds |
| Streamer | a sealed (AES-256-GCM) copy of a token the streamer lent, only until the operator's own feed replaces it | passwords, session cookies |
The operator's bet feed
The Stake-backend shape: the casino pushes an opted-in streamer's settled bets and Impakt runs the rounds from them. No token on our side at all.
POST /api/operator/bets
X-Impakt-Timestamp / X-Impakt-Signature (the operator's secret, same scheme)
{ "operator": "acme", "channel": "<streamer>", "bets": [ { "id", "amount", "payout", "game", "updatedAt" } ] }
The first batch after a connect only primes; history never opens a round.
The cut
Impakt moves no money, so its share is settled by statement. Every settled or refunded round is recorded (handle, rake, paid, dust) and a signed call returns the period's totals with Impakt's share of the rake at the agreed basis points (shareBps in the operator's configuration):
POST /api/operator/statement { "operator": "acme", "from": <unix ms>, "to": <unix ms> }
-> { rounds, settled, refunded, handle, rake, paid, dust, refundedAmount, shareBps, share, currency }
The operator invoices against its own ledger; this statement is the reconciliation basis, not a balance.
The sandbox
A built-in operator called sandbox points at a mock wallet inside Impakt (/api/operator/sandbox/*), signed exactly like a real one. Any launch token creates a player with 1 000.00 EUR. Open https://impaktlive.gg/play?operator=sandbox&token=alice&channel=impakt in two browsers with two tokens and you have a demo, a certification target and an integration test in one.
Configuration
OPERATORS='[{"id":"acme","name":"Acme Casino","walletUrl":"https://wallet.acme.example/impakt","secret":"…","currency":"EUR","rakeBps":500,"minStake":100,"maxStake":100000}]'
SANDBOX_OPERATOR_SECRET=…
What this is not
Impakt does not accept deposits, hold balances, pay out, or set odds. It is a game provider on the operator's licence, like any studio behind an aggregator, and the operator's compliance (KYC, limits, jurisdictions) is the compliance that applies. Certification of the round logic (the pool arithmetic and the outcome source) is done with the operator's test lab.
Part of the IMPAKT crowdplay integration pack. All documents.