# User

### [User API](https://docs.idosgames.com/api/api-v2/user) — Configuration & Logic

***

### 1. Overview

The User system provides core account-level operations for every player. It serves as the central hub for managing player data, inventory, virtual currencies, custom preferences, and account lifecycle.

The system supports the following features:

* **Client State** — single-call bootstrap that returns the full player state (profile, inventory, currencies, configuration, characters, quests, premium, etc.)
* **Inventory** — reading the player's items and virtual currency balances
* **Custom User Data** — storing and retrieving arbitrary key-value pairs per player (preferences, tutorial progress, UI state)
* **Currency Transfer** — converting one virtual currency into another based on configured allowed pairs
* **Currency Subtraction** — burning (spending) virtual currency from the player's balance
* **Item Consumption** — consuming/removing items from inventory by instance or by item type
* **Usage Time Tracking** — recording and retrieving player session time statistics
* **Account Deletion** — permanently removing a player's account and all associated data

<https://platform.idosgames.com/TitleID/liveops/user>

***

### 2. Configuration Structure

The User system relies on several sections within the title's `TitlePublicConfiguration`. Unlike the Character system, the User system has fewer dedicated configuration blocks — most of its behavior is determined by virtual currency definitions and inventory catalog settings configured elsewhere.

The key configurable element specific to the User API is:

| Field                          | Type                        | Description                                                     |
| ------------------------------ | --------------------------- | --------------------------------------------------------------- |
| `AllowedCurrencyTransferPairs` | List\<CurrencyTransferPair> | Whitelist of permitted currency-to-currency transfer directions |

***

#### 2.1. Allowed Currency Transfer Pairs

This section defines which virtual currency conversions are permitted via the `TransferVirtualCurrency` action. Each pair specifies a one-way direction — from one currency to another.

| Field            | Type   | Description                     |
| ---------------- | ------ | ------------------------------- |
| `FromCurrencyID` | string | Source virtual currency ID      |
| `ToCurrencyID`   | string | Destination virtual currency ID |

**Key Rules:**

* Transfer direction matters: configuring `DICE → CO` does **not** automatically allow `CO → DICE`. Each direction must be added separately if both are needed.
* System currencies (Coin, CoinLimit, Token, TokenLimit) are **always forbidden** regardless of configuration. The server enforces this hard block.
* The transfer is a 1:1 exchange by amount — the server subtracts `N` from the source and adds `N` to the destination.
* If `AllowedCurrencyTransferPairs` is empty or not configured, all transfer attempts will be rejected.

**How to add:** In the admin panel, enter the `FromCurrencyID` and `ToCurrencyID` for each allowed pair and click **+ Add**.

> 💡 This is useful for games where players can exchange one earned resource for another, such as converting dice/energy tokens into soft currency.
>
> 💡 Or, for example, you can create a "LIMIT" currency that is restored, for example, 10,000 per day, and use it to control the rewards of the "COIN" currency.

***

#### 2.2. Custom User Data

Custom User Data is a key-value store attached to each player. The client can read and write to it freely, with the following constraints:

* **System keys are reserved.** Any key that matches a value in the `SystemCustomUserDataKey` enum will be rejected. These keys are managed by the server internally.
* **Values are stored as strings.** Even if the client sends a number or object, the server serializes `Value` via `.ToString()`.

**Common Use Cases:**

* Tutorial/onboarding progress (`tutorial_step: "5"`)
* Player preferences (`language: "en"`, `music_volume: "0.8"`)
* UI state (`last_tab: "inventory"`, `seen_promo: "true"`)
* Feature flags or A/B test assignments (read-only from server, but client reads via `GetCustomUserData`)

> ⚠️ Do not store sensitive or game-critical data in Custom User Data, as it is client-writable. Use server-side systems (Leaderboards, Characters, Quests) for progression and economy.

***

#### 2.3. Virtual Currencies

Virtual currencies are defined in the title's economy configuration (not in the User-specific config). The User API provides two operations for spending currencies:

**SubtractVirtualCurrency** — directly removes a specified amount from the player's balance. The server checks:

1. `CurrencyID` and `SubtractAmount` are provided
2. Amount meets the minimum threshold (`IGSData.MIN_AMOUNT`)
3. Player has sufficient balance (no negative balances allowed)

**TransferVirtualCurrency** — moves an amount from one currency to another (1:1 ratio). Additional checks:

1. Source and destination currencies are different
2. Neither currency is a system currency
3. The pair is in the `AllowedCurrencyTransferPairs` whitelist
4. Player has sufficient balance in the source currency

> 💡 For purchase-related currency deductions (shop, upgrades, level-ups), use the dedicated systems (Store, Character, etc.) which handle the full transaction atomically. `SubtractVirtualCurrency` is intended for standalone burns (e.g., skipping a timer, unlocking cosmetics via client logic).

***

#### 2.4. Item Consumption

The `ConsumeItem` action allows the client to reduce item quantities in the player's inventory. Two modes are supported:

**By ItemInstanceID:** Targets a specific item instance. Useful when the player selects an exact item from their inventory.

