Purchases

Selling in-game items through the platform, checking ownership, and gating rewards correctly.

Items are configured in the Store on the game page in the Studio, each with a slug and a price in Bits. An item is one-time (the player keeps it) or consumable (bought again for each use), and new items go on sale the next time you launch the game. The platform owns the purchase flow, the player's Bits and the record of what they own; the game only asks whether the player owns an item and starts a purchase when they want one.

Checking Ownership

await sdk.ready()

sdk.hasItem('super-skin')              // boolean
sdk.getItemPurchaseCount('super-skin') // number
sdk.purchasedItems                     // string[]
sdk.inventory                          // { slug, quantity }[]

Ownership comes from the player record the host sends at boot and may refresh during play. A successful purchase adds the item right away, so re-check after purchase() resolves or in onPurchaseComplete.

The record keeps the items a player owns for good. Consumables do not stay in it: the next boot does not list them, and a count can drop back when the host refreshes the record. Grant a consumable's effect when its purchase succeeds, and keep what it gave (an extra life, a coin pack) in your own save if it should last.

Starting a Purchase

async function buy(slug: string) {
  const { success } = await sdk.purchase({ item: slug })
  if (success) refreshUnlocks()
}

purchase() opens the platform's purchase sheet and resolves when it closes. Gate the reward on success, not on the call having been made. It resolves { success: false } when the player cancels or the platform cannot sell the item, such as a slug that is not on sale. Start one purchase at a time: a second call before the first resolves leaves the first unanswered.

Players can also buy from the host chrome without the game asking. sdk.onPurchaseComplete(({ success, item }) => …) fires either way, so keep ownership checks in one function and call it from both places.

Shop Items

sdk.shopItems and sdk.getShopItem(slug) describe the items the game page offers, when the host supplies them. Each has a slug and name, plus optional itemType, bitsCost (the price in Bits), description and iconUrl. Treat an empty list as "nothing to sell here" rather than an error; not every surface carries the catalogue.

Multiplayer

sdk.multiplayer.actions.purchase({ item }) is the same call for challenge sessions.

What not to do

  • Do not build a price list or currency in the game. Prices live on the platform, in Bits.
  • Do not unlock on purchase() returning; unlock on success.
  • Do not cache one-time ownership in game state. The host's record is the source of truth on every boot.