Notell API Docs
Русский

Integration

Wallet callbacks

The platform keeps no balance of its own. For every player action that touches money it calls your wallet endpoint. You implement one HTTPS endpoint that handles several method values.

Transport#

PropertyValue
URLPOST <callback URL>/<currency>, e.g. https://casino.example/wallet/UAH (currency in the path: UAH, USD, EUR, RUB)
Where to set the URLAdmin panel → Projects → your project → Integration (see Admin: projects)
BodyJSON object with sorted keys; includes api_key
AuthenticationThe project api_key in the body — compare it with your stored key
Time-out2 seconds per attempt; redirects are not followed
SuccessHTTP 2xx with the JSON answer below. A non-2xx status counts as a failure even if the body says ok
IdempotencyEvery bet / win carries a unique meta.transaction; a retry repeats the same id and body

If a project has no callback URL configured, the platform uses a built-in test wallet (starting balance 10 000.00 per currency) so you can try games before your wallet is ready.

The answer#

Every method is answered with:

json
{"status": "ok", "balance": 988.5, "currency": "UAH"}
FieldRule
status"ok" or "error"
balanceThe player's balance after the operation, as a JSON number (not a string)
currencyMust equal the currency in the request path; otherwise the answer is rejected as invalid
messageWith "status":"error": a code such as INSUFFICIENT_FUNDS

Methods#

session_info — read the balance#

Sent at game launch. Nothing is changed.

json
{
  "method": "session_info",
  "player_id": "player-123",
  "session_id": "9d0c3f7e-…",
  "api_key": "YOUR_API_KEY"
}

Answer with the current balance. If you answer with an error or not at all, the launch fails with BALANCE_UNAVAILABLE.

bet — debit the stake#

Sent before a paid round is played. Debit amount and answer.

json
{
  "method": "bet",
  "player_id": "player-123",
  "amount": 1.5,
  "meta": {
    "symbol": "gates-of-olympus",
    "time": 1789473600,
    "transaction": "6f1d0c9e-…",
    "round_id": "b2a7…",
    "session_id": "9d0c3f7e-…"
  },
  "api_key": "YOUR_API_KEY"
}
  • amount is a positive JSON number in currency units.
  • Free-spin rounds are sent with amount: 0 and extra meta; accept the zero bet when is_freespins is true:
json
"meta": {
  "transaction": "…", "round_id": "…", "session_id": "…", "symbol": "…", "time": 1789473600,
  "is_freespins": true,
  "freespins": {"grant_id": "…", "external_id": "promo-1", "nominal_bet": 1, "remaining": 9}
}
  • If the balance is too low, answer {"status":"error","message":"INSUFFICIENT_FUNDS","balance":0.5,"currency":"UAH"}. The round is rejected and nothing is played. Return this code only for a real lack of funds.

win — credit the result#

Sent when a round pays. amount is the total win of the round (positive; zero wins are not sent). The meta has the same fields as bet (symbol, time, transaction, round_id, session_id). For a free-spin round it also carries is_freespins: true and freespins: {grant_id, external_id, nominal_bet}.

json
{
  "method": "win",
  "player_id": "player-123",
  "amount": 12.75,
  "meta": {"symbol": "gates-of-olympus", "time": 1789473612, "transaction": "0b6e…", "round_id": "b2a7…", "session_id": "9d0c3f7e-…"},
  "api_key": "YOUR_API_KEY"
}

round_info — round notification (round summary)#

Informational: record it, change nothing, answer ok with the current balance. Two are sent per round, in order: start (after the debit is confirmed) and finish (after the credit is confirmed, or after the round ended without a win).

json
{
  "method": "round_info",
  "player_id": "player-123",
  "status": "finish",
  "round_id": "b2a7…",
  "session_id": "9d0c3f7e-…",
  "game_symbol": "gates-of-olympus",
  "currency": "UAH",
  "timestamp": 1789473615,
  "bet_amount": 1.5,
  "bet_type": "spin",
  "bonus_buy": false,
  "bonus_trigger": true,
  "win_amount": 12.75,
  "multiplier": 8.5,
  "has_win": true,
  "api_key": "YOUR_API_KEY"
}
FieldDescription
statusstart or finish
bet_amountStake of the round (nominal bet for free-spin rounds)
bet_typeType of bet of the round, for example spin or purchase
bonus_buyThe round was a bonus buy
bonus_triggerThe round triggered a bonus feature
win_amount, multiplier, has_winOnly on finish: total win, win ÷ bet, and whether it is positive
forcedtrue when the round was produced for an operator target outcome

The finish notification is the round summary: use it for reporting; money has already moved through bet and win.

freespins_finished — free-spins grant summary#

One per finished free-spins grant. Answer in the usual format ({"status":"ok","balance":…,"currency":"…"}); it is repeated until you do.

json
{
  "method": "freespins_finished",
  "grant_id": "7b1c…",
  "external_id": "promo-2026-10",
  "player_id": "player-123",
  "currency": "UAH",
  "game": "gates-of-olympus",
  "status": "used",
  "total": 10,
  "played": 10,
  "bet": "1.00",
  "total_win": "23.50",
  "finished_at": "2026-10-15T12:30:00.000Z",
  "api_key": "YOUR_API_KEY"
}

Order of calls in a round#

bet  ->  (debit confirmed)  ->  round_info start  ->  [play]  ->  win (if > 0)  ->  (credit confirmed)  ->  round_info finish

round_info finish is only delivered after round_info start was acknowledged.

Retries and failures#

SituationWhat the platform does
bet answered INSUFFICIENT_FUNDSThe round is rejected; nothing is retried
Any other error, an invalid answer, a non-2xx status or a time-out on bet / winThe operation is treated as unknown and retried later with the same transaction id and body until confirmed. The round stays pending meanwhile
round_info not answered okRetried later; a partner that does not respond is skipped for a while so that it never blocks others
freespins_finished not answered okRetried with growing delays: 10 s × 2<sup>attempts</sup>, at most 1 hour

Because retries are expected, your wallet must be idempotent: remember the answer you gave for each meta.transaction and return it again for a repeat of the same request. A repeat must never debit or credit twice.

Checklist for your wallet#

  • [ ] Verify api_key; serve HTTPS only; answer within 2 seconds.
  • [ ] Parse amount as a decimal; return balance as a JSON number.
  • [ ] Echo the currency from the URL path in currency.
  • [ ] Idempotency by meta.transaction (same id, same body → same answer).
  • [ ] Accept amount: 0 for bet when meta.is_freespins is true.
  • [ ] Answer round_info and freespins_finished with ok (status, balance, currency).
  • [ ] Use Test connection in the admin panel and watch API Logs while testing.
Documentation for operators and integrators.TEST_ONLY platform: non-withdrawable units, no real payments.