Box catalog
GET /api/s2s/boxes returns the boxes available to your operator. Use it to build
your own lobby, product grid, or “most popular” widget
(Model B).
Request
GET https://{operator}.app.lootboxsolutions.com/api/s2s/boxesGET https://{operator}.app.lootboxsolutions.com/api/s2s/boxes?page=2&perPage=50GET https://{operator}.app.lootboxsolutions.com/api/s2s/boxes?ids=1,2,3GET https://{operator}.app.lootboxsolutions.com/api/s2s/boxes?sort=-meta.popularity&perPage=12¤cy=EUR&locale=pt-BRGET https://{operator}.app.lootboxsolutions.com/api/s2s/boxes?filter[meta.theme]=fantasy&sort=-price| Query | Notes |
|---|---|
| (none) | All adoptable boxes (active, with a current version), sorted by name — the first page. |
page | Page number, 1-based. Defaults to 1. See Pagination. |
perPage | Page size. Defaults to 100, capped at 200. |
ids | Comma-separated box ids — returns exactly those, regardless of state, so you can re-read previously adopted boxes and detect deactivations. |
filter[<key>] | Spatie query-builder style filter, e.g. filter[slug]=dragon-box or filter[meta.theme]=fantasy. Multiple keys combine with AND; comma-separate values for an OR within one key. Filterable: name, slug, isActive, isCollectible, meta.<key>. |
sort | Ordering — see Sorting. name (default), price, listed, or meta.<key>; prefix with - for descending. |
limit | Alias for perPage, kept for widgets that just cap the strip. |
locale | BCP-47-ish code (e.g. en, pt-BR). Localizes display fields (e.g. name) where a translation exists. Defaults to the operator default. |
currency | ISO-4217 code. Prices come back in this currency; must be one of your configured currencies. Defaults to the operator default. |
Response
{ "boxes": [ { "boxId": 42, "name": "Dragon Box", "slug": "dragon-box", "isActive": true, "isCollectible": false, "isPublished": true, "versionNumber": 7, "priceMinor": 500, "currency": "EUR", "houseEdgeBps": 600, "image": { "alt": "Dragon Box", "webp": "https://cdn…/boxes/dragon.webp", "default": "https://cdn…/boxes/dragon.png" }, "customAttributes": { "is_purchasable": true, "featured_rank": 3 }, "listedAt": "2026-03-14T08:30:00Z", "updatedAt": "2026-06-01T09:00:00Z" } ], "pagination": { "page": 1, "perPage": 100, "total": 240, "totalPages": 3, "hasMore": true }}| Field | Notes |
|---|---|
boxId | Integer id; pass to /launches or /purchase. |
name, slug | Display fields. name honours the requested locale where a translation exists. |
image | Image object with pre-converted format variants — webp and default URLs — plus alt. The default keeps the artwork’s original format, preserving transparency. Render a <picture> with the WebP source and the default fallback (see Images). |
isActive, isPublished | Lifecycle flags. |
isCollectible | true when the box is a collectibles box. It is an explicit marker, not something derived from the contents — a box can hold collectibles without being one. Use it to route the box into a dedicated collectibles surface: filter[isCollectible]=true for that grid, filter[isCollectible]=false for your main one. false for every box while collectibles are off for your operator (they are excluded from the catalog entirely). |
versionNumber | The current version; pricing/odds belong to a version. |
priceMinor, currency | Open price, in the requested currency. |
houseEdgeBps | House edge in basis points (e.g. 600 = 6%). |
customAttributes | Your custom box attributes — the typed properties you declared, with this box’s values (e.g. is_purchasable). Only declared attributes appear; {} when you’ve declared none. |
listedAt | ISO 8601 timestamp — the day the box went on sale. Set when the box is first published and left alone by every later republish or price update, so it is the field to build a “Newest” sort or a “New” badge on. An operator can move it by hand from the box page (to re-list an existing box); doing so sends a box_updated webhook. null for a box that has never been published — only reachable through ids. |
updatedAt | Last change, for cache invalidation. Changes on every edit, including cosmetic ones — don’t use it to decide what is new. |
pagination | The current page’s position — see Pagination. |
Pagination
The catalog is paginated. Each response carries a pagination envelope
alongside boxes:
| Field | Notes |
|---|---|
page | The page you’re on (1-based). |
perPage | The page size in effect (defaults to 100, capped at 200). |
total | Total boxes matching the request, across all pages. |
totalPages | Number of pages at this perPage. |
hasMore | true when another page follows — keep walking. |
To mirror the whole catalog, walk pages until hasMore is false:
GET /api/s2s/boxes?page=1&perPage=200GET /api/s2s/boxes?page=2&perPage=200…until "hasMore": falsePagination composes with filter[…], sort, ids, currency, and locale —
the envelope counts only the boxes matching your filters. A page past the last
one returns an empty boxes array (with hasMore: false), not an error.
Images
The image object ships each box artwork in several formats so you don’t
transcode anything yourself. Use a modern format with a safe fallback:
<picture> <source srcset="{box.image.webp}" type="image/webp" /> <img src="{box.image.default}" alt="{box.image.alt}" loading="lazy" /></picture>Sorting
Pass sort=<key> to order the list. Prefix the key with - for descending;
no prefix is ascending.
sort | Orders by |
|---|---|
name / -name | Box display name. name (ascending) is the default. |
price / -price | Open price in the requested currency. |
listed / -listed | The box’s listedAt date. -listed is “Newest first”. Boxes listed on the same day (everything an operator started with, for instance) fall back to the highest box id first, so the order is stable across pages; boxes with no listing date sort last. |
meta.<key> / -meta.<key> | A casino-controlled custom box property (meta.*) — e.g. meta.popularity, meta.featured_rank, meta.theme. Boxes without the property sort last. Use -meta.popularity for a curated “most popular” order. |
Combine with perPage for a tidy home-page strip — the first page is all you
need:
GET /api/s2s/boxes?sort=-meta.popularity&perPage=8¤cy=EURBuilding your own lobby
A typical Model-B flow:
- Render your grid from
GET /boxes(walking pages if your catalog is large; cache it; refresh onbox_updated/box_version_publishedwebhooks). - On open, either:
- mint a launch at that
boxIdand embed the iframe, or - read the box’s prize table to render your own box
page, then call
/purchasefrom your backend and render the result yourself.
- mint a launch at that
- For a “Buy now” in a recommended widget,
redirect the player to the box page and
launch with
autoOpento buy + play on arrival — or use a pre-pay purchase so the box auto-opens when the player next lands on it.
Keep prices fresh: a box’s
priceMinorbelongs to its current version. Don’t hard-code prices — read them from the catalog (in the player’s currency) at render time.