> ## Documentation Index
> Fetch the complete documentation index at: https://docs.playtolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# In-game Stores

> List, search, and sell items with PlaytoliaStore

`PlaytoliaStore` provides the item catalog and purchase flow. It syncs automatically after login.

### Fetching items

```c# theme={null}
var allItems    = PlaytoliaStore.GetItems();
var consumables = PlaytoliaStore.GetItemsByType("Consumable");
var nonConsum   = PlaytoliaStore.GetItemsByType("NonConsumable");
var subs        = PlaytoliaStore.GetItemsByType("Subscription");
var results     = PlaytoliaStore.SearchItems("Gold");

var item = PlaytoliaStore.GetItemById("gold_500");
var item = PlaytoliaStore.GetItemBySku("com.mygame.gold500");
```

### StoreItem fields

`Id`, `Name`, `Sku`, `Type` (Consumable/NonConsumable/Subscription), `Grants[]`

Each `Grant` has: `GrantId`, `GrantType`, `GrantAmount`, `Currency?`

### Making a purchase

```c# theme={null}
PlaytoliaStore.BeginPurchaseFlow("gold_500",
    onSuccess: (receipt) =>
    {
        Debug.Log($"Purchase succeeded! Transaction: {receipt.ReceiptId}");
        Debug.Log($"Store: {receipt.Store}");
        Debug.Log($"Item: {receipt.Item.Name} ({receipt.Item.Sku})");
    },
    onError: (error) =>
    {
        Debug.LogError($"Purchase failed [{error.Code}]: {error.Message}");

        if (error.Code == "USER_CANCELLED")
        {
            // User backed out — no action needed
            return;
        }

        if (error.Stage == "ACKNOWLEDGEMENT")
        {
            // Player was charged, SDK will retry automatically
            ShowMessage("Your purchase is being processed.");
            return;
        }

        ShowMessage("Purchase failed: " + error.Message);
    }
);

// Also accepts a StoreItem directly
var item = PlaytoliaStore.GetItemById("gold_500");
PlaytoliaStore.BeginPurchaseFlow(item,
    onSuccess: (receipt) => { /* grant confirmed */ },
    onError: (error) => { /* handle error */ }
);
```

The `onSuccess` callback receives a `PurchaseReceipt` with the transaction ID, store, and purchased item. The `onError` callback receives a `PurchaseError` with a machine-readable error code, stage, and message. Both callbacks are optional.

When the purchase completes successfully, the SDK automatically updates the player's wallet, entitlements, and subscriptions.

### PurchaseReceipt

| Field       | Type        | Description                            |
| ----------- | ----------- | -------------------------------------- |
| `Item`      | `StoreItem` | The purchased store item               |
| `ReceiptId` | `string`    | Platform transaction ID                |
| `Store`     | `string`    | `"google_play"` or `"apple_app_store"` |

### PurchaseError

| Field       | Type      | Description                                      |
| ----------- | --------- | ------------------------------------------------ |
| `Code`      | `string`  | Machine-readable error code                      |
| `Message`   | `string`  | Human-readable description                       |
| `Stage`     | `string`  | `PURCHASE`, `VERIFICATION`, or `ACKNOWLEDGEMENT` |
| `ReceiptId` | `string?` | Set if the platform purchase succeeded           |
| `ItemId`    | `string?` | Playtolia store item ID                          |
| `ItemSku`   | `string?` | Platform SKU                                     |

### Error codes

| Code                     | Stage             | When                                               |
| ------------------------ | ----------------- | -------------------------------------------------- |
| `BILLING_UNAVAILABLE`    | `PURCHASE`        | Platform billing not available on device           |
| `ITEM_NOT_FOUND`         | `PURCHASE`        | Item ID not found in store                         |
| `USER_CANCELLED`         | `PURCHASE`        | User dismissed the purchase dialog                 |
| `PURCHASE_FAILED`        | `PURCHASE`        | Platform billing error                             |
| `VERIFICATION_FAILED`    | `VERIFICATION`    | Backend verification failed                        |
| `ACKNOWLEDGEMENT_FAILED` | `ACKNOWLEDGEMENT` | Platform acknowledgement failed after verification |

<Warning>Store data is empty until the player is authenticated. All item getters return `null` or empty lists before login.</Warning>

<Tip>
  When `Stage` is `ACKNOWLEDGEMENT`, the user has been charged but acknowledgement failed. The SDK automatically retries on next app launch. Show a reassuring message like "Your purchase is being processed."
</Tip>

### Listening to changes

```c# theme={null}
void Start()    => PlaytoliaStore.AddListener(OnStoreChanged);
void OnDestroy() => PlaytoliaStore.RemoveListener(OnStoreChanged);
```

<CardGroup cols={2}>
  <Card title="Wallets" icon="wallet" href="/for-unity/billing/wallets">Track currency after purchases</Card>
  <Card title="Entitlements" icon="certificate" href="/for-unity/billing/entitlements">Track non-consumable unlocks</Card>
</CardGroup>
