Skip to content

Upgrader

The Upgrader is a single-shot trade-up game: the player stakes value, picks a win chance, and picks a target prize from the candidates the server allows for that stake. One provably-fair roll decides it — win grants the target item to the player’s inventory, loss grants nothing. Either way the stake is spent. The stake can be a balance amount or owned inventory items (see Wager-items mode).

These endpoints back a backend-driven Upgrader (your own frontend, or the storefront’s native render). To embed the Upgrader as an iframe instead, mint a launch with gameKey: "upgrader" — see Game-target launch below.

The Upgrader must be in your operator’s enabled games, and its win chances, house edge, and wager limits are configured in your operator admin under Settings → Upgrader. Prizes are drawn from your live catalogue — any active, fulfillable item whose value lands in the computed band is a candidate.

List candidate prizes

GET /api/s2s/upgrader/prizes resolves the target value band for a chosen wager + chance and returns the in-band catalogue items (highest value first), so your frontend can render the prize carousel and let the player pick a target. Read-only — nothing is staked or drawn here.

GET https://{operator}.app.lootboxsolutions.com/api/s2s/upgrader/prizes
?playerExternalId=u_8431&wagerMinor=10000&chanceBps=2500&currency=EUR
FieldRequiredNotes
playerExternalIdThe player the prizes are listed for.
wagerMinorThe stake, in minor units of the display currency.
chanceBpsThe chosen win chance in basis points (2500 = 25%). Must be one of the operator’s configured presets (see config.chancePresetsBps).
currencyISO-4217 display currency to price the band + prizes in. Defaults to the operator currency; must be one of your configured currencies.
localeBCP-47-ish content locale. Any value is served, falling back to best-available copy.

Response — 200

{
"wagerMinor": 10000,
"chanceBps": 2500,
"feeBps": 500,
"currency": "EUR",
"targetBand": { "lowerMinor": 34545, "upperMinor": 38000 },
"prizes": [
{ "itemId": 906, "name": "", "valueMinor": 38000, "currency": "EUR", "imageUrl": "https://…" }
],
"config": {
"houseEdgeBps": 500,
"chancePresetsBps": [1000, 2500, 5000, 7500, 9000],
"defaultChanceBps": 2500,
"maxChanceBps": 9500,
"minWagerMinor": 100,
"maxWagerMinor": 1000000,
"currency": "EUR",
"modes": { "balance": true, "items": false }
}
}
FieldNotes
targetBand.lowerMinor / upperMinorThe value window a target prize must fall in. Higher chance → narrower, lower band; lower chance → richer prizes.
prizes[]In-band candidates, highest value first. Default the player’s selection to prizes[0] (closest to the band top → best value). imageUrl may be null.
prizes[].valueMinorThe item’s value in the requested currency, repriced from the operator base.
config.chancePresetsBpsThe win-chance options to offer. defaultChanceBps is pre-selected.
config.maxChanceBpsThe largest chance the operator allows — you can’t buy a sure thing, so it’s capped below 100% by the house edge.
config.minWagerMinor / maxWagerMinorThe wager limits, in the requested currency. The max bounds the richest winnable prize.
  • Amounts are in the requested currency — the band, every prize value, and the wager limits, all repriced from the operator base at the current rate.
  • The list is bounded; a wager with no in-band catalogue item returns an empty prizes array (the band still resolves).

Play a round

POST /api/s2s/upgrader/play stakes the wager and plays one balance-mode round. LootBox Solutions calls your wallet.debit for the wager before the roll; a refused debit voids the round and moves no money. On a win the target item is granted (a normal inventory item, ready to cash back or ship).

POST https://{operator}.app.lootboxsolutions.com/api/s2s/upgrader/play
{
"playerExternalId": "u_8431",
"clientActionId": "5f2c…-per-click-uuid",
"wagerMinor": 10000,
"chanceBps": 2500,
"targetItemId": 906,
"currency": "EUR"
}
FieldRequiredNotes
playerExternalIdThe player to charge and credit.
clientActionIdIdempotency key for this player action (≤80 chars). A retry with the same value returns the original round — your wallet is never debited twice.
wagerMinorThe stake, in minor units of the display currency. Must be within the operator’s wager limits.
chanceBpsThe chosen win chance in basis points. Must be a configured preset, under the house-edge cap.
targetItemIdThe chosen prize. Its value must fall in the band for this wager + chance — the server re-checks, so a client cannot request a richer prize than the odds allow.
currencyThe currency to charge the player in. Defaults to the operator base; debited at the current rate when it differs.

