Checking entitlements instead of products means you can add plans, change prices, run experiments, and offer lifetime purchases — all without touching the client. One entitlement can be granted by many products and stays active as long as any granting purchase is valid.
Entitlements
Gate features on access levels instead of products, check them on device and server-side, and sync across platforms.
An entitlement is a level of access — pro, premium, gold. A
product is a purchasable SKU — pro_monthly, pro_annual, lifetime.
Products grant entitlements. Your app should always ask "is pro active?"
rather than "did they buy pro_monthly?"
Check on device#
After a purchase or restore, read the entitlement straight off the result:
let info = try await CashSDK.offerings()
if info.entitlements["pro"]?.isActive == true {
unlockPro()
}
// On launch, restore across reinstalls / new devices
try await CashSDK.restorePurchases()
val info = CashSDK.offerings()
if (info.entitlements["pro"]?.isActive == true) {
unlockPro()
}
CashSDK.restorePurchases()
const info = await CashSDK.offerings();
if (info.entitlements["pro"]?.isActive) {
unlockPro();
}
await CashSDK.restorePurchases();
Check server-side#
Never trust the client for anything that unlocks paid value on your backend. Ask CashSDK for the customer's live entitlements:
curl https://api.cashsdk.com/v1/apps/{app}/customers/u_812 \
-H "Authorization: Bearer csk_sk_..."
{
"app_user_id": "u_812",
"entitlements": {
"pro": {
"active": true,
"product_id": "pro_annual",
"expires_at": "2027-01-04T00:00:00Z",
"store": "app_store"
}
}
}
A client-reported isActive is great for UI, but authorize sensitive actions
(server-rendered content, API access, cloud features) against the API or a
verified webhook. See
receipt validation.
Cross-platform sync#
Entitlements follow the customer, not the device. Call
CashSDK.identify("u_812") with your own stable user id and CashSDK unifies
purchases made on iOS, Android, and Web under one customer. A subscription
bought on an iPhone unlocks pro on the same account's Android tablet and your
web app automatically.
CashSDK.identify("u_812")
Grant entitlements manually#
For support credits, promos, giveaways, or comping a beta tester, grant an
entitlement directly — no purchase required. Use the dashboard, or the
MCP server's grant_entitlement tool:
grant_entitlement(app_user_id="u_812", entitlement="pro", duration="30d")
Manually granted entitlements are first-class: they sync across platforms, are
returned by the customers API, and fire entitlement.granted /
entitlement.revoked webhooks just like purchased ones — so your backend
reacts the same way whether access came from a sale or a support gesture.