Virtual Currencies
Soft and premium currencies with auto-recharge, balance caps, and transaction history.
Define virtual currencies for your app. Currencies can be soft (earned through gameplay) or premium (purchased with real money), with optional auto-recharge for time-gated mechanics.
SDK usage
Get balances
Get transactions
Client API reference
| Method | Path | Description |
|---|---|---|
GET | /client/currencies | Get all currency balances |
GET | /client/currencies/transactions | Get transaction history |
MCP tools
| Tool | Description |
|---|---|
amba_currencies_create | Create a currency (soft/premium, auto-recharge, caps) |
amba_currencies_list | List all currencies |
amba_currencies_grant | Grant currency to a user (admin). Accepts idempotency_key for exactly-once grants. |
amba_currencies_spend | Debit currency from a user (admin). Atomic; rejects on insufficient funds. Accepts idempotency_key. |
Example: Hearts system
Currency options
| Field | Type | Description |
|---|---|---|
code | string | Unique code (e.g., "gold", "gems") |
name | string | Display name |
is_premium | boolean | Premium (real money) currency |
initial_balance | number | Spendable starting balance for new users (default 0) — see below |
max_balance | number | Balance cap (null for unlimited) |
auto_recharge_amount | number | Amount to auto-recharge |
auto_recharge_interval_hours | number | Hours between recharges |
Spendable starting balances
When a currency sets initial_balance > 0, that starting amount is real, spendable currency — not just a number the balance read displays. The first time a user is granted or spends the currency, Amba lazily credits the starting balance into the user's transaction history as a system transaction, then applies the grant or spend on top. From that point on, the balance read and the transaction history always agree: summing a user's transactions reconstructs their current balance.
This means a user can spend their starting balance immediately, even before their first grant. Currencies with initial_balance of 0 are unaffected — nothing is credited and the user starts empty.
Idempotent grants and spends
Both grants and spends accept an optional idempotency_key (string, ≤255 characters). It makes the operation exactly-once: if you replay a request with the same key for the same user and currency, Amba returns the original transaction with idempotent_replay: true and does not apply the balance change again.
The key is permanent — it's anchored to the ledger row it created, so there's no expiry window to manage. You control the dedup window entirely through what you encode into the key. Want to cap a reward at "one grant per share, per day"? Encode the day into the key:
The first call that day credits the balance and returns idempotent_replay: false. Every later call with the same key that day is a no-op replay that returns the original transaction — no double-grants, and no guard collection of your own to maintain. The next day's key is different, so the grant lands again.
One exception worth knowing: a spend that fails with insufficient funds stores no key (no ledger row was created), so retrying the same key after the user tops up is allowed and will go through.
Event-triggered grants
Grant currency automatically when a user action fires — no admin credentials needed on the client.
See Event-triggered Currency Grants for setup, grant modes, daily caps, and how it works.