Skip to main content

Virtual Currency

Virtual currencies are digital assets used within your app to facilitate transactions, unlock premium features, or enhance customer engagement. These currencies are typically acquired through in-app purchases, rewards, or gameplay achievements and do not have intrinsic real-world value outside the application. They can be used for purchasing virtual goods, upgrading characters, or accessing exclusive content. Common examples include tokens, coins, credits, or other units that can be replenished through purchases. You can leverage virtual currencies to monetize apps, encourage customer retention, and create a more immersive experience.

πŸ“˜

This feature is in an early stage and may change without notice in future releases. To request access, please do so here.

Configuration​

In RevenueCat, virtual currencies are defined at the project level. You can configure up to 100 virtual currencies per project and use them to enrich your app experience.

  1. Click the β€œVirtual Currencies” option in the β€œProduct catalog” of your project sidebar in RevenueCat

  1. Select β€œ+ New” button in the top right corner. The β€œNew Currency” form will appear. Enter a code and a name for your currency.
  • Code: This is used across various APIs to identify the virtual currency (e.g: GLD)
  • Icon (optional): Choose an icon to visually represent this currency in the dashboard
  • Name: This should be a readable name for the currency that you're creating (e.g: GOLD)
  • Description (optional): A description of what this currency represents or how it is used (e.g: Can be used to purchase in-app items)

  1. You can optionally associate products with your new currency. Every time customers purchase one of these products, the defined amount of virtual currency will be added to their balance. Click "NEW ASSOCIATED PRODUCT", pick a product and fill in the amount.

You can associate as many products as you want with your virtual currency and you can also associate a product with more than one virtual currency, meaning once it's purchased, multiple types of virtual currencies are added to the customer's balance. If you have not yet configured any products, see our documentation for further instructions.

⚠️Only non-subscription products are supported

Currently, only non-subscription products, such as consumables, are supported for currency grants. When a customer purchases a non-subscription product linked to a virtual currency, we will automatically grant the corresponding currency amount to their balance. Subscription-based products are not yet supported for this functionality.

  1. Remember to select "SAVE" in the upper right-hand corner. Repeat this process if to create more than one currency.

Dashboard balances​

Once your customer purchase the associated products they will get the defined amount of your virtual currency. You can inspect the virtual currency balances of your customer in the right side-panel of the customer page.

SDK Beta Installation​

SDK support for virtual currencies is currently in beta, and as such requires the usage of a beta build. Please note that the virtual currency APIs in these betas are subject to change without warning in future releases. The beta virtual currency features are currently available in the native iOS and Android SDKs.

iOS​

Use the virtual-currency-beta branch of the purchases-ios SDK to access the virtual currency beta features. If you’re using Swift Package Manager, you can do this in Xcode like so:

Android​

When adding the purchases-android SDK to your app, use the most recent vc-beta version when adding purchases-android to your build.gradle:

Latest Virtual Currency Android Beta Release

implementation 'com.revenuecat.purchases:purchases:8.14.2-vc-beta.1'

When you use the beta virtual currency features, you’ll need to annotate your function/class with the @OptIn(ExperimentalPreviewRevenueCatPurchasesAPI::class) annotation:

import com.revenuecat.purchases.ExperimentalPreviewRevenueCatPurchasesAPI

@OptIn(ExperimentalPreviewRevenueCatPurchasesAPI::class)
fun printVirtualCurrencyBalances() {
for((vcCode, virtualCurrencyInfo) in customerInfo.virtualCurrencies) {
println("$virtualCurrencyCode: ${virtualCurrencyInfo.balance}")
}
}

Usage​

Prerequisites​

The endpoints available for virtual currency are supported through our REST V2 API endpoints. You will need a secret key to access it. Make sure that your key at least has Read & Write permissions for Customer Purchases Configuration. See our documentation for more details on how you can access RevenueCat’s REST V2 APIs.

Depositing or spending​

You can deposit or spend currency by calling the virtual currency transactions REST API V2 endpoint from the backend of your app:


curl --location 'https://api.revenuecat.com/v2/projects/<YOUR_PROJECT_ID>/customers/<YOUR_CUSTOMER_ID>/virtual_currencies/transactions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer sk_***************************' \
--data '{
"adjustments": {
"GLD": -20,
"SLV": -10
}
}'

The example request will deduct 20 GLD and 10 SLV from the customer's balance. Upon successful execution, the response will contain the updated balances of the virtual currencies that were spent.

Note that sufficient balances of both currency types are required for the transaction to succeed. If not, the transaction will fail with HTTP 422 error and no virtual currency will be deducted.

{
"items": [
{
"balance": 80,
"currency_code": "GLD",
"object": "virtual_currency_balance",
},
{
"balance": 40,
"currency_code": "SLV",
"object": "virtual_currency_balance",
},
],
"next_page": null,
"object": "list",
"url": "https://api.revenuecat.com/v2/projects/<YOUR_PROJECT_ID>/customers/<YOUR_CUSTOMER_ID>/virtual_currencies"
}

