Skip to main content
You can determine subscription status using the ZeroSettleKit SDK or the REST API.

Getting subscription status via the SDK

The entitlements property contains all of the purchase and subscription data available about a user. This is updated whenever a purchase completes or when you call restoreEntitlements().
// Restore and get current entitlements
let entitlements = try await ZeroSettle.shared.restoreEntitlements(
    userId: currentUser.id
)

// Or access cached entitlements
let cached = ZeroSettle.shared.entitlements
It’s safe to call restoreEntitlements() frequently throughout your app. The SDK caches entitlements locally and the network request is lightweight.

Checking If A User Is Subscribed

The subscription status for a user can be determined using the Entitlement objects returned by restoreEntitlements(). For most apps with a single premium tier, check for a specific product:
let hasPremium = entitlements.contains {
    $0.productId == "premium_monthly" && $0.isActive
}

if hasPremium {
    // user has access to premium features
}
If your app has multiple entitlements, check if any are active:
if entitlements.contains(where: { $0.isActive }) {
    // user has access to some entitlement
}
Entitlements will be empty if no purchases have been made. Always handle the empty case in your UI.

Restoring Purchases

Restoring purchases allows users to recover their in-app purchases on a new device or after reinstalling the app. It is recommended that all apps have a way for users to trigger restore, even if you require accounts.
do {
    let entitlements = try await ZeroSettle.shared.restoreEntitlements(
        userId: currentUser.id
    )
    // Update UI based on entitlements
    updatePremiumAccess(entitlements)
} catch {
    // handle error
}
This fetches entitlements from both ZeroSettle’s web checkout system and StoreKit/Play Store (if native transaction syncing is enabled).

Anonymous Users

restoreEntitlements() requires a userId. If your app doesn’t have a user account system (anonymous mode), entitlements are linked to the email address the user enters during Stripe checkout — not to a userId. This means:
  • During the session: After a successful purchase, the SDK caches entitlements in memory. The user has access for the remainder of the session without calling restoreEntitlements().
  • On a new session or device: restoreEntitlements() cannot recover entitlements without a userId. There is no SDK method for email-based restoration.
  • REST API workaround: You can query entitlements by email from your backend using the REST API (?email=user@example.com).
If your app uses anonymous checkout (empty userId), users will lose access to their entitlements when the app is reinstalled or on a new device. Consider prompting users to create an account after purchase, or use the REST API to implement email-based restoration in your backend. See User Identity — Anonymous Users for details.

Cache

The SDK caches the user’s subscription information in memory to reduce your app’s reliance on the network. The cache is not persisted to disk — it is cleared when the app process terminates. Users who unlock entitlements will be able to access them even without an internet connection for the duration of the session. The SDK will update the cache if it’s older than 5 minutes when you call restoreEntitlements(), make a purchase, or restore purchases. It’s a good idea to call restoreEntitlements() on app launch and any time a user accesses premium content.
Because the cache is in-memory only, you should call restoreEntitlements() on every app launch to rehydrate the user’s entitlements from the server.

Listening For Entitlement Updates

Entitlements can change from various sources: web checkout completion, StoreKit/Play Store transaction updates, or subscription renewals/cancellations. Use the delegate to respond to changes:
class PurchaseManager: ZeroSettleDelegate {
    init() {
        ZeroSettle.shared.delegate = self
    }

    func zeroSettleEntitlementsDidUpdate(_ entitlements: [Entitlement]) {
        // Handle any changes to entitlements
        updatePremiumUI(entitlements)
    }
}
You can also observe state reactively in your UI framework:
struct ContentView: View {
    @ObservedObject var iap = ZeroSettle.shared

    var body: some View {
        if iap.entitlements.contains(where: { $0.isActive }) {
            PremiumContent()
        } else {
            UpgradePrompt()
        }
    }
}
Entitlement updates are triggered by SDK operations (purchases, restores). They are not pushed from the backend in real-time.

Getting subscription status via the REST API

If you need to get a user’s subscription status from outside of the ZeroSettle SDK, for example, from your own backend, you should use the REST API. Query by user ID:
curl --request GET \
  --url https://api.zerosettle.io/v1/iap/entitlements?user_id=app_user_id \
  --header 'Content-Type: application/json' \
  --header 'X-ZeroSettle-Key: zs_pk_live_...'
Query by email (for anonymous users without a user ID):
curl --request GET \
  --url https://api.zerosettle.io/v1/iap/entitlements?email=user@example.com \
  --header 'Content-Type: application/json' \
  --header 'X-ZeroSettle-Key: zs_pk_live_...'
Either user_id or email is required. The email parameter is useful for recovering entitlements for anonymous users who purchased without a user account.
All API endpoints authenticate with your publishable key (zs_pk_live_... or zs_pk_test_...) via the X-ZeroSettle-Key header — the same key you use in the SDK.

Handling Refunds

ZeroSettle handles refunds for both subscription and non-subscription products. As soon as a refund is processed, the entitlements will be updated to reflect the correct status — no action required on your part. The isActive property on the affected Entitlement will be set to false.