Entitlements
Track which users have access to which features. Amba is the entitlements layer — wire any subscription source (or none) into it.
An entitlement is Amba's abstraction for "does this user have access to a feature." It's a row in user_entitlements keyed by (app_user_id, entitlement_id) that your app reads at runtime to gate paid content.
Amba is the entitlements layer. The subscription source is your choice. Grant entitlements directly from your server (Stripe, Paddle, manual ops, gift codes, comp grants, anything), wire in an optional integration like RevenueCat or Superwall, or mix the two. Every entitlement ends up in the same table and is read through the same client API regardless of where it came from.
Data model
user_entitlements:
| Column | Purpose |
|---|---|
app_user_id | The user who owns the entitlement |
entitlement_id | Logical identifier (e.g. "premium") |
product_id | Store product identifier |
is_active | Whether the entitlement is currently valid |
store | "app_store" / "play_store" / "stripe" / "manual" / ... |
period_type | "trial" / "intro" / "normal" / ... |
purchase_date | First purchase timestamp |
expiration_date | When the current period ends (NULL for lifetime) |
The columns are whitelisted for segment targeting — see Segment operators.
Grant entitlements from your server
This is the universal path — works for any source.
The handler upserts on (app_user_id, entitlement_id), so a second call for the same pair refreshes the row in place. To revoke, pass is_active: false. To clear a column (e.g. extend a finite subscription to lifetime), pass that field as null.
Use this directly from:
- Stripe / Paddle / web checkout webhooks — your backend receives the payment event, upserts the entitlement.
- Manual admin tooling — support comps a month, refund a chargeback, grant a gift code.
- Migrations from legacy systems — backfill entitlements once at import time.
- App Store / Play Store Server Notifications — if you'd rather wire StoreKit Server Notifications and Google Play RTDN directly than use a middleman.
- Your own paywall / subscription service — anything that knows whether a user should have access can write to this endpoint.
See the full reference: POST /admin/projects/:projectId/users/:userId/entitlements.
Optional: sync from RevenueCat
If you use RevenueCat for mobile subscriptions, Amba accepts its webhook and maps the events into the same user_entitlements table. Skip this section if you don't use RevenueCat.
| RevenueCat event | Effect |
|---|---|
INITIAL_PURCHASE | Upsert active entitlement row |
RENEWAL | Extend expiration_date |
CANCELLATION | Mark for expiry at period end |
EXPIRATION | is_active = false |
BILLING_ISSUE | Flag on the entitlement for UI to surface |
Setup: RevenueCat integration.
Optional: sync paywall events from Superwall
If you use Superwall, Amba mirrors its paywall events (shown, dismissed, purchased, ...) as engagement events named superwall_<event> so streaks, XP rules, and segments can target paywall behavior alongside first-party events. Skip if you don't use Superwall.
Setup: Superwall integration.
Checking entitlements in the SDK
Both methods hit GET /client/entitlements:
UserEntitlement shape:
Example: gate a premium feature
Targeting by entitlement
Entitlement fields can drive segment rules, which in turn drive push campaigns and remote-config overrides:
See Segment operators for the full list of supported entitlement fields.
Local caching
The SDK does not cache entitlements client-side beyond the fetch lifetime. For performance-sensitive gates, fetch once on launch (after Amba.init() resolves) and keep the result in React state / a context.
Do not persist entitlement state to local storage and trust it later — subscription state can change server-side (cancellations, billing issues). Always confirm against the server before granting access to paid content.
Routes reference
| Method | Path | Description |
|---|---|---|
GET | /client/entitlements | List the current user's entitlements (active). |
POST | /admin/projects/:projectId/users/:userId/entitlements | Server-side grant / refresh. Universal path — works for any subscription source. |
POST | /webhooks/revenuecat | Optional. Accepts RevenueCat subscription events. |
POST | /webhooks/superwall | Optional. Accepts Superwall paywall events. |