Skip to main content
The status code you return is a contract. It tells Zero-Dash whether a transaction exists on your side, and that decides whether we send a correction.

Error body

Wherever an error can carry an explanation, use this shape:
Be specific. "currency mismatch: account is USD, request is EUR" closes a ticket; "error" opens one.

Status codes on debit

This is the table that matters most.
422 and 500 are opposites, and the difference is money.Return 422 only when you are certain nothing was written — a validation failure before any database work, a wallet service that refused the connection. We will not roll it back, because there is nothing to roll back.Return 500 when the transaction may exist — the write committed and the response failed, a timeout after the balance moved, an unknown state. We will send a rollback and retry it until it succeeds.Get it backwards and you either roll back a bet that never existed, or you leave a stake permanently deducted from a player who never played.
When you genuinely cannot tell, return 500. A rollback for a transaction you never created is answered with 404 and costs nothing. A stake stranded on a player’s account costs a support ticket and a manual correction.

Status codes on credit and rollback

There is no 422 here. A settlement always has to land: if it cannot be applied now, it is retried until it can, or a human looks at it.

Retry behaviour

Zero-Dash uses durable retry logic for failed credit and rollback calls.

Credit

10 retries, exponential backoff, spanning 3 days.

Rollback

10 retries, exponential backoff, spanning 3 days.
If all retries fail, Zero-Dash keeps retrying until the settlement resolves or the case is manually reviewed. A round is never silently abandoned.
Credit and rollback must not require a player session token.Requests can arrive days after the round finished. You must process them whether or not the player is logged in — resolve the player from playerId alone and apply the movement.Session-gated settlement endpoints are the most expensive integration bug we see: every retry fails, the round stays open for three days, and the player is missing a payout the whole time.

Reconciling after a failure

When a settlement keeps failing, or a debit ended in an ambiguous 500, Get transaction is how state gets compared.
Return 404 only when the transaction genuinely does not exist. A 404 returned because the lookup itself failed reads as “this bet never happened” and closes the round the wrong way.

Designing for the retry window

Make settlements terminal

Once applied, a credit or rollback stays applied. A later duplicate replays the stored result — see Idempotency.

Never expire an open bet

A debit can sit unsettled for three days. Do not sweep old pending transactions on a shorter timer; a cleanup job that voids them locally will disagree with our ledger.

Log the Zero-Dash IDs

Store transactionId, referenceTransactionId and gameRoundId on every row. They are the only keys we can search by during an incident.

Alert on repeated 4xx

A 400 on a settlement will keep arriving until you fix it. Catch that in your own monitoring rather than in a support thread.

Failure playbook

A signature problem, and it is almost always the path or the raw body. Work through Troubleshooting — verify against the path you registered, including any prefix, and against the untouched request bytes.
Your /credit handler is rejecting something systematically. The usual causes: zero payouts treated as invalid, a required session token, or a referenceTransactionId lookup that fails for free rounds.
Duplicate application. Check that transactionId is the primary key of your ledger and that the balance update shares a database transaction with the insert.
A debit that returned 422 after actually writing. We never rolled it back, because you told us there was nothing to roll back. Audit which code path returns 422 and confirm nothing can be written before it.