Every purchase creates its own entry, so buying the same item twice gives you two. Each entry
carries a server-set status and used_at, both read-only — there is no call in either SDK that
marks an entry used.A purchase is money-safe. It is never retried after an ambiguous failure and never queued
offline, so it cannot double-charge. Inventory is always fetched fresh; the catalog is cached and
served offline, so treat a displayed price as advisory until the purchase succeeds.
A purchase does not grant the item’s contents. A shop item has a name, a status, a price and
a currency — there is no field describing what it gives, so the server has nothing to credit.
Buying a “1000 Gold” pack debits the price and records the entry; the gold is not added.Granting the contents from the game client is the only option today, and it is not safe for
anything you care about: the client can be modified to grant any amount, and a dropped connection
after the debit leaves the player charged with nothing to show for it. Server-side rewards are
tracked as a feature request.
Dashboard
Unity
Unreal
Configure shops and their items for a game version in the dashboard — set prices, currencies,
and availability.
Configure shops and items in the dashboard.
Use the SDK’s shop methods to list the shops and items available for your game version, then make
a purchase for the signed-in player. PurchaseAsync defaults to the signed-in player and returns
the inventory entry it created.
A declined purchase throws — catch FlockException and check ErrorCode for
FlockErrorCode.ShopInsufficientFunds to tell “can’t afford it” apart from a network failure.
Browse with the Flock | Shop nodes, or the shop provider in C++. An item’s free-form data and
stats read by dotted path, so no JSON parsing node is needed.
Purchase by picking a generated item — the ID is baked in and cannot be mistyped.
Sdk->GetShopProvider()->Purchase(ItemId, [](TFlockResult<FFlockPlayerInventory> Entry) { if (!Entry.bSuccess && Entry.Error.Code == EFlockErrorCode::ShopInsufficientFunds) { // The server declined — show the player, don't retry. } });