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.
- Click the βVirtual Currenciesβ option in the βProduct catalogβ of your project sidebar in RevenueCat
- 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)
- 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.
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.
- 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
:
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:
- Kotlin
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:
- Code
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.
- 200
- 422
{
"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"
}
{
"doc_url": "https://errors.rev.cat/unprocessable-entity-error",
"message": "Customer's balance is not enough to perform the transaction.",
"object": "error",
"param": "adjustments",
"retryable": false,
"type": "unprocessable_entity_error"
}
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:
- Code
{
"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:
- Code
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.
- Code
{
"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:
- Swift
- Kotlin
// 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)")
}
// Don't forget to opt in to experimental RevenueCat APIs with
// @OptIn(ExperimentalPreviewRevenueCatPurchasesAPI::class)
// Get the balance of a specific virtual currency
val balance = customerInfo.virtualCurrencies[<your_virtual_currency_code>]?.balance
// Iterate through all virtual currency balances
for((virtualCurrencyCode, virtualCurrencyInfo) in customerInfo.virtualCurrencies) {
println("$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! β |
---|---|
|
|
|
|
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.
- Code
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.