**By ItemID (+ CatalogVersion):** Targets all instances of a given item type and consumes across them. Useful for fungible items like potions or resources where the specific instance doesn't matter.

**Equipped item protection:** An equipped item cannot be reduced to 0 quantity. The player must unequip it first (via the Character system) before fully consuming it.

> ⚠️ `CatalogVersion` defaults to `"Item"` if not provided. Ensure this matches your catalog setup to avoid consuming from the wrong catalog.

***

#### 2.5. Usage Time Tracking

The Usage Time system allows the client to periodically report how long the player has been active, and to retrieve aggregated statistics.

**AddUsageTime** — records a time increment for the current session. Call this periodically (e.g., every 60 seconds) from the client.

**GetUsageTime** — returns aggregated stats broken down by:

| Field          | Type                 | Description                            |
| -------------- | -------------------- | -------------------------------------- |
| `Today`        | int                  | Total usage time for today             |
| `Yesterday`    | int                  | Total usage time for yesterday         |
| `CurrentWeek`  | int                  | Total usage time for the current week  |
| `CurrentMonth` | int                  | Total usage time for the current month |
| `Total`        | long                 | All-time total usage time              |
| `History`      | Dict\<DateTime, int> | Raw daily history (date → time value)  |

> 💡 This data can be used for retention analytics, rewarding active players, or displaying play time in the player's profile.

***

### 3. API Logic

#### 3.1. GetClientState (Bootstrap)

`GetClientState` is the primary entry point when a player opens the game. It returns everything the client needs in a single call:

1. Loads the player's `UserData`
2. Refreshes authentication tokens if they are about to expire
3. Aggregates all player data (inventory, currencies, characters, quests, premium, social, leaderboard data, title configuration, etc.) into a `ClientStateResponse`

#### 3.2. Inventory Access

`GetUserInventory` returns the latest snapshot of the player's inventory, including:

* All owned item instances (with `ItemInstanceId`, `ItemId`, `CatalogVersion`, `RemainingUses`, `IsEquipped` status)
* Virtual currency balances (key-value dictionary of currency IDs to amounts)
* Virtual currency recharge times (if auto-recharge is configured)

#### 3.3. Rate Limiting & Locking

The User API enforces rate limiting and optimistic locking to prevent abuse:

* **Rate limit:** 1 request per 1 second per user

If a request arrives while the user is rate-limited or locked, it will be rejected. This applies to all User actions.

#### 3.4. Account Deletion

`DeleteUserAccount` permanently removes all player data. This action:

* Is irreversible
* Removes the player's database document entirely
* Should be gated behind a client-side confirmation dialog

> ⚠️ Consider implementing a soft-delete or cooldown period in your client UI before calling this endpoint. The server performs immediate permanent deletion.

***

### 4. Step-by-Step Configuration Guide

#### Step 1: Configure Virtual Currencies

Before using the User API's currency operations, ensure your virtual currencies are defined in the title's economy configuration. Common currencies include soft currency (Gold/Coins), hard currency (Gems/Crystals), and special currencies (Energy, Dice, Shards).

#### Step 2: Configure Currency Transfer Pairs (Optional)

If your game needs currency-to-currency conversion:

1. Navigate to the **AllowedCurrencyTransferPairs** section in the admin panel
2. For each permitted conversion, enter the **FromCurrencyID** and **ToCurrencyID**
3. Click **+ Add** for each pair
4. Remember: each pair is one-directional. Add both directions if bidirectional transfer is needed.

**Example pairs:**

| FromCurrencyID | ToCurrencyID | Description                |
| -------------- | ------------ | -------------------------- |
| DICE           | CO           | Convert dice into coins    |
| SH             | CO           | Convert shields into coins |

#### Step 3: Configure Item Catalogs

Ensure your item catalog is set up with the correct `CatalogVersion` (typically `"Item"`). The `ConsumeItem` action will default to this catalog if the client doesn't specify one.

#### Step 4: Save

After completing all settings, click **Save All (server)**. Changes are stored locally until saved to the server. The **Refresh** button allows you to discard local changes and reload current data from the server.

***

### 5. Player Data Structure

The `UserData` is the central storage model for each player. The User API reads from and writes to various fields within this document.

#### Key Fields Relevant to the User API

| Field             | Type                            | Description                                                   |
| ----------------- | ------------------------------- | ------------------------------------------------------------- |
| `UserID`          | string                          | Unique player identifier (database primary key)               |
| `TitleID`         | string                          | Title this player belongs to                                  |
| `Platform`        | string                          | Registration platform                                         |
| `Inventory`       | List\<ItemInstance>             | Player's item instances                                       |
| `VirtualCurrency` | Dict\<string, long>             | Currency balances (CurrencyID → amount)                       |
| `CustomUserData`  | GetCustomUserDataResult         | Key-value custom data store                                   |
| `Characters`      | Dict\<string, CharacterModel>   | Player's characters (see Character API)                       |
| `GameLoops`       | GameLoopsState                  | Board/game loop state                                         |
| `Premium`         | UserPremiumState                | Active premium subscriptions                                  |
| `Quests`          | UserQuestState                  | Quest progress and cycle state                                |
| `Social`          | UserSocialState                 | Friends lists (accepted, incoming, outgoing requests)         |
| `PublicData`      | UserPublicDataModel             | Public profile data (username, country, avatar, level, power) |
| `UsageTime`       | Dict\<DateTime, int>            | Daily usage time history                                      |
| `DailyRewards`    | Dict\<string, DailyRewardState> | Daily reward claim progress per calendar                      |
| `IsBanned`        | bool                            | Whether the player is banned                                  |
| `BanReason`       | string                          | Reason for the ban (if applicable)                            |

