Skip to content

Box detail

GET /api/s2s/boxes/{boxId} returns the full detail for a single box — its price plus the complete prize table (each prize’s value, image, and drop odds) and the fairness snapshot link. Use it when you drive the open from your backend and render the box page, reel, and “show odds” list yourself.

The catalog (GET /api/s2s/boxes) lists box-level cards (name, price, image); this endpoint adds the per-box prize detail those cards don’t carry. Fetch it when a player opens a box page, then POST /purchase to open.

Request

GET https://{operator}.app.lootboxsolutions.com/api/s2s/boxes/42
GET https://{operator}.app.lootboxsolutions.com/api/s2s/boxes/42?currency=EUR&locale=pt-BR
QueryNotes
currencyISO-4217 code. The box price and every prize value come back in this currency; must be one of your configured currencies. Defaults to the operator default.
localeBCP-47-ish code (e.g. en, pt-BR). Localizes the box and prize names where a translation exists, falling back to the best-available copy. Defaults to the operator default.

Response

{
"box": {
"boxId": 42,
"boxVersionId": 1201,
"name": "Dragon Box",
"priceMinor": 500,
"currency": "EUR",
"isCollectible": false,
"snapshotUrl": "/fairness/box-version/1201/snapshot",
"customAttributes": { "is_purchasable": true },
"prizes": [
{
"itemId": 906,
"name": "Golden Sword",
"valueMinor": 320,
"currency": "EUR",
"imageUrl": "https://cdn…/items/golden-sword-card.png",
"imageUrlLarge": "https://cdn…/items/golden-sword.png",
"odds": 0.05,
"type": "physical"
},
{
"itemId": 1204,
"name": "Tarmogoyf — Modern Masters (NM)",
"valueMinor": 15200,
"currency": "EUR",
"imageUrl": "https://cdn…/items/tarmogoyf-card.png",
"imageUrlLarge": "https://cdn…/items/tarmogoyf.png",
"odds": 0.001,
"type": "physical",
"isCollectible": true,
"collectibleCategory": "mtg_card",
"metadata": {
"category": "mtg_card",
"schema_version": 1,
"card_name": "Tarmogoyf",
"set_code": "MMA",
"condition": "nm",
"language": "en"
}
}
]
}
}
FieldNotes
boxIdInteger id; pass to /purchase.
boxVersionIdThe current version. Pass this as the reels[].boxVersionId when you open so the player spins the exact version you showed.
nameDisplay name, honouring the requested locale.
priceMinor, currencyOpen price, in the requested currency.
isCollectibleMirrors the catalog flag, so a detail consumer never has to re-derive it. See Collectibles.
snapshotUrlPath to the public fairness snapshot for this version, relative to your operator host. Prefix it with your https://{operator}.app.lootboxsolutions.com origin to link players to it.
customAttributesYour custom box attributes (e.g. is_purchasable), with this box’s values. Only declared attributes appear; {} when you’ve declared none.
prizes[]One row per item in the box, in the order configured.
prizes[].itemIdThe item id. The same id comes back on a purchase win (reels[].prize.itemId / wonItems[].itemId), so you can map the outcome to the prize tile you rendered.
prizes[].nameItem name, honouring locale. Names are live, not snapshotted — a rename shows without republishing.
prizes[].valueMinor, prizes[].currencyPrize value, repriced into the requested currency. The value is frozen to the box’s current version.
prizes[].imageUrlCard-size image URL, or null when the item has no image.
prizes[].imageUrlLargeThe same image at its original (full) size, for an item-detail view — a dialog or zoom on the prize tile. null exactly when imageUrl is.
prizes[].oddsDrop probability as a fraction in [0, 1] (e.g. 0.05 = 5%). The rows sum to 1.
prizes[].typeThe item’s type: physical, digital, bonus or nuggets. A Nuggets prize is worth valueMinor in Nuggets at your own rate; show that amount where you show other prizes’ value.

Collectible prize fields

While your operator has collectibles enabled, a prize that is a collectible carries three additional fields (the example’s second row). The addition is strictly additive: a non-collectible prize — and every prize while the capability is off — has none of the three keys, never a false/null placeholder.

FieldNotes
prizes[].isCollectibleAlways true when present. This marks the prize item; it is independent of the box-level isCollectible — a mixed box can contain a collectible prize.
prizes[].collectibleCategoryThe collectible family (e.g. mtg_card, coin, sports_card) — the same values as inventory. Drives which metadata keys to expect.
prizes[].metadataDescriptive attributes for the item, keyed per category — the same shape and semantics as the inventory item-detail metadata: read live (not snapshotted), keys vary by category plus the reserved category / schema_version pair, render whatever is present rather than hard-coding a list. null for a collectible with no attributes. Internal admin-only keys (e.g. third-party pricing cross-references) are never included.

Use these to give the prize tiles an item-detail view — the full name, the imageUrlLarge image, and the attributes as a spec table — so a player can inspect a card before opening the box.

Current version — lightweight lookup

Open the exact version the player saw: pass the boxVersionId you rendered to /purchase as reels[].boxVersionId. If the box was republished in the meantime, that version is no longer current and the open is refused with BOX_NOT_PLAYABLE — surface a “refresh the page and try again” rather than opening a version whose prizes the player never saw.

To detect that before charging — e.g. to re-render the prize table when a box changed under the player — use the slim companion endpoint:

GET https://{operator}.app.lootboxsolutions.com/api/s2s/boxes/42/version
{
"boxVersionId": 1201,
"customAttributes": { "is_purchasable": true }
}

It returns the live boxVersionId plus the box’s customAttributes — no prices, FX repricing, or prize list. Compare the version to the one you rendered: if they differ, your page is stale. The attributes come back here too so a backend can apply a per-box rule (e.g. gate a purchase on is_purchasable) against a fresh value at open time, without re-reading the full detail. Same UNKNOWN_BOX / BOX_NOT_PLAYABLE errors as below.

Errors

codeHTTPwhen
UNKNOWN_BOX404no box with that id for your operator
BOX_NOT_PLAYABLE409the box is inactive or has no published version
UNSUPPORTED_CURRENCY422currency is not one of your configured currencies

Same data, two callers. The game app reads the equivalent in-iframe player-API box detail with a session token. This S2S endpoint is the backend-driven equivalent — same prize table, signed with your API key.