Skip to content

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.

| 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) |

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>;
}

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
}
const result = await sdk.checkEntitlement('data_export');
// result.status: 'allowed' | 'limited' | 'denied'
// result.allowed: boolean
// result.reason: string (optional)
// result.used: number (for usage-based)
// result.limit: number (for usage-based)
// result.remaining: number (for usage-based)
// result.tier: string (for tier-based)

Every entitlement check returns an EntitlementResult:

interface EntitlementResult {
status: 'allowed' | 'limited' | 'denied';
allowed: boolean;
reason?: string;
used?: number;
limit?: number;
remaining?: number;
tier?: string;
}

| 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 |

Report usage to keep entitlement checks accurate:

// Update current balances
sdk.updateUsage({
api_calls: 950,
storage_gb: 45,
team_members: 5,
});

updateUsage() triggers:

  • Re-evaluation of usage-based entitlements
  • Segment re-evaluation (targeting rules may change)
  • Decision cache invalidation
  • Local runtime state persistence
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>
);
}
const { allowed } = useEntitlement({ handle: 'brand_kit' });
// allowed: true/false
const { allowed, limited, result } = useEntitlement({ handle: 'api_calls' });
// limited: true when usage > 80%
// result.used: 8500, result.limit: 10000
const { result } = useEntitlement({ handle: 'render_credits' });
// result.used: 850
// result.limit: 1000
// result.remaining: 150
const { denied, result } = useEntitlement({ handle: 'team_members' });
if (denied) {
// result.used: 10
// result.limit: 10
// Show "seat limit reached" prompt
}
const { denied, result } = useEntitlement({ handle: 'advanced_analytics' });
if (denied) {
// result.tier: 'professional'
// Show "upgrade to Professional" prompt
}

The SDK uses fail-open behavior — if the entitlement service is unreachable, checkEntitlement 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' }