Skip to content
Skip the menu

API reference

Purchases API

Sell an item to a player for virtual currency, debiting the wallet and delivering the item in one step, with the server API.

View as Markdown

On this page

A purchase turns coins into an item: the player pays the price of the item in its currency and receives the item. It happens in one step: either both the debit and the delivery are done, or nothing is. This is not a sale for real money: for that, see Checkouts. The examples on this page continue from the setup.

Buy an item with currency

Debits the price of an item, multiplied by the quantity, from the player's wallet, and adds the item to their inventory. Use it for every in-game shop where coins buy items.

POST/players/{player}/purchases

Authentication: secret key. Idempotency: required (Idempotency-Key header).

Path parameters

ParameterTypeDescription
playerstringA GameCoin player id, or ext:<your id> URL-encoded once. An unknown ext: player is created, with an empty wallet.

Body

FieldTypeRequiredRules
skustringyesThe sku of an active item that has a price: 1 to 48 characters.
quantityintegernoA whole number from 1 to 1,000,000,000,000. Default 1. The player pays the price times quantity.
LangageLanguage
curl -X POST "https://gamecoin.apilow.com/api/v1/players/ext%3Auser-42/purchases" \
  -H "Authorization: Bearer $GAMECOIN_SECRET_KEY" \
  -H "Idempotency-Key: buy-potion-user-42" \
  -H "Content-Type: application/json" \
  -d '{"sku": "potion", "quantity": 1}'

Response 200 OK: the debit, the new balance and the item.

FieldTypeDescription
entryLedgerEntryThe debit: type spend, with ref.itemSku set to the item.
balanceBalanceThe balance of the item's currency after the purchase.
itemInventoryItemThe item and the quantity the player owns after the purchase.
JSON
{
  "entry": {
    "id": "6ac4214e255a2e692cd84196",
    "type": "spend",
    "currency": "gems",
    "paidDelta": 0,
    "bonusDelta": -20,
    "balanceAfter": { "paid": 0, "bonus": 50, "total": 50 },
    "reason": null,
    "metadata": {},
    "ref": { "itemSku": "potion" },
    "createdAt": "2026-10-05T22:14:38.350Z"
  },
  "balance": { "currency": "gems", "paid": 0, "bonus": 50, "total": 50 },
  "item": { "sku": "potion", "quantity": 3, "updatedAt": "2026-10-05T22:14:38.396Z" }
}

Errors

StatusCodeWhenWhat to do
400IDEMPOTENCY_KEY_REQUIREDThe Idempotency-Key header is missing or emptySend one: see Idempotency.
400VALIDATION_FAILEDAn unknown field; sku empty or longer than 48 characters; quantity not an integer between 1 and 10¹²; a key that is not 1 to 100 printable ASCII charactersRead details.fieldErrors.
403PLAYER_BLOCKEDThe player is blockedNothing can be written for this player until the player is unblocked.
404NOT_FOUNDThe item is not in the catalog (or is archived), or a GameCoin id does not existCheck the sku against Get the catalog.
409INSUFFICIENT_FUNDSThe wallet is lower than the price times quantity: details.required and details.availableNothing was debited and nothing delivered. Offer a pack, or a smaller quantity.
409LIMIT_REACHEDThe purchase would take the player over the item's maxOwned: details.maxOwned and details.ownedNothing was debited. The player already has the item.
409CONFLICTThe item has no price in currencySell the item another way, or grant it.
409IDEMPOTENCY_CONFLICTThe key was already used with a different requestUse a new key for a new purchase.
JSON
{
  "error": {
    "code": "INSUFFICIENT_FUNDS",
    "message": "Insufficient funds",
    "details": { "required": 2000, "available": 935 }
  }
}

Notes

  • Replay. The same key with the same request returns the original response again, with the header Idempotent-Replayed: true, and changes nothing.
  • The debit and the delivery are one transaction: if the player cannot afford the item, or is at the item's limit, nothing changes. You never have to undo half a purchase.
  • The price is the one of the item in the catalog, in its own currency (gems for potion). Coins are taken the usual way: bonus first, then paid.
  • On this server route any item with a price can be sold. The client API only sells the items flagged clientPurchasable.
  • The ledger entry has no reason: it is identified by its ref.itemSku.
  • The first write on an unknown ext: player creates it; its purchase then fails with INSUFFICIENT_FUNDS.