Response — 200

{
"round": {
"publicId": "r_01J…",
"status": "settled",
"betMinor": 10000,
"payoutMinor": 38000,
"currency": "EUR",
"chanceBps": 2500,
"feeBps": 500,
"rolledBps": 1840,
"isWin": true,
"target": { "itemId": 906, "name": "", "valueMinor": 38000, "currency": "EUR", "imageUrl": "https://…" },
"fairness": { "serverSeedHash": "", "clientSeed": "", "nonce": 42, "algorithmKey": "hmac_sha256_v1" },
"settledAt": "2026-06-24T12:00:05Z"
},
"wonItem": { "inventoryItemId": 88, "itemId": 906, "name": "", "cashbackMinor": 30400, "currency": "EUR", "state": "unresolved" },
"balanceAfterMinor": 78000
}
FieldNotes
round.isWintrue when the roll landed in the win region.
round.rolledBpsThe roll as an integer in 0…9999; the round wins when rolledBps < chanceBps. Verify it against the fairness seeds.
round.payoutMinorThe granted value on a win, 0 on a loss.
round.targetThe prize the player aimed for (won on a win, missed on a loss).
wonItemThe granted inventory item, or null on a loss. cashbackMinor is what it could cash back for now (in the round’s player currency), null when not cashable.
balanceAfterMinorThe casino’s authoritative balance after the debit, in the round currency.
  • Amounts are in the player’s currencybetMinor, payoutMinor, the target value, and the won item’s cashbackMinor come back in the currency the wallet was charged in (cashbackMinor at the round’s pinned rate — the actual cash-back reprices at claim time).
  • A win is a normal inventory item: cash it back via /cashout or ship it via /shipping — no Upgrader-specific endpoints.

A refused debit returns the voided round and the casino’s error code:

{
"error": { "code": "INSUFFICIENT_FUNDS", "message": "" },
"round": { "publicId": "r_01J…", "status": "voided" },
"balanceAfterMinor": 0
}

Wager-items mode

Instead of staking a balance amount, a player can stake owned inventory items — items they previously won and haven’t yet shipped or cashed back. The wager is the staked items’ combined value, and the staked items are consumed on play, win or lose (just as a balance stake is spent). On a win the target item is granted on top; on a loss the staked items are simply gone. No wallet call is made for the stake — the items are the stake.

Whether this mode is available, plus the win chances, house edge, and wager limits, are configured in your operator admin under Settings → Upgrader (the same controls as balance mode). The two endpoints below mirror the balance pair; only the stake is expressed as items rather than money.

List candidate prizes by items

GET /api/s2s/upgrader/prizes-by-items sizes the wager from the staked items’ combined value and returns the same band + in-band candidates as the balance prizes call, plus a stake echo of the items the wager was sized from. Read-only — nothing is staked or consumed here.

GET https://{operator}.app.lootboxsolutions.com/api/s2s/upgrader/prizes-by-items
?playerExternalId=u_8431&stakeItemIds[]=88&stakeItemIds[]=91&chanceBps=2500&currency=EUR
FieldRequiredNotes
playerExternalIdThe player whose items are staked. Every staked item must belong to this player.
stakeItemIds[]One or more inventory item ids to stake (the inventoryItemIds from /inventory). Each must be owned and still open — not already shipped or cashed back.
chanceBpsThe chosen win chance in basis points. Must be one of the operator’s configured presets (see config.chancePresetsBps).
currencyISO-4217 display currency to price the band, prizes, and stake in. Defaults to the operator currency; must be one of your configured currencies.
localeBCP-47-ish content locale. Any value is served, falling back to best-available copy.

Response — 200

The same shape as balance prizeswagerMinor is the derived combined stake value (in the requested currency) — with one extra stake block:

{
"wagerMinor": 10000,
"chanceBps": 2500,
"feeBps": 500,
"currency": "EUR",
"targetBand": { "lowerMinor": 34545, "upperMinor": 38000 },
"prizes": [
{ "itemId": 906, "name": "", "valueMinor": 38000, "currency": "EUR", "imageUrl": "https://…" }
],
"config": { "…": "" },
"stake": {
"currency": "EUR",
"totalMinor": 10000,
"items": [
{ "inventoryItemId": 88, "itemId": 712, "name": "", "valueMinor": 6000, "currency": "EUR" },
{ "inventoryItemId": 91, "itemId": 540, "name": "", "valueMinor": 4000, "currency": "EUR" }
]
}
}
FieldNotes
wagerMinorThe combined value of the staked items, in the requested currency — the wager the band is computed from. The player doesn’t type it.
stake.totalMinorThe combined stake value; equals wagerMinor.
stake.items[]The staked items and the value each contributes, priced in the requested currency. An item is valued at its current catalogue value, so a since-appreciated item stakes for more.

