Notell API Docs
Русский

Features

RTP management

RTP (return to player) is the share of the stakes that the games pay back over time. The platform lets you steer it between 60 % and 100 %: for the whole project and, optionally, for each player. Use this page to understand which level a round gets and to manage player levels over the API.

How a round gets its RTP#

The level is resolved before the debit, inside the same transaction as the paid round, and then stays fixed for that round. A change applies from the next round; started rounds finish at their own level.

  1. Default. A project without saved RTP settings plays at 90 % (the provider RTP). The games' natural mathematics is used only if an owner explicitly saves "no provider RTP".
  2. Provider RTP set, personal RTP off. Every player's rounds are played at the project's provider RTP. Manual player levels are ignored.
  3. Personal RTP on. Each player has their own level (below).

Free-spin rounds go through the same logic and count in the adaptive window with their nominal bet. Target-outcome rounds are marked and do not count in the window.

Project settings#

Set in the admin panel under RTP & players (the platform owner edits the project settings; see Admin).

SettingMeaning
Provider RTPThe project's RTP, 60–100 %. Default 90 %. It is the ceiling for automatic levels and the starting level of each new player. Already registered players keep their start.
Personal RTPSwitches on per-player levels. Off means every player plays at the provider RTP.
Adaptive ruleOptional automatic correction of a player's level (below).
Bet limits per gameMinimum and maximum bet per game and currency (Bet limits).

Personal RTP of a player#

  • A new player is bound at their first round to the provider RTP that is current at that moment (start level = current level).
  • The level can be changed manually (admin panel or API, 60–100 %, up to two decimals, with a reason kept in the player's journal). A manual level freezes the adaptive rule for that player until you return them to auto.
  • In auto mode the player plays at their current level, capped by the provider RTP at the time. If the provider RTP is lowered below a player's level, the player plays at the provider RTP.
  • A manual level is not capped by the provider RTP.
  • The journal of every player records who changed the level, when and why (binding, rule steps, manual changes).

Adaptive rule#

The rule watches the realised return of a player's last settled rounds. If a player is too lucky it lowers their level a little; when the luck ends it brings them back, but never above their starting level.

ParameterMeaningDefault
Window, roundsHow many recent settled rounds are examined (50–100 000).1000
Lower if player RTP is above, %Window RTP above this lowers the level.150 %
Restore if below, %Window RTP below this raises the level back.90 %
Step, p.p.Change per step (0.1–20 percentage points).2 p.p.
Not below start minus, p.p.The level never drops further than this below the player's start (0–40).6 p.p.
Minimum turnoverPer currency: the rule ignores windows with a smaller total stake.none

At most one step is made per window. The level never goes below 60 %. Players with a manual level are not touched.

On short samples the observed RTP can differ from the target; this is normal.

POST /playerRtp.do#

Manage a player's level and personal bet limits. Every action needs partner, api_key and an allowlisted IP. The request is not idempotency-key aware and is not rate limited. Common fields:

FieldTypeRequiredDescription
partner, api_keystringyesYour project id and API key.
actionenumyesget, set, auto or bet-limit.
player_idstringyesThe player. Only letters, digits and _ . : @ -, 1–128 characters. This is stricter than launch: a player id with other characters can play but cannot be managed here.
providerenumnoendorphina, pragmatic or nolimitcity. Default endorphina, so pass it explicitly.

Every action answers {"status": "ok", "player": {…}}; the player object is described under get.

Errors that apply to every action: INVALID_ACTION (400) for an unknown action, INVALID_PLAYER (400) for a player_id outside the allowed characters, RTP_PROVIDER_UNSUPPORTED (400) for another provider.

get#

POST/playerRtp.doactionget

Returns a player's state for one provider.

Request#

curl
curl -s -X POST https://notell-api.com/playerRtp.do \
  -H 'Content-Type: application/json' \
  -d '{"partner":"demo-casino","api_key":"YOUR_API_KEY","action":"get","player_id":"player-1024","provider":"pragmatic"}'
JSON
{
  "partner": "demo-casino",
  "api_key": "YOUR_API_KEY",
  "action": "get",
  "player_id": "player-1024",
  "provider": "pragmatic"
}

The common fields above are the only ones.

Response#

json
{
  "status": "ok",
  "player": {
    "partner": "demo-casino",
    "player": "player-1024",
    "nickname": null,
    "bound": true,
    "provider": "pragmatic",
    "startBps": 9000,
    "currentBps": 8800,
    "mode": "auto",
    "roundsSinceAdjust": 120,
    "providerBps": 9000,
    "effective": {"bps": 8800, "source": "player"},
    "betLimits": [{"currency": "EUR", "minMinor": "10", "maxMinor": "5000"}],
    "journal": [
      {
        "provider": "pragmatic",
        "actor": "bind",
        "reason": "bound before the first round by a level change",
        "fromBps": null,
        "toBps": 9000,
        "fromMode": null,
        "toMode": "auto",
        "windowRounds": null,
        "windowRtpPpm": null,
        "at": "2027-02-15T10:00:00.000Z"
      }
    ],
    "providers": [
      {"provider": "pragmatic", "startBps": 9000, "currentBps": 8800, "mode": "auto", "roundsSinceAdjust": 120, "effective": {"bps": 8800, "source": "player"}, "updatedAt": "2027-02-15T10:00:00.000Z"}
    ]
  }
}
FieldTypeDescription
player.partner, player.playerstringYour project id and the player id.
player.nicknamestring or nullNickname of a player of the platform's own site, otherwise null.
player.boundbooleanThe player already has a level for this provider. When false, startBps and currentBps are 0 and effective is null.
player.providerstringThe provider this view is for.
player.startBps, player.currentBpsintegerStart and current level in basis points (9450 = 94.50 %).
player.modeenumauto or manual.
player.roundsSinceAdjustintegerRounds since the last rule step.
player.providerBpsinteger or nullThe project's provider RTP in basis points, or null if the project has no provider RTP.
player.effectiveobject or null{bps, source}: the level that applies if personal RTP is on. source is player, provider-cap (the provider RTP caps the level) or manual.
player.betLimitsarray<object>The player's limits per currency, {currency, minMinor, maxMinor} in minor units (strings).
player.journalarray<object>Latest changes, newest first, up to 100.
player.providersarray<object>The player's rows for each provider that has one.

Errors#

CodeHTTPWhen
INVALID_PLAYER400player_id is missing or has characters outside A-Z a-z 0-9 _ . : @ -.
RTP_PROVIDER_UNSUPPORTED400provider is not one of the three providers.

set#

POST/playerRtp.doactionset

Sets a manual level (mode manual). The player is bound to the provider on first use.

Request#

curl
curl -s -X POST https://notell-api.com/playerRtp.do \
  -H 'Content-Type: application/json' \
  -d '{"partner":"demo-casino","api_key":"YOUR_API_KEY","action":"set","player_id":"player-1024","provider":"pragmatic","rtp":94.5,"reason":"VIP agreement"}'
JSON
{
  "partner": "demo-casino",
  "api_key": "YOUR_API_KEY",
  "action": "set",
  "player_id": "player-1024",
  "provider": "pragmatic",
  "rtp": 94.5,
  "reason": "VIP agreement"
}
FieldTypeRequiredDescription
rtpnumberyesPercent, 60–100, at most 2 decimals, as a JSON number (94.5, not a string).
reasonstringnoUp to 200 characters, kept in the journal. Default: manual change.

Response#

{"status": "ok", "player": {…}} with mode: "manual", currentBps: 9450 and effective.source: "manual". The object is described under get.

json
{
  "status": "ok",
  "player": {
    "partner": "demo-casino",
    "player": "player-1024",
    "nickname": null,
    "bound": true,
    "provider": "pragmatic",
    "startBps": 9000,
    "currentBps": 9450,
    "mode": "manual",
    "roundsSinceAdjust": 0,
    "providerBps": 9000,
    "effective": {"bps": 9450, "source": "manual"},
    "betLimits": [],
    "journal": [],
    "providers": []
  }
}

(journal and providers are shortened here; the real answer lists them.)

Errors#

CodeHTTPWhen
RTP_LEVEL_INVALID400rtp is not a number or has more than 2 decimals.
RTP_LEVEL_OUT_OF_RANGE400rtp is below 60 or above 100.
INVALID_REASON400reason is not a string of up to 200 characters.
RTP_POLICY_REQUIRED400The project has no provider RTP (it was explicitly switched off).

auto#

POST/playerRtp.doactionauto

Returns the player to automatic mode: the adaptive rule resumes from the current level. The player is bound to the provider on first use.

Request#

curl
curl -s -X POST https://notell-api.com/playerRtp.do \
  -H 'Content-Type: application/json' \
  -d '{"partner":"demo-casino","api_key":"YOUR_API_KEY","action":"auto","player_id":"player-1024","provider":"pragmatic","reason":"VIP period over"}'
JSON
{
  "partner": "demo-casino",
  "api_key": "YOUR_API_KEY",
  "action": "auto",
  "player_id": "player-1024",
  "provider": "pragmatic",
  "reason": "VIP period over"
}
FieldTypeRequiredDescription
reasonstringnoUp to 200 characters, kept in the journal. Default: manual change.

Response#

{"status": "ok", "player": {…}} with mode: "auto". The object is described under get.

Errors#

CodeHTTPWhen
INVALID_REASON400reason is not a string of up to 200 characters.
RTP_POLICY_REQUIRED400The project has no provider RTP (it was explicitly switched off).

bet-limit#

POST/playerRtp.doactionbet-limit

Sets or removes a player's own bet limit for one currency. The limit applies together with the project limits; the smallest maximum wins (Bet limits).

Request#

curl
curl -s -X POST https://notell-api.com/playerRtp.do \
  -H 'Content-Type: application/json' \
  -d '{"partner":"demo-casino","api_key":"YOUR_API_KEY","action":"bet-limit","player_id":"player-1024","provider":"pragmatic","currency":"EUR","min_minor":"10","max_minor":"5000"}'
JSON
{
  "partner": "demo-casino",
  "api_key": "YOUR_API_KEY",
  "action": "bet-limit",
  "player_id": "player-1024",
  "provider": "pragmatic",
  "currency": "EUR",
  "min_minor": "10",
  "max_minor": "5000"
}
FieldTypeRequiredDescription
currencystringyesISO 4217 code, three capital letters.
min_minorstring or nullyesMinimum bet per spin in minor units, digits only, at least "1". "10" = 0.10.
max_minorstring or nullyesMaximum bet per spin in minor units, digits only, not below min_minor. "5000" = 50.00.

Both limits are required: send both as strings, or both as null to remove the limit.

Response#

{"status": "ok", "player": {…}}; betLimits shows the new limit. The object is described under get.

Errors#

CodeHTTPWhen
INVALID_CURRENCY400currency is not three capital letters.
INVALID_BET_LIMIT400min_minor / max_minor are not both strings of digits (or both null), min_minor is below 1, or max_minor is below min_minor.

See also#

Documentation for operators and integrators.TEST_ONLY platform: non-withdrawable units, no real payments.