Skip to content
NORDONTalk to us
Developer help centre

The wallet contract

Five calls, amounts as digit strings, and one idempotency rule that the rest follows from.

For whoever writes or reviews the adapter.

Five calls

Contract version 1.0. Every call carries the version, so a mismatch is an error rather than a surprise.

launch
Exchange your token for a session. Once per game opening.
balance
What the player has now, in minor units. Read only.
debit
Take a stake for a round. Carries the stake source, cash or bonus.
credit
Pay a round out. Names the debit it pays against, and says so explicitly when the round returned nothing, so you can book a closed round rather than infer one.
rollback
Void a debit for a round that then did not happen. An adapter that cannot roll back is an adapter that can keep a stake for a round nobody played.

A stake

debit request
{
  "contract_version": "1.0",
  "transaction_id": "<ours, identical on every retry of this intent>",
  "player_ref": "<from the launch>",
  "game_id": "nordon.unicorn",
  "round_id": "<ours>",
  "amount_minor": "250",
  "currency": "EUR",
  "stake_source": "CASH"
}

An answer

Two shapes, discriminated by one field, so there is no answer that is neither.

wallet outcome
{ "ok": true,  "balance_minor": "1000", "partner_reference": "<yours, optional>" }

{ "ok": false, "code": "INSUFFICIENT_FUNDS", "partner_reference": "<yours, optional>" }

Idempotency is the rule everything else rests on

Every economic call carries a transaction identifier we choose, and it is the same on every retry of the same intent. A partner that answers slowly, or does not answer at all, has to be askable again without moving money twice.

So a repeated transaction identifier must not move the balance a second time. Answering it with the result of the first attempt is right; answering it with a duplicate error is acceptable and the kit accepts both. Moving the money again is the one thing that fails.

This is not a performance concern. It is the difference between a timeout costing a retry and a timeout costing a player their stake.

Amounts are digit strings

Every amount travels as a string of digits with no sign and no separators, in minor units at the scale the launch declared.

JSON numbers are doubles. A minor unit can exceed what a double holds exactly, and a balance that silently loses its last digit is a reconciliation meeting rather than a bug report. The conformance kit puts a value through your adapter that a double cannot hold and checks it comes back whole.

Error codes

Your platform has its own error vocabulary. The adapter maps it onto this one, because a code we do not recognise is a code we cannot act on.

CodeWhat it meansWhat the game does
INSUFFICIENT_FUNDSThe player cannot cover the stake.The round does not start. The player is told, and nothing is taken.
LIMIT_EXCEEDEDA limit on your side refuses this stake.The round does not start, and the game does not retry at a lower amount on behalf of the player.
DUPLICATE_TRANSACTIONThis transaction identifier was already settled.Treated as success. It is the answer to a retry, not a failure.
WALLET_TIMEOUTNo answer in time.We ask again with the same identifier. A stake already taken is rolled back if the round cannot start.
WALLET_UNAVAILABLEYour wallet is refusing traffic.The game stops accepting stakes rather than queueing them.
AUTH_INVALIDThe launch token is not one you will honour.The game does not open, and nothing is retried.
SESSION_EXPIREDThe session is no longer yours to honour.The game closes the session and the lobby has to launch again.
RG_SUSPENDEDA responsible gambling control on your side stops this player.Play stops immediately. Never softened into a generic failure.
MARKET_DISABLEDThis jurisdiction may not be served.The game does not open.
GAME_DISABLEDThis title may not be served to this player.The game does not open.