https://wallet.luckystar.example/kinematic/:
The Wallet API reference has every field. This page explains the rules your implementation must keep. In the dashboard, the Connect your wallet step on Integration sums up the three calls with your wallet URL, and the page’s Wallet contract tab has the contract to read.
Sandbox casinos need no wallet: the game server keeps test balances. Build and test your wallet against a sandbox casino first, then switch to live. See Go live.
Signatures
Every call is aPOST with a JSON body and these headers:
Check every call before you act on it:
- Compute the HMAC over the exact bytes you received, before you parse them, and compare it with the header in constant time.
- Refuse a timestamp more than 60 seconds from your clock.
- Check that
Idempotency-Keyequals the body’sid, and that the path’s endpoint matches the body’skind.
verify.mjs
Receipts
Answer every call you accept with HTTP 200 and a receipt:idandcurrencyrepeat the request’s.statusisapplied, ordeclinedfor a debit the player cannot cover. Credits and balance reads are alwaysapplied.balanceis the player’s balance after the operation, in the currency’s minor units.revisionis your wallet-wide revision after the operation. It increases with every change to the account, including deposits, withdrawals and your other products. Two different balances never share a revision.amount,balanceandrevisionare canonical integer strings: digits only, no decimals, no signs, no leading zeros.- The receipt is a JSON object of at most 16 KiB.
Idempotency
Implement atomic, persistent idempotency, not only the endpoints:- Store each ID with a fingerprint of its request and the exact receipt you answered, in the same database transaction as the balance change.
- A repeated ID with the same body gets the original receipt, even if the balance has changed since.
- A repeated ID with a different body is a conflict. Refuse it with a status other than 200, such as 409. The game server never sends one.
- Never expire IDs while the game server may still retry them.
id or currency all count as unanswered. None of them counts as a declined debit, so a plain 400 never releases a bet.
Debits
- A debit can pay for several bets at once:
roundslists their bet IDs, and their stakes add up toamount. - Apply the whole amount, or durably record
status: "declined"and apply nothing. Never debit part of a batch. A declined ID stays declined if funds arrive later. - Lock and check the same account that your other products spend from.
- Record which rounds each applied debit named.
- A Blackjack double, split or insurance arrives as its own debit with an ID that starts with
stake_. Itsroundsholds the round’s bet ID andamountis the extra stake.
insufficient_funds. No money moved.
Credits
- The game server credits each round that pays on its own, as soon as the round ends. A losing round has no credit.
- A credit is the gross payout: it includes the returned stake, because the debit took the whole stake.
- Never decline a credit for funds. Credit availability is your liability. Answer
applied. - Each credit carries one settlement per round: the player’s signed bet, the revealed seed, the VRF proof and output, and the round’s steps. A refund carries
refundinstead. - A payout of a bet at a return to player other than 99% also carries
manifest, the payload of the signed math manifest the bet was placed under (about 7 KB). Its SHA-256 is themaththe player’s authorization signs, and it names the house edge the round paid at.
Balance reads
Several currencies
Every call names itscurrency, and a player’s currencies are separate accounts. Answer with that currency’s balance in its minor units, under the same currency. One revision counter across a player’s currencies works if it increases with every change it reports.
Balance changes outside the games
When a player deposits, withdraws or spends in another product, tell the game server. It reads the balance again after any settlement in progress and pushes it to every tab the player has open:wallet-events.mjs
/balance. Without hints, an open game refreshes its balance when the page becomes visible and every 30 seconds while it stays idle.
A reference wallet
This server keeps the contract with balances and receipts in memory. Use it to compare your implementation’s answers, never as storage:reference-wallet.mjs
reference-wallet.mjs
reference-wallet.mjs
Checking credits before they apply
Every payout credit carries what your wallet needs to check it: the player’s own signed bet, the seed it committed to, and the VRF proof under your casino’s key. A wallet that checks a credit applies no payout the engine does not compute from the proof of a round you debited. The check is optional. Kinematic’s verifier library implements it ascheckCredit; write to hello@kinematic.run to get it.
For each settlement, the check confirms, in order:
Your game server publishes its VRF keys, retired ones included, at
GET <game server>/v1/catalog under vrf.keys. A bet always settles under the key its acceptance named, even after a rotation.
Refuse a credit that fails the check with HTTP 409 and change nothing: