Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2a7c13b
clarify test store
ekurutepe Sep 30, 2025
8071f94
introduce Test Store in Projects overview
ekurutepe Sep 30, 2025
8a67ba0
add a Test Store section
ekurutepe Sep 30, 2025
effe529
Disable swcHtmlMinimizer in configuration (#1177)
codykerns Oct 1, 2025
70cf1aa
more Test Store details
ekurutepe Oct 1, 2025
fd1969a
add Test Store info
ekurutepe Oct 1, 2025
66bc898
Test Store considerations in SDK config
ekurutepe Oct 1, 2025
384eac3
update launch checklist with test store
ekurutepe Oct 1, 2025
424aea5
sandbox testign with Test Store
ekurutepe Oct 1, 2025
b516080
simplify
ekurutepe Oct 1, 2025
201b7ca
add test store sandbox rules
ekurutepe Oct 2, 2025
32a2020
add clarification to Apple offer table
mshmoustafa Oct 1, 2025
d8e14e0
add store_transaction_id to non subscriptions objects (#1167)
alfondotnet Oct 2, 2025
662ddd7
added 60 min limitation to redemption link (#1179)
GuilhermeMota93 Oct 2, 2025
57b8067
Fixed RN code block awaiting for configure (#1180)
Jethro87 Oct 2, 2025
c466788
logIn method alias behavior doc improvement (#1181)
cperriam-rc Oct 3, 2025
64efc4f
Bump the all group with 2 updates (#1185)
dependabot[bot] Oct 6, 2025
73a826d
Bump crate-ci/typos from 1.36.3 to 1.37.2 (#1183)
dependabot[bot] Oct 6, 2025
83bcf0a
Bump @docusaurus/* from 3.8.1 to 3.9.1 (#1170)
dependabot[bot] Oct 6, 2025
4180ea6
Update support for new_product_id in PRODUCT_CHANGE events (#1111)
MarkVillacampa Oct 6, 2025
637eb9c
Support PRICE_INCREASE in Google (#1187)
greenietea Oct 6, 2025
ead60ff
Web-3122 Web home - Documentation updates (#1163)
iga-gawronska Oct 7, 2025
91e9638
update product config with Test Store
ekurutepe Oct 7, 2025
156d83a
add an overview for configuring products
ekurutepe Oct 7, 2025
53a062a
fix broken links
ekurutepe Oct 7, 2025
89facd5
add that test store API key will crash your app
ekurutepe Oct 7, 2025
39c172d
Merge remote-tracking branch 'origin/main' into engin/15min-to-paywal…
ekurutepe Oct 9, 2025
8e87858
add Test Store required SDK versions
ekurutepe Oct 9, 2025
a9e8f98
Fix link in managing-subscriptions.mdx (#1190)
egor-n Oct 9, 2025
2b5f8a4
fix required store versions
ekurutepe Oct 10, 2025
4884744
fix the versions again
ekurutepe Oct 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ jobs:
- name: Checkout Actions Repository
uses: actions/checkout@v5
- name: Spell Check Repo
uses: crate-ci/typos@v1.36.3
uses: crate-ci/typos@v1.37.2
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ...
await Purchases.configure({apiKey: <public_api_key>});
Purchases.configure({apiKey: <public_api_key>});
// ...
Purchases.enableAdServicesAttributionTokenCollection();
8 changes: 4 additions & 4 deletions code_blocks/test-and-launch/debugging_10.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
[Purchases] - DEBUG: ℹ️ PurchaserInfo cache is stale, updating caches
[Purchases] - DEBUG: ℹ️ Offerings cache is stale, updating caches
[Purchases] - DEBUG: ℹ️ Vending PurchaserInfo from cache.
[Purchases] - DEBUG: ℹ️ There are no requests currently running, starting request GET /subscribers/<APP_UESR_ID>
[Purchases] - DEBUG: ℹ️ API request started: GET /v1/subscribers/<APP_UESR_ID>
[Purchases] - DEBUG: ℹ️ API request started: GET /v1/subscribers/<APP_UESR_ID>/offerings
[Purchases] - DEBUG: ℹ️ There are no requests currently running, starting request GET /subscribers/<APP_USER_ID>
[Purchases] - DEBUG: ℹ️ API request started: GET /v1/subscribers/<APP_USER_ID>
[Purchases] - DEBUG: ℹ️ API request started: GET /v1/subscribers/<APP_USER_ID>/offerings
[Purchases] - DEBUG: ℹ️ No cached Offerings, fetching from network
[Purchases] - DEBUG: ℹ️ API request completed with status: GET /v1/subscribers/<APP_UESR_ID>/offerings 200
[Purchases] - DEBUG: ℹ️ API request completed with status: GET /v1/subscribers/<APP_USER_ID>/offerings 200
[Purchases] - DEBUG: ℹ️ Requesting products from the store with identifiers: {(
onetime,
annual,
Expand Down
8 changes: 4 additions & 4 deletions code_blocks/test-and-launch/debugging_12.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
[Purchases] - DEBUG: ℹ️ PurchaserInfo cache is stale, updating caches
[Purchases] - DEBUG: ℹ️ Offerings cache is stale, updating caches
[Purchases] - DEBUG: ℹ️ Vending PurchaserInfo from cache.
[Purchases] - DEBUG: ℹ️ There are no requests currently running, starting request GET /subscribers/<APP_UESR_ID>
[Purchases] - DEBUG: ℹ️ API request started: GET /v1/subscribers/<APP_UESR_ID>
[Purchases] - DEBUG: ℹ️ API request started: GET /v1/subscribers/<APP_UESR_ID>/offerings
[Purchases] - DEBUG: ℹ️ There are no requests currently running, starting request GET /subscribers/<APP_USER_ID>
[Purchases] - DEBUG: ℹ️ API request started: GET /v1/subscribers/<APP_USER_ID>
[Purchases] - DEBUG: ℹ️ API request started: GET /v1/subscribers/<APP_USER_ID>/offerings
[Purchases] - DEBUG: ℹ️ No cached Offerings, fetching from network
[Purchases] - DEBUG: ℹ️ API request completed with status: GET /v1/subscribers/<APP_UESR_ID>/offerings 200
[Purchases] - DEBUG: ℹ️ API request completed with status: GET /v1/subscribers/<APP_USER_ID>/offerings 200
[Purchases] - DEBUG: ℹ️ Requesting products from the store with identifiers: {(
onetime,
annual,
Expand Down
12 changes: 6 additions & 6 deletions docs/customers/user-ids.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -218,12 +218,12 @@ import contentKmpLogin from "@site/code_blocks/customers/user-ids_kmp_login.kts?

When logging in from an Anonymous ID to a provided custom App User ID, RevenueCat will decide whether the identities should be merged (aliased) into the same CustomerInfo object or not. This is decided depending on whether the provided custom App User ID already exists, and if it does exist whether it has an anonymous alias already.

| Current App User ID | Provided Custom App User ID already exists? | Provided Custom App User ID already has an anonymous alias? | Result |
| :------------------ | :------------------------------------------ | :---------------------------------------------------------- | :--------------------------------------------------------- |
| Anonymous | No | N/A | Anonymous ID and Provided ID have CustomerInfo merged. |
| Anonymous | Yes | No | Anonymous ID and Provided ID have CustomerInfo merged. |
| Anonymous | Yes | Yes | CustomerInfo transfers to Provided ID, no aliases created. |
| Non-anonymous | Any | Any | CustomerInfo transfers to Provided ID, no aliases created. |
| Current App User ID | Provided Custom App User ID already exists? | Provided Custom App User ID already has an anonymous alias? | Result |
| :------------------ | :------------------------------------------ | :---------------------------------------------------------- | :-------------------------------------------------------------------------------------------------- |
| Anonymous | No | N/A | Anonymous ID and Provided ID have CustomerInfo merged. |
| Anonymous | Yes | No | Anonymous ID and Provided ID have CustomerInfo merged. |
| Anonymous | Yes | Yes | Current User ID is logged out, Provided User ID is logged in. No merge or purchase transfer occurs. |
| Non-anonymous | Any | Any | Current User ID is logged out, Provided User ID is logged in. No merge or purchase transfer occurs. |

</details>

Expand Down
31 changes: 29 additions & 2 deletions docs/getting-started/configuring-sdk.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,30 @@ As detailed in the sample code above, debug logs can be enabled or disabled by s

Debug logs will provide detailed log output in Xcode or LogCat for what is going on behind the scenes and should be the first thing you check if your app is behaving unexpectedly, and also to confirm there aren't any unhandled warnings or errors.

## Testing with Test Store

After configuring the SDK, you can immediately start testing with your Test Store products—no additional SDK configuration required. Simply use your Test Store API key when initializing the SDK, and test purchases will work automatically.

See [Sandbox Testing](/test-and-launch/sandbox) for details on testing with Test Store vs platform sandboxes.

### Switching between Test Store and Real Stores

Test Store uses a **separate API key** from your real store API keys. This allows you to control which store your app communicates with:

- **Test Store API Key**: Use during development and testing
- **Platform Store API Keys** (iOS, Android, etc.): Use for production builds

You can find both types of keys in **Project Settings > API keys** in the RevenueCat dashboard. Switch between them by changing which key you pass to the SDK configuration.

:::danger CRITICAL: Never submit apps with Test Store API key
**You must NEVER submit an app to the App Store or Google Play that is configured with a Test Store API key.** Always use the correct platform-specific API key (iOS, Android, etc.) for release builds.

We recommend using build configurations or environment variables to automatically use the correct API key for each build type:

- **Development/Debug builds**: Test Store API key
- **Production/Release builds**: Platform-specific API key (iOS, Android, etc.)
:::

## Additional Configuration

The SDK allows additional configuration on first setup:
Expand Down Expand Up @@ -155,6 +179,9 @@ Called whenever _Purchases_ receives an updated `CustomerInfo` object. This may

## Next steps

Once you've configured the SDK, it's time to add your products in the dashboard.
Once you've configured the SDK, you're ready to set up your products:

- **Start with Test Store** (recommended): Your project already has a Test Store provisioned. [Create test products](/docs/offerings/products-overview) and start testing immediately.
- **Connect real stores**: When you're ready for production, [configure your products](/docs/offerings/products-overview) in App Store Connect, Google Play Console, or other platforms.

<Button href="/docs/offerings/products-overview">Add your products →</Button>
<Button href="/docs/offerings/products-overview">Set up your products →</Button>
61 changes: 46 additions & 15 deletions docs/getting-started/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,40 +15,60 @@ Before continuing with this guide, follow our [Setting up RevenueCat](/welcome/o

## 2. Product Configuration

### Store Setup
Now that your account is set up, you can start configuring your in-app purchase products. **Every new project automatically comes with a Test Store**, so you can start building and testing immediately—no Apple or Google accounts needed.

Before you can start using RevenueCat to fetch products, you must configure your products in the respective stores. See the following guides for [App Store Connect](/getting-started/entitlements/ios-products), [Google Play Console](/getting-started/entitlements/android-products), [Amazon Appstore](/getting-started/entitlements/amazon-product-setup), [Stripe](/getting-started/entitlements/stripe-products), and [Paddle](/getting-started/entitlements/paddle-products) for help navigating through this process.
### 2.1 Test Store (Recommended Starting Point)

If you are selling iOS products, be sure to sign your 'Paid Applications Agreement' and fill out your bank and tax information in **App Store Connect > Agreements, Tax, and Banking**. **This needs to be completed before you can test any purchases**.
Every new RevenueCat project includes a Test Store provisioned automatically. This lets you create products, configure offerings, and test the complete purchase flow—all without connecting to the App Store or Google Play.

:::info Want to skip the store setup while testing?
Test Store is perfect for early development: no platform accounts needed, instant setup, and works in environments like Expo where native APIs aren't available.

:::tip
See [Sandbox Testing](/test-and-launch/sandbox) for a complete comparison of Test Store vs platform sandboxes and recommended testing workflows.
:::

### 2.2 Connecting Real Stores (For Production)

Before you can submit your app for App Store or Play Store review, you MUST set up the corresponding store and configure your products there. See the following guides for [App Store Connect](/getting-started/entitlements/ios-products), [Google Play Console](/getting-started/entitlements/android-products), [Amazon Appstore](/getting-started/entitlements/amazon-product-setup), [Stripe](/getting-started/entitlements/stripe-products), and [Paddle](/getting-started/entitlements/paddle-products) for help navigating through this process.

If you are selling iOS products, be sure to sign your 'Paid Applications Agreement' and fill out your bank and tax information in **App Store Connect > Agreements, Tax, and Banking**. **This needs to be completed before you can test any purchases on real devices with Apple accounts**.

:::info Want to skip the real store setup while testing?
On iOS, you can delay configuring products in App Store Connect by testing with StoreKit Configuration files instead. These config files require minimal setup and are configurable via Xcode directly.

Read more about setting up StoreKit Configuration files in our [Sandbox Testing](/test-and-launch/sandbox/apple-app-store#ios-14-only-testing-on-the-simulator) guide.
:::

### Configure Products and Entitlements in RevenueCat
### 2.3 Configure Products and Entitlements in RevenueCat

<YouTubeEmbed
videoId="QxHeZiW4KCA"
title="RevenueCat Products, Offerings, and Entitlements Explained"
/>

Once your in-app products have been configured in [App Store Connect](/getting-started/entitlements/ios-products), [Google Play Console](/getting-started/entitlements/android-products), [Amazon Appstore](/getting-started/entitlements/amazon-product-setup), [Stripe](/getting-started/entitlements/stripe-products), or [Paddle](/getting-started/entitlements/paddle-products) you'll need to copy that configuration into the RevenueCat dashboard. RevenueCat uses an Entitlements system to control access to premium features, and Offerings to manage the set of products you offer to customers.
Whether you're using Test Store products or real store products, you'll configure them in RevenueCat using our Entitlements and Offerings system:

Entitlements are the level of access that a customer is "entitled" to after purchasing a specific product, and Offerings is a simple way for you to organize the in-app products you wish to "offer" on your paywall and configure them remotely. We **recommend** utilizing these features to simplify your code and enable you to change products without releasing an app update.
- **Entitlements** control the level of access a customer gets after purchasing a specific product
- **Offerings** organize the products you want to display on your paywall and let you configure them remotely

See [Configuring Products](/getting-started/entitlements) to set up your products and then organize them into Offerings or Entitlements.
We **strongly recommend** using Entitlements and Offerings—they simplify your code and let you change products without releasing an app update.

**Getting started:**

- **With Test Store**: Create products directly in RevenueCat, then organize them into Offerings and link them to Entitlements
- **With real stores**: After configuring products in [App Store Connect](/getting-started/entitlements/ios-products), [Google Play Console](/getting-started/entitlements/android-products), [Amazon Appstore](/getting-started/entitlements/amazon-product-setup), [Stripe](/getting-started/entitlements/stripe-products), or [Paddle](/getting-started/entitlements/paddle-products), copy that configuration into RevenueCat

See [Configuring Products](/getting-started/entitlements) for detailed setup instructions.

![Offerings Diagram](/docs_images/offerings/offerings-visual.png)

### Build and Design Your Paywall
### 2.4 Build and Design Your Paywall

<YouTubeEmbed videoId="PNiVCdExtkw" title="How to use RevenueCat Paywalls" />

After configuring your offerings, you can jump right into designing a paywall (even before installing the SDK!) by choosing Paywalls in the sidebar of your project dashboard.
After configuring your offerings (whether using Test Store or real store products), you can jump right into designing a paywalleven before installing the SDK! Just choose Paywalls in the sidebar of your project dashboard.

RevenueCat provides several pre-built, customizable paywall templates that you can use to rapidly create a paywall.
RevenueCat provides several pre-built, customizable paywall templates that you can use to rapidly create a paywall. Your Test Store products will work seamlessly with these paywalls, letting you test the complete user experience immediately.

If you'd prefer to install the SDK before designing your paywall, you can always come back to this step later.

Expand Down Expand Up @@ -125,7 +145,7 @@ If you have a user authentication system in your app, you can provide a user ide

At this point, you're ready to present a paywall to your users. If you skipped the paywall setup earlier, that's okay! The SDK will display a default, non-customized paywall. If you want to customize a paywall first, head back up to the [Build and Design Your Paywall](#build-and-design-your-paywall) section.

The SDK will automatically fetch the [configured Offerings](/getting-started/entitlements#offerings) and retrieve the product information from Apple, Google, or Amazon. Thus, available products will already be loaded when customers launch your paywall.
The SDK will automatically fetch the [configured Offerings](/getting-started/entitlements#offerings) and retrieve the product information from your Test Store or from Apple, Google, or Amazon (if you've connected real stores). Thus, available products will already be loaded when customers launch your paywall.

Presenting a paywall varies depending on your platform. See [Displaying Paywalls](/tools/paywalls/displaying-paywalls) to see in-depth examples for each platform.

Expand All @@ -144,13 +164,24 @@ If you're running into this error, please see our [community post](https://commu

### Make a Purchase

Once your paywall is presented, select one of your products to make a purchase. The SDK will handle the purchase flow automatically and send the purchase information to RevenueCat. The RevenueCat SDK will automatically handle sandbox vs. production environments.
Once your paywall is presented, select one of your products to make a purchase. The SDK will handle the purchase flow automatically and send the purchase information to RevenueCat.

**Testing with Test Store:**

- Test Store purchases work immediately without any additional setup
- They behave just like real subscriptions in your app
- No real money is charged
- Perfect for development and testing your integration

**Testing with real stores:**

Each platform requires slightly different configuration steps to test in sandbox. See [Sandbox Testing](/test-and-launch/sandbox) for more information.
- The RevenueCat SDK automatically handles sandbox vs. production environments
- Each platform requires slightly different configuration steps to test in sandbox
- See [Sandbox Testing](/test-and-launch/sandbox) for platform-specific instructions

When the purchase is complete, you can find the purchase associated to the customer in the [RevenueCat dashboard](/dashboard-and-metrics/customer-profile). You can [search for the customer](/dashboard-and-metrics/customer-lists#find-an-individual-customer) by their App User ID that you configured, or by the automatically assigned `$RCAnonymousID` that you'll find in your logs.

**Note:** RevenueCat **_always_** validates transactions with the respective store. The dashboard will only reflect purchases that have been successfully validated by the store.
**Note:** RevenueCat **_always_** validates transactions. Test Store purchases are validated by RevenueCat; real store purchases are validated by the respective platform (Apple, Google, etc.).

Additionally, the SDK will automatically update the customer's `CustomerInfo` object with the new purchase information. This object contains all the information about the customer's purchases and subscriptions.

Expand Down
Loading
Loading