Migrating from RevenueCat
EntitleHub's model and SDK are intentionally close to RevenueCat's, so the move is mostly a rename and a re-point. This page maps the concepts and calls, and is honest about the one thing EntitleHub doesn't replace yet.
On Expo / React Native, @entitlehub/react-nativedrives the native StoreKit / Play Billing sheet and validates with EntitleHub in one call, a direct swap for RevenueCat's purchasePackage(). On other stacks, keep any billing library to open the sheet, then report the receipt to EntitleHub (see Purchases). EntitleHub replaces the whole backend: entitlements, server-side validation, state, webhooks.
Concepts
| RevenueCat | EntitleHub |
|---|---|
| Project / App | Project (its id is your app_id) |
| Entitlement | Entitlement (same idea; check the key) |
| Product | Product, mapped to entitlements |
| Offering / Package | /v1/offerings |
app_user_id | app_user_id, identical; use your own stable user id |
| Public SDK key | Publishable key (pk_live_…) |
| Secret API key | Secret key (sk_live_…) |
| CustomerInfo | CustomerInfo (isActive, active, …) |
| Webhooks | Webhooks (HMAC-signed) |
Calls
| RevenueCat SDK | EntitleHub |
|---|---|
Purchases.configure({apiKey, appUserID}) | new EntitleHub({apiKey: pk_…, appUserId}) |
Purchases.logIn / logOut | eh.logIn(id) / eh.logOut() |
getCustomerInfo() | eh.getCustomerInfo() |
customerInfo.entitlements.active["pro"] | info.isActive("pro") / info.active["pro"] |
getOfferings() | eh.getOfferings() |
purchaseStoreProduct() | your billing lib opens the sheet → server reportPurchase(...) |
restorePurchases() | billing lib restores → re-reportPurchase → re-read customer info |
| RC webhook → your DB | EntitleHub webhook → your DB (or read /v1/subscribers/{id} live) |
A typical purchase flow
// 1. App (client): open the native purchase sheet with your billing library.
const { purchaseToken } = await billing.purchase("app_pro_monthly");
// 2. App → your backend: send the token (never the secret key to the client).
await api.post("/iap/report", { productId: "app_pro_monthly", purchaseToken });
// 3. Your backend: validate + record via EntitleHub (secret key).
import { EntitleHubServer } from "@entitlehub/sdk";
const eh = new EntitleHubServer({ apiKey: process.env.ENTITLEHUB_SECRET_KEY! });
await eh.reportPurchase(userId, {
store: "play", storeProductId: "app_pro_monthly",
purchaseToken, isSubscription: true,
});
// 4. App: re-read entitlements (or wait for the webhook to update your DB).
const info = await eh.getCustomerInfo(); // client-side: eh.getCustomerInfo()Don't re-enter everything by hand. Dashboard → Import takes a RevenueCat v2 secret key + project id, reads your entitlements, products, and mappings, previews them, and creates them in EntitleHub. Read-only against RevenueCat.
Suggested cutover
- Set up your project, then Import your catalog from RevenueCat, grab keys, and add store credentials.
- Dual-write: on each purchase, report to EntitleHub in addition to RevenueCat, and compare entitlements for a week.
- Switch your app's reads to EntitleHub once they match.
- Drop the RevenueCat SDK: swap in EntitleHub's native SDK for your platform (Swift, Kotlin, Flutter, React Native), which drives the store purchase sheet for you. Prefer your own billing library? Keep it and report the receipt over the SDK or API.