#### UserPublicDataModel

Public profile data visible to other players.

| Field       | Type   | Description                       |
| ----------- | ------ | --------------------------------- |
| `Username`  | string | Display name                      |
| `Country`   | string | Player's country                  |
| `AvatarUrl` | string | URL to avatar image               |
| `Vip`       | bool   | Whether the player has VIP status |
| `Level`     | int    | Player level                      |
| `Power`     | long   | Total power rating                |
| `NetWorth`  | long   | Net worth value                   |

***

### 6. API Actions

| Action                    | Description                                                                                              |
| ------------------------- | -------------------------------------------------------------------------------------------------------- |
| `GetClientState`          | Returns the full client state (profile, inventory, config, characters, quests, premium, etc.)            |
| `GetUserInventory`        | Returns the player's items and virtual currency balances                                                 |
| `GetCustomUserData`       | Returns the player's custom key-value data (excluding system keys)                                       |
| `UpdateCustomUserData`    | Sets a single key-value pair in custom data. Requires `Key` and `Value`                                  |
| `TransferVirtualCurrency` | Transfers currency between two types. Requires `FromCurrencyID`, `ToCurrencyID`, `TransferAmount`        |
| `SubtractVirtualCurrency` | Burns currency from the player's balance. Requires `CurrencyID`, `SubtractAmount`                        |
| `ConsumeItem`             | Consumes item uses/quantity. Requires `ItemInstanceID` or `ItemID` (+`CatalogVersion`), `SubtractAmount` |
| `DeleteUserAccount`       | Permanently deletes the player's account                                                                 |
| `GetUsageTime`            | Returns aggregated usage time statistics                                                                 |
| `AddUsageTime`            | Records additional usage time. Requires `UsageTime`                                                      |

***

### 7. Usage Examples

#### Example 1: Casual Game with Soft Currency

* **Currencies:** CO (Coins)
* **AllowedCurrencyTransferPairs:** empty (no conversions needed)
* **Custom User Data:** tutorial progress, sound settings, last level played
* **ConsumeItem:** used for single-use power-ups

#### Example 2: Idle/Tycoon Game with Multiple Currencies

* **Currencies:** CO (Coins), DICE (Dice/Energy), SH (Shields), IG (Gems)
* **AllowedCurrencyTransferPairs:**
  * DICE → CO (convert unused dice to coins)
  * SH → CO (convert shields to coins)
* **SubtractVirtualCurrency:** used for cosmetic purchases managed by client logic
* **Usage Time:** tracked for daily login rewards and session-based bonuses

#### Example 3: RPG with Inventory Management

* **Currencies:** CO (Gold), IG (Crystals)
* **ConsumeItem by ItemInstanceID:** player uses a specific health potion from inventory
* **ConsumeItem by ItemID:** batch-consume crafting materials (e.g., 10 iron ore)
* **Custom User Data:** class selection, keybindings, chat preferences

***

### 8. FAQ

**Q: What is the difference between `GetClientState` and `GetUserInventory`?** A: `GetClientState` returns everything — the full player profile, all configuration, inventory, characters, quests, premium state, etc. It's designed to be called once at app launch. `GetUserInventory` returns only the inventory and currency balances, and is cheaper to call for refreshing after a purchase or action.

**Q: Can the client write any key to Custom User Data?** A: Almost any key. The only restriction is that keys matching the `SystemCustomUserDataKey` enum values are reserved by the server and will be rejected. Use descriptive, prefixed keys (e.g., `ui_theme`, `pref_language`) to avoid collisions.

**Q: Is currency transfer a 1:1 exchange rate?** A: Yes. The server subtracts `TransferAmount` from the source and adds the same `TransferAmount` to the destination. If you need exchange rates (e.g., 10 Dice = 1 Coin), implement the ratio on the client side by adjusting `TransferAmount` accordingly, or use a different mechanism (e.g., Store offers).

**Q: Can I undo `DeleteUserAccount`?** A: No. Account deletion is permanent and irreversible. Always gate this behind a client-side confirmation dialog (ideally with a typed confirmation like "DELETE" to prevent accidental taps).

**Q: What happens if I call `ConsumeItem` on an equipped item?** A: If consuming would reduce the item's quantity to 0, the operation will be rejected. The player must unequip the item first via the Character API's `UnequipItems` action.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.idosgames.com/liveops/user.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