Play with items

POST /api/s2s/upgrader/play-with-items stakes the named items and plays one round. The staked items are consumed regardless of outcome — no wallet call is made for the stake. On a win the target item is granted (a normal inventory item, ready to cash back or ship) on top of the consumed stake.

POST https://{operator}.app.lootboxsolutions.com/api/s2s/upgrader/play-with-items
{
"playerExternalId": "u_8431",
"clientActionId": "5f2c…-per-click-uuid",
"stakeItemIds": [88, 91],
"chanceBps": 2500,
"targetItemId": 906,
"currency": "EUR"
}
FieldRequiredNotes
playerExternalIdThe player staking the items. Every staked item must belong to this player.
clientActionIdIdempotency key for this player action (≤80 chars). A retry with the same value returns the original round — the stake is never consumed twice.
stakeItemIdsThe inventory item ids to stake (owned + open). Their combined value is the wager.
chanceBpsThe chosen win chance in basis points. Must be a configured preset, under the house-edge cap.
targetItemIdThe chosen prize. Its value must fall in the band for the staked value + chance — the server re-checks.
currencyDisplay currency for the response amounts. Defaults to the operator currency. No money moves on the stake side, so this only affects how amounts are shown.

Response — 200

The same shape as balance play — the settled round and the granted wonItem (or null on a loss) — plus a stake block listing the consumed items, and balanceAfterMinor: null (no wallet leg moved):

{
"round": { "publicId": "r_01J…", "status": "settled", "betMinor": 10000, "payoutMinor": 38000, "isWin": true, "…": "" },
"wonItem": { "inventoryItemId": 142, "itemId": 906, "name": "", "cashbackMinor": 30400, "currency": "EUR", "state": "unresolved" },
"stake": {
"currency": "EUR",
"totalMinor": 10000,
"items": [
{ "inventoryItemId": 88, "itemId": 712, "name": "", "valueMinor": 6000, "currency": "EUR", "state": "consumed" },
{ "inventoryItemId": 91, "itemId": 540, "name": "", "valueMinor": 4000, "currency": "EUR", "state": "consumed" }
]
},
"balanceAfterMinor": null
}
FieldNotes
round.betMinorThe combined staked value — recorded as the round’s wager, so it counts toward loyalty / reporting exactly like a balance round.
stake.items[].stateconsumed — the staked items are spent and can no longer be shipped or cashed back, win or lose.
balanceAfterMinorAlways null — the stake is items, not money, so no wallet balance changes on play.

A win is a normal inventory item; cash it back or ship it via the same endpoints as any other inventory item.

Game-target launch

To open the Upgrader inside the iframe, mint a launch token with gameKey: "upgrader" and an empty target — it’s a game target (the whole game), not a box:

{ "playerExternalId": "u_8431", "gameKey": "upgrader", "target": {} }

The session boots straight into the Upgrader (game.key = upgrader), with its selector config on the bootstrap. A boxId is rejected — the Upgrader has no box to pin.

Errors

codeHTTPwhen
UPGRADER_MODE_DISABLED403the requested Upgrader wager mode (balance or items) is off
UPGRADER_WAGER_OUT_OF_RANGE422wager below the min or above the max (for items, the combined staked value)
UPGRADER_CHANCE_INVALID422chance isn’t a configured preset, or exceeds the house-edge cap
UPGRADER_PRIZE_OUT_OF_RANGE422the target item isn’t an eligible prize, or its value is outside the band
UPGRADER_ITEM_NOT_OWNED422a staked item isn’t owned by the player, or isn’t available to stake (already shipped, cashed back, or spent)
GAME_DISABLED403the Upgrader isn’t in the operator’s enabled games
INSUFFICIENT_FUNDS422wallet refused — balance
PLAYER_BLOCKED403wallet refused — player state
WALLET_UNAVAILABLE503wallet timeout / 5xx / unconfigured
UNSUPPORTED_CURRENCY422currency not configured (or has no rate to price the round)
validation error422malformed input (e.g. a non-preset chance on prizes)

Same effect, two callers. The game app drives the equivalent in-iframe player-API upgrader/prizes + upgrader/play with a session token. This S2S pair is the backend-driven equivalent — same engine, same wallet calls, signed with your API key on behalf of a playerExternalId you supply.