You implement five endpoints
GET /player · POST /debit · POST /credit · POST /rollback · GET /players/{accountId}/transactions/{transactionId}/zerodash/v1 is fine, as long as you verify against the same path.
Before you write code
Signature verification
Recompute and compare before touching the wallet. Non-negotiable.
IP allowlist
Only two source addresses may reach these endpoints.
Amounts and currencies
Decimals on the wire, minor units in storage, 8 places for crypto.
Idempotency
The same
transactionId must never apply twice.The endpoints
The round contract
Three rules, and every reconciliation question follows from them:Exactly one debit opens a round
Identified by
transactionId. Its gameRoundId is the round key.Exactly one settlement closes it
A credit or a rollback. Never both, never neither. The settlement carries
referenceTransactionId pointing back at the debit, and the same gameRoundId.Every settlement is eventually delivered
Credits and rollbacks are retried for up to 3 days, then escalated to manual review. A round does not get silently dropped.
The four rules that break integrations
A losing round still sends a credit
A losing round still sends a credit
When the player loses, you receive
POST /credit with payout.amount of 0. This is not an error and not an edge case — it is how a round closes.Create the transaction, credit zero, return the unchanged balance and 200 OK. Rejecting zero payouts leaves rounds open forever and puts every one of them into our retry queue.Credit and rollback must work with no player session
Credit and rollback must work with no player session
Neither carries a token. Both can arrive days after the round, long after the player logged out, and
/credit will keep being retried until it succeeds.Do not look up a session. Do not require the player to be online. Resolve the player from playerId and apply the movement.Free rounds debit a stake of zero
Free rounds debit a stake of zero
When
reason is freeround, stake.amount is 0. Subtract nothing — but still create the transaction and return a valid response with the current balance.The matching credit carries the winnings with the stake already deducted. Credit exactly what you are given. Each free spin is its own bet, with its own debit and its own credit.422 and 500 on debit mean opposite things
422 and 500 on debit mean opposite things
Return
500 when nothing was written and you get a rollback for a transaction you never had. Return 422 when the money did move and you never get the correction. Choose deliberately.Response shape
Debit, credit, rollback and the transaction lookup all answer with the same object:string
required
Your internal transaction ID. Stored by Zero-Dash for troubleshooting only — we never use it as a key.
object
required
The player’s balance after the operation was applied. A decimal value with its ISO-4217 currency. See Amounts and currencies.
string
ISO-8601 UTC creation time of the transaction. Defaults to the processing time when omitted.
Implementation checklist
Verify before you act
Signature, timestamp freshness, source IP. Reject with
401 and touch nothing.Look up transactionId first
Already processed? Return the stored result with
200 OK, without reapplying. See Idempotency.Apply the movement atomically
Write the transaction row and update the balance in a single transaction, with a unique constraint on
transactionId.Answer with the post-movement balance
Decimal amount, currency, and your internal transaction ID.
Choose failure codes deliberately
409 insufficient funds, 422 nothing was written, 500 something was. See Errors and retries.