Case Unboxing allows users to open cases to win items. It supports single or multiple spins and demo mode.
Client -> Server
unboxing:spin
Opens one or more cases with real balance.
Payload:
{"caseIDs":["case-id-1","case-id-2"],// Array of 1-5 case IDs"clientSeed":"my-seed","fastSpin":true// or false to toggle fastMode of spin}
Constraints:
caseIDs must be an array with 1 to 5 items.
Special cases (level-X or free-case) must be opened individually (array length 1).
Response (Emit): Responds directly via unboxing:spin event with success/failure and results.
unboxing:demo-spin
Simulates case opening without using the user's balance.
Payload:
{"caseIDs":["case-id-1","case-id-2"]// Array of 1-5 case IDs,"fastSpin":true// or false to toggle fastMode of spin}
Response (Emit): unboxing:demo-spin.
Server -> Client
unboxing:pf
Emitted immediately before the result to establish the Provably Fair commitment.
Payload:
unboxing:spin (Response)
Returns the result of the spin.
Payload (Success):
unboxing:proof
Returns the server seed and nonce for verification after the animation is finished (~4 seconds).
Payload:
Level Cases
Level cases are free one-time cases that users unlock based on their XP level.
How it works
Case IDs follow the pattern level-{number} (e.g. level-5, level-10).
The user's effective XP is converted to a level via Auth.expToLevel(). They can only open the level case closest to (and not exceeding) their current level. For example, if available cases are levels 5, 10, and 15 and the user is level 12, they can only open level-10.
Each level case can only be opened once — if a user has opened a level case in the past, they cannot open it again.
Level cases are free — no balance is deducted (betAmount = 0).
Winnings are added directly to the user's balance.
Level case spins are not recorded as games.
Constraints
Must be opened individually — caseIDs array length must be 1.
Cannot be demo spun — attempting a demo spin returns "You cannot demo spin level cases".
Eligibility is validated via Rewards.dailyCases(userId, level, session) inside the transaction before the spin proceeds.
Opening a level case
Send the standard unboxing:spin event:
The response follows the same unboxing:pf → unboxing:spin → unboxing:proof flow as regular cases.
Fetching available level cases
GET /cases?type=true
Returns only level cases. Supports pagination via /cases/pagination?caseType=true.
Checking which level cases a user has opened
GET /rewards (requires auth)
Returns the user's rewards data. The history.dailyCases object contains a map of level case keys that the user has already opened. If a key exists for a given level, the user has already claimed that case and cannot open it again.
Example response:
A key like "level-5" existing in dailyCases means the user has already opened that level case — it cannot be opened again.
The absence of a key means the user has not opened that level case yet and is eligible (provided their level is sufficient).