Multiple virtual currency types can be adjusted in a single transaction. Deductions and additions can also be combined. For example, you can execute the conversion of 50 GLD to 200 SLV with the following transaction:

{
"adjustments": {
"GLD": -50,
"SLV": 200
}
}

Reading balances​

From your backend​

The following endpoint allows you to retrieve a customer's current balance from your backend:

curl --location 'https://api.revenuecat.com/v2/projects/<YOUR_PROJECT_ID>/customers/<YOUR_CUSTOMER_ID>/virtual_currencies' \
--header 'Authorization: Bearer sk_***************************'

The response will include the balances for all the virtual currencies that the customer has.

{
"items": [
{
"balance": 80,
"currency_code": "GLD",
"object": "virtual_currency_balance"
},
{
"balance": 40,
"currency_code": "SLV",
"object": "virtual_currency_balance"
}
],
"next_page": null,
"object": "list",
"url": "https://api.revenuecat.com/v2/projects/<YOUR_PROJECT_ID>/customers/<YOUR_CUSTOMER_ID>/virtual_currencies"
}

From the SDK​

If you're using the virtual currency SDK betas, you can fetch the virtual currency balances from the CustomerInfo object in the SDK:

// Get the balance of a specific virtual currency
let balance = customerInfo.virtualCurrencies[<your_virtual_currency_code>]?.balance

// Iterate through all virtual currency balances
for(virtualCurrencyCode, virtualCurrencyInfo) in customerInfo.virtualCurrencies {
print("\(virtualCurrencyCode): \(virtualCurrencyInfo.balance)")
}

Best practices and security considerations​

Virtual currencies is a very powerful feature that RevenueCat provides, however it needs to be used correctly to ensure high standards of security. Here are some necessary requirements in order to make sure that bad actors cannot exploit your system for their benefit or to harm other users of your app.

Virtual currency transactions should be securely initiated by a backend server​

Transactions that add or remove virtual currencies to your customer balances, except for In-App Purchases, should be initiated by the backend of your Application. These requests require RevenueCat secret API keys to be authenticated, and these keys need to be securely stored and never be exposed to the public.

It’s fine if your backend provides APIs for your app to initiate virtual currency transactions, however, these APIs should not allow direct modifications of customer balances. Instead they should only support operations that do not require direct input of amounts and they should always perform the necessary validations to ensure that the customer has the rights and meets the requirements to perform the requested transaction.

See some examples of secure and unsecure backend APIs:

Do βœ…Do not! ❌
POST app_backend/virtual_product_purchase
{
"product_id": "machine_gun"
}
The backend knows the price of the product and charges accordingly. Also it should check that the customer has the right to purchase the product.
POST app_backend/virtual_product_purchase
{
"product_id": "machine_gun"
"price": "GLD 10"
}
The backend blindly attaches the product to the customer and spends the amount that is defined in the request.
POST app_backend/level_unlocked_reward_request
{}
The backend grants 100 Gold to the customer after checking that they indeed reached a new level in the game and the reward is not already provided.
POST app_backend/reward
{
"prize": "500 GLD"
"reason": "NEW_LEVEL_UNLCOKED"
}
The backend blindly rewards 500 GLD to the customer according the HTTP request data.

Following this will ensure that the users of your app cannot tamper / fake requests to your backend for their benefit.

Communication between your app and your backend should be encrypted and authenticated​

All the requests from your app to your backend that could trigger a virtual currency transaction need to be encrypted and authenticated. Make sure you use TLS or equivalent encryption technologies. Also ensure that all the requests that can trigger a virtual currency transaction are authenticated using well proved methodology.

Here are a few options to consider:

  • Password based authentication
  • Two/Multifactor authentication
  • Token based authentication (e.g. JWT, OAuth 2.0)
  • Single sign on using widely used services (Google, Facebook, Apple etc)
  • Other equivalent or stronger technologies

With this you will ensure that requests that could trigger virtual currency transactions for an account of your app can only be initiated by the actual account owner.

Tips & Hints​

Ensuring exactly one execution of Virtual Currency transactions​

As a common practice, you may implement retries to handle network or other errors when submitting a Virtual Currency transaction. If you want to ensure that your transaction will only be executed once, even if your request reaches our server more than one times, you can make use of our Idempotency-Key HTTP header. Make sure that you pass an identifier that uniquely identifies your transaction (e.g. a UUID) and it will be guaranteed that your transaction will be executed at most one time.

curl --location 'https://api.revenuecat.com/v2/projects/<YOUR_PROJECT_ID>/customers/<YOUR_CUSTOMER_ID>/virtual_currencies/transactions' \
--header 'Idempotency-Key: 2c15a0a5-8cf8-4eb3-95c2-56a343974663' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer sk_***************************' \
--data '{
"adjustments": {
"GLD": 20,
"SLV": 1
}
}'

Virtual Currencies are not transferable​

In contrast to regular In-App purchases that can be transferred to other customers during purchase restores, Virtual Currencies are not transferable, and once granted they will remain with the same customer until they are consumed.