Skip to content

Operator configuration

These settings live in Settings → Integration. The two endpoints you must implement — the wallet RPC and the webhook receiver — are specified here.

Enabled games

In Settings → Integration you choose which games your players can launch. Today the only option is mystery_box. A launch for a game that isn’t enabled fails with GAME_DISABLED.

Currencies & locales

Declare the currencies and locales your brand supports so launches and on-the-fly switching can validate against them. See Localization & currency for the full model.

Custom box attributes

Attach your own typed properties to boxes — a flag, a number, or a short label — without waiting on a code change for each one. Under Boxes → Settings you declare an attribute once, giving it a name, a type (Yes/No, Number, or Text), and a default; then you set its value per box on the box’s edit page. Declaring or changing an attribute is cosmetic — it never republishes the box or changes its odds.

Your declared attributes ride along on every box you read over the API, under customAttributes, in both the catalog and box detail. Only attributes you’ve declared are sent, and the values are typed — a Yes/No attribute is a JSON boolean, a Number is a JSON number, Text is a string:

"customAttributes": { "is_purchasable": true, "featured_rank": 3 }

Because they’re stored as box metadata, your declared attributes are also filterable and sortable in the catalog via meta.<name> (e.g. sort=-meta.featured_rank).

Wallet RPC

The synchronous endpoint LootBox Solutions calls for every money movement. You implement this. Set its HTTPS URL in Settings → Integration; leaving it empty disables spending (every open returns WALLET_UNAVAILABLE).

All calls are POST, JSON, HMAC-signed with your outbound secret, and carry a type field. Money operations also send an Idempotency-Key header equal to the body’s idempotencyKey.

wallet.debit / wallet.credit

Sent when the player spends (open / shipping cost) or is paid (cashback / refund).

{
"type": "wallet.debit",
"playerExternalId": "u_8431",
"amountMinor": 500,
"currency": "EUR",
"idempotencyKey": "round:r_01J…",
"reference": { "kind": "round", "publicId": "r_01J…" }
}

Respond:

// accepted
{ "accepted": true, "balanceAfterMinor": 11500, "providerTxnRef": "txn_xyz" }
// refused
{ "accepted": false, "errorCode": "INSUFFICIENT_FUNDS" }
  • balanceAfterMinor and providerTxnRef are optional but recommended — balanceAfterMinor lets the game app update the balance without a second call.

  • Recognised refusal codes map to player-facing semantics:

    your errorCodeplayer sees
    INSUFFICIENT_FUNDS422 — not enough balance
    PLAYER_BLOCKED403 — your casino blocked this player
    anything else / no body503 — wallet unavailable

wallet.balance

A read for header display and heartbeat refresh.

{ "type": "wallet.balance", "playerExternalId": "u_8431", "currency": "EUR" }

Respond { "balanceMinor": 12500, "currency": "EUR" } (or { "errorCode": "…" }).

Rules you must honour

  • Timeout: LootBox Solutions waits 10 seconds. Transport failure, non-2xx, or unparseable JSON all map to WALLET_UNAVAILABLE; the player can retry, and nothing is lost.
  • Idempotency: the idempotencyKey is stable per real-world event — retries reuse it. Treat a duplicate as “already processed” and return the cached result. Never debit twice for the same key. Key shapes:
    • round:<roundPublicId> — opening a round.
    • cashback:inventory:<inventoryItemId> — cashing back an item.
    • refund:round:<roundPublicId> — refunding a held box.
    • shipping:player:<hash> — a shipping batch.
  • Currency: every call names the exact currency being moved. Process the amount in that currency. LootBox Solutions converts the box price once, at purchase, via the rate pinned for the player’s session — the amount and currency are final, and your wallet never does a second conversion. When a player changes display currency mid-session, the next purchase’s calls carry the new currency.

Webhooks

The async endpoint LootBox Solutions POSTs domain events to (set in Settings → Integration), HMAC-signed with your outbound secret. Same envelope; at-least-once delivery with exponential backoff.

A 2xx (any body) marks the dispatch delivered. A 4xx/5xx retries until the budget is exhausted, then parks the row as failed for reconciliation in the admin Integration screen. Dedupe on idempotencyKey.

Event types

Two kinds travel the same channel. Subscribe to the ones you need.

Instructions — you must act on these:

typeWhenYou should
bonus_entitlementA bonus prize was wonGrant the bonus in your system
fulfillment_noticeA physical item shipped / changed stateUpdate your records / notify the player

Observational — mirror state, no in-band settlement:

typeWhen
round_settledA round resolved (loyalty/XP, analytics)
box_version_publishedA box’s new version went live
box_updatedBox metadata changed
box_archivedA box was archived

Example: bonus_entitlement

{
"type": "bonus_entitlement",
"playerExternalId": "u_8431",
"idempotencyKey": "bonus:reel:917",
"payload": {
"itemId": 12,
"name": "Free spin",
"valueMinor": 0,
"currency": "EUR",
"roundPublicId": "r_01J…",
"metadata": { }
}
}

See Concepts for how bonus vs. cashback are split (cashback is a synchronous wallet credit, not a webhook).

Example: round_settled

Observational — a round resolved. Mirror it for loyalty/XP or analytics; there is nothing to settle in-band (the money already moved through the wallet RPC). outcome is the game-specific result blob (reels, won items, …).

{
"type": "round_settled",
"playerExternalId": "u_8431",
"idempotencyKey": "round_settled:r_01J…",
"payload": {
"dataVersion": 1,
"occurredAt": "2026-06-03T12:00:00Z",
"roundPublicId": "r_01J…",
"gameKey": "mystery_box",
"betMinor": 4200,
"payoutMinor": 1500,
"currency": "EUR",
"funding": "player",
"boxId": 42,
"outcome": { }
}
}

funding is player or operator — it tells you whether the player paid for this open or you funded it (operator-funded), so you can reconcile a free box differently from a paid round. boxId is the box this round opened, letting you attribute the settle back to the grant that funded it.