Entitlements
Entitlements define what users can do based on their plan. The SDK evaluates entitlements locally (in local_only mode) or via the RevTurbine API, and provides React hooks and imperative APIs for access control.
Entitlement Types
Section titled “Entitlement Types”| Type | Example | Check Pattern |
|---|---|---|
| Feature gate | brand_kit, data_export | Boolean — allowed or denied |
| Usage limit | api_calls, storage_gb | Numeric — current vs. limit |
| Credits | render_credits | Depleting balance |
| Seats | team_members | Per-account count limit |
| Capability tier | analytics_tier | Plan-level access (starter → pro → enterprise) |
Checking Entitlements
Section titled “Checking Entitlements”React Hook — useCan
Section titled “React Hook — useCan”The simplest reactive check. useCan(handle) returns { can, limited, result }. can is true while the user is entitled — including the limited (running-low) state — so gate on !can, never !allowed:
Full surface — useEntitlement
Section titled “Full surface — useEntitlement”For the complete reactive result (allowed / denied / limited / isLoading / error / gatedPlacement / recheck), use useEntitlement:
import { useEntitlement } from '@revturbine/sdk';
function ExportButton() { const { allowed, denied, isLoading } = useEntitlement({ handle: 'data_export', });
if (isLoading) return <button disabled>Loading…</button>; if (denied) return <button disabled>Upgrade to Export</button>;
return <button>Export Video</button>;}Declarative gate — <Gate>
Section titled “Declarative gate — <Gate>”<Gate> gates its children declaratively. can="handle" checks an entitlement (shorthand for check={{ entitlement: 'handle' }}); children render while entitled, and a configured upgrade placement — or deniedFallback — shows on denial. limitedFallback renders a soft “running low” state while access is still granted:
A <Gate> is also a placement. On denial the gate doesn’t render hardcoded UI — it resolves a placement from your monetization config and renders it in place of the children. So what a denied user sees — the upgrade modal or banner, its headline, offer, and CTA — is authored in the studio (or the CLI config), not baked into your app. Your PM, growth, or marketing team can rewrite the denial copy, swap the offer, or A/B-test it with no code deploy. surfaceTemplateIds scopes which surface templates can fill the gate; deniedFallback is the static backstop shown only when no placement is configured for it.
With Auto-Gate
Section titled “With Auto-Gate”When autoGate: true, the hook automatically resolves an upgrade placement if the entitlement is denied:
const { allowed, denied, gatedPlacement } = useEntitlement({ handle: 'data_export', autoGate: true, gatePlacementRequest: { slotId: 'export_gate', surfaceTemplateIds: ['modal_overlay'], },});
if (denied && gatedPlacement) { // Render gatedPlacement.content as an upgrade prompt}Imperative API
Section titled “Imperative API”const result = await sdk.can('data_export');
// result.status: 'allowed' | 'limited' | 'denied'// result.allowed: boolean// result.reason: string (optional)// result.current_tier: string (optional, for tier-based)// Usage numbers (used/limit/remaining) come from useUsageSnapshot — see "Reading Usage".Entitlement Result
Section titled “Entitlement Result”Every entitlement check returns an EntitlementResult:
interface EntitlementResult { status: 'allowed' | 'limited' | 'denied'; allowed: boolean; reason?: string; current_tier?: string;}// Usage numbers (used / limit / remaining) are NOT on the result —// read them from useUsageSnapshot() (see "Reading Usage" below).| Status | Meaning |
|---|---|
allowed | Full access — proceed normally |
limited | Access granted but approaching limit (e.g., 85% usage) |
denied | No access — show upgrade prompt or block |
Usage Tracking
Section titled “Usage Tracking”Report usage to keep entitlement checks accurate:
// Update current balancessdk.update({ api_calls: 950, storage_gb: 45, team_members: 5,});update() triggers:
- Re-evaluation of usage-based entitlements
- Segment re-evaluation (targeting rules may change)
- Decision cache invalidation
- Local runtime state persistence
Reading Usage
Section titled “Reading Usage”import { useUsageSnapshot } from '@revturbine/sdk';
function UsagePanel() { const { usage, refresh } = useUsageSnapshot();
return ( <ul> {Object.entries(usage).map(([handle, data]) => ( <li key={handle}> {handle}: {data.current} / {data.limit ?? '∞'} </li> ))} </ul> );}Patterns by Entitlement Type
Section titled “Patterns by Entitlement Type”Feature Gate
Section titled “Feature Gate”const { allowed } = useEntitlement({ handle: 'brand_kit' });// allowed: true/falseUsage Limit
Section titled “Usage Limit”const { allowed, limited } = useEntitlement({ handle: 'api_calls' });// limited: true when usage > 80%// used / limit: read from useUsageSnapshot() (see "Reading Usage")Credits
Section titled “Credits”const { limited, result } = useEntitlement({ handle: 'render_credits' });// result.status / result.allowed reflect access as credits run low// remaining balance: read from useUsageSnapshot() (see "Reading Usage")const { denied, result } = useEntitlement({ handle: 'team_members' });if (denied) { // seat counts: read from useUsageSnapshot() (see "Reading Usage") // Show "seat limit reached" prompt}Capability Tier
Section titled “Capability Tier”const { denied, result } = useEntitlement({ handle: 'advanced_analytics' });if (denied) { // result.current_tier: 'professional' // Show "upgrade to Professional" prompt}Fail-Open Semantics
Section titled “Fail-Open Semantics”The SDK uses fail-open behavior — if the entitlement service is unreachable, can returns allowed: true with reason 'entitlement_service_unavailable'. This ensures your app’s baseline UX is never blocked by RevTurbine downtime.
// If API is down:// { status: 'allowed', allowed: true, reason: 'entitlement_service_unavailable' }Next Steps
Section titled “Next Steps”- Placements Guide — render upgrade prompts for denied entitlements
- Events & Analytics — track entitlement check outcomes
- Error Handling — fail-open behavior and recovery patterns
- Try it live → Data Export Gate