Skip to content

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/boxes
GET https://{operator}.app.lootboxsolutions.com/api/s2s/boxes?page=2&perPage=50
GET https://{operator}.app.lootboxsolutions.com/api/s2s/boxes?ids=1,2,3
GET https://{operator}.app.lootboxsolutions.com/api/s2s/boxes?sort=-meta.popularity&perPage=12&currency=EUR&locale=pt-BR
GET https://{operator}.app.lootboxsolutions.com/api/s2s/boxes?filter[meta.theme]=fantasy&sort=-price
QueryNotes
(none)All adoptable boxes (active, with a current version), sorted by name — the first page.
pagePage number, 1-based. Defaults to 1. See Pagination.
perPagePage size. Defaults to 100, capped at 200.
idsComma-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, meta.<key>.
sortOrdering — see Sorting. name (default), price, or meta.<key>; prefix with - for descending.
limitAlias for perPage, kept for widgets that just cap the strip.
localeBCP-47-ish code (e.g. en, pt-BR). Localizes display fields (e.g. name) where a translation exists. Defaults to the operator default.
currencyISO-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,
"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 },
"updatedAt": "2026-06-01T09:00:00Z"
}
],
"pagination": {
"page": 1,
"perPage": 100,
"total": 240,
"totalPages": 3,
"hasMore": true
}
}
FieldNotes
boxIdInteger id; pass to /launches or /purchase.
name, slugDisplay fields. name honours the requested locale where a translation exists.
imageImage 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, isPublishedLifecycle flags.
versionNumberThe current version; pricing/odds belong to a version.
priceMinor, currencyOpen price, in the requested currency.
houseEdgeBpsHouse edge in basis points (e.g. 600 = 6%).
customAttributesYour 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.
updatedAtLast change, for cache invalidation.
paginationThe current page’s position — see Pagination.

Pagination

The catalog is paginated. Each response carries a pagination envelope alongside boxes:

FieldNotes
pageThe page you’re on (1-based).
perPageThe page size in effect (defaults to 100, capped at 200).
totalTotal boxes matching the request, across all pages.
totalPagesNumber of pages at this perPage.
hasMoretrue when another page follows — keep walking.

To mirror the whole catalog, walk pages until hasMore is false:

GET /api/s2s/boxes?page=1&perPage=200
GET /api/s2s/boxes?page=2&perPage=200
…until "hasMore": false

Pagination 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.

sortOrders by
name / -nameBox display name. name (ascending) is the default.
price / -priceOpen price in the requested currency.
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&currency=EUR

Building your own lobby

A typical Model-B flow:

  1. Render your grid from GET /boxes (walking pages if your catalog is large; cache it; refresh on box_updated / box_version_published webhooks).
  2. On open, either:
    • mint a launch at that boxId and embed the iframe, or
    • read the box’s prize table to render your own box page, then call /purchase from your backend and render the result yourself.
  3. For a “Buy now” in a recommended widget, redirect the player to the box page and launch with autoOpen to 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 priceMinor belongs to its current version. Don’t hard-code prices — read them from the catalog (in the player’s currency) at render time.