No extra setup
The SDK fetches and caches the mapping by itself and refreshes it when the copy is 25 hours old.
Feature
Paying customers keep their access when RevenueDot is down. The RevenueCat SDKs cache a product-to-entitlement mapping from your server and, when it answers with a 5xx, work out the customer's entitlements on the device from the store's own record of their purchases. RevenueDot serves the mapping for each app and answers 5xx, never 4xx, for its own failures.
Free up to $10,000 a month in tracked revenue. Works with the RevenueCat SDK you already ship.
The SDK fetches and caches the mapping by itself and refreshes it when the copy is 25 hours old.
Each app key gets its own app's products, keyed the way that app's SDK looks them up.
RevenueDot answers 5xx for its own failures and store outages, so the SDK's offline path runs when it should.
The purchase stays unfinished, so the SDK posts it again once the server is up.
It calls GET /v1/product_entitlement_mapping and caches the answer, refreshing it when the copy is 25 hours old.
GET /v1/subscribers/{app_user_id} or POST /v1/receipts answers 5xx and no customer info is cached.
It reads the active purchases from StoreKit or Google Play and looks each product up in the mapping.
The result is marked as verified on the device. The purchase stays unfinished, so the SDK posts it again once the server is back.
Google Play's bare key carries the entitlements of every base plan of the subscription, because Android's purchase record names the subscription but not the base plan. Nobody who paid loses access, and a customer on a cheaper base plan may see the richer plan's entitlements for at most a day, only while the server is down. Archived products still map. Consumables are left out.
| Store | Product in RevenueDot | Keys in the mapping |
|---|---|---|
| App Store | pro_monthly | pro_monthly |
| App Store, iOS 26.4 billing plan | pro_annual:monthly | pro_annual:monthly |
| App Store, up-front billing plan | pro_annual:upFront | pro_annual |
| Google Play | pro:monthly and pro:annual | pro:monthly, pro:annual and pro |
| Google Play, product without a base plan | legacy_pro | legacy_pro |
A secret key with no X-Platform header gets the whole project's mapping.
curl -s https://api.revenuedot.app/v1/product_entitlement_mapping \
-H "Authorization: Bearer $GOOGLE_APP_KEY"
# {"product_entitlement_mapping": {
# "pro:monthly": {"product_identifier": "pro", "base_plan_id": "monthly", "entitlements": ["pro"]},
# "pro:annual": {"product_identifier": "pro", "base_plan_id": "annual", "entitlements": ["pro", "cloud_sync"]},
# "pro": {"product_identifier": "pro", "base_plan_id": "monthly", "entitlements": ["pro", "cloud_sync"]}}} These limits are the SDKs' own, not RevenueDot's.
purchasesAreCompletedBy = .myApp).FAQ
Paying customers keep access. When the server answers 5xx, the RevenueCat SDK reads the customer's active purchases from StoreKit or Google Play and maps each product to entitlements with a mapping it cached from RevenueDot. Access is computed on the device until the server is back.
No. It is a feature of the RevenueCat SDKs and needs only the normal setup. RevenueDot serves the mapping at GET /v1/product_entitlement_mapping for each app, and the SDK fetches and refreshes it by itself.
A 4xx tells the SDK the purchase can never be accepted, so it finishes the transaction. A 5xx tells it to try again later and to use the offline mapping. RevenueDot answers 5xx for its own failures and store outages so purchases are not dropped.
No. The SDK does not use it in observer mode, with the Test Store or on iOS before version 15. A pending consumable on iOS and any active one-time purchase on Android also return an error instead.
Get started
Start free on RevenueDot Cloud, free up to $10,000 a month in tracked revenue, or move an existing RevenueCat app with one line of code.
Already have an account? Sign in · Prefer your own servers? Self-host free