Entitlements
Entitlements are feature flags or capabilities tied to a license. They allow you to gate specific features, modules, or tiers within your software without creating separate products or licenses.
What are Entitlements?
Think of entitlements as fine-grained permissions attached to a license:
- A regular license might include
downloadsonly for 1 year - A "Pro" license might include entitlements for
advanced-export,cloud-sync, andpriority-support - A "Team" license might add
multi-userandadmin-panelentitlements - A trial might grant
full-accesswith a 14-day expiration
Each entitlement has:
- Key — A unique identifier (e.g.,
pro-features,api-access,beta-mode) - Expiration — Optional expiry date (perpetual if not set)
- Metadata — Optional custom data attached to the entitlement
Setting Up Entitlements
Entitlements are configured on License Plans in the LicenseSeat dashboard.
1. Create or Edit a License Plan
Go to your product → License Types → Edit a plan (or create a new one).
2. Add Entitlements
In the "Entitlements" section, add the feature keys you want to grant:
| Feature Slug | When does it expire? | Duration |
|---|---|---|
pro-features |
Never | — |
beta-access |
Expires after... | 90 days |
updates |
With the license | — |
3. Expiration Options
Each entitlement can have one of three expiration modes:
| Mode | Description |
|---|---|
| Never | Perpetual access — the entitlement never expires |
| With the license | Expires when the license expires |
| Expires after... | Fixed duration from license issuance (e.g., 1 year, 90 days) |
Note: Fixed-duration entitlements start counting from the license's
starts_atdate, not from the first activation.
4. Entitlement Keys
Keys must be lowercase alphanumeric with hyphens or underscores:
pro-featuresapi_accessbeta2024
Invalid: Pro Features, api access, PRO-FEATURES
Checking Entitlements in Your App
All LicenseSeat SDKs provide methods to check entitlements.
JavaScript
// Simple boolean check
if (sdk.hasEntitlement('pro-features')) {
enableProFeatures();
}
// Detailed check with expiration info
const result = sdk.checkEntitlement('beta-access');
if (result.active) {
console.log('Expires:', result.entitlement.expires_at);
} else {
console.log('Reason:', result.reason);
// 'no_license' | 'not_found' | 'expired'
}
Swift
// Simple check
let status = LicenseSeat.shared.checkEntitlement("pro-features")
if status.active {
enableProFeatures()
}
// SwiftUI property wrapper
@EntitlementState("pro-features") private var hasPro
var body: some View {
if hasPro {
ProFeaturesView()
}
}
// Reactive publisher
LicenseSeat.shared.entitlementPublisher(for: "beta-access")
.sink { status in
updateUI(for: status)
}
C#
// Simple boolean check
if (LicenseSeat.HasEntitlement("pro-features"))
{
EnableProFeatures();
}
// Detailed check
var status = LicenseSeat.Entitlement("beta-access");
if (status.Active)
{
Console.WriteLine($"Expires: {status.ExpiresAt}");
}
else
{
switch (status.Reason)
{
case EntitlementInactiveReason.Expired:
ShowRenewalPrompt();
break;
case EntitlementInactiveReason.NotFound:
ShowUpgradePrompt();
break;
}
}
C++
// Simple boolean check
if (client.has_entitlement("pro-features")) {
enable_pro_features();
}
// Detailed check with expiration and metadata
auto status = client.check_entitlement("beta-access");
if (status.active) {
std::cout << "Active until: " << status.expires_at.value_or(0) << "\n";
// Access metadata if needed
if (status.entitlement) {
for (const auto& [key, value] : status.entitlement->metadata) {
std::cout << key << ": " << value << "\n";
}
}
} else {
std::cout << "Inactive: " << status.reason << "\n";
// Reasons: "no_license", "not_found", "expired"
}
API Response
Entitlements are returned in all license validation responses:
{
"valid": true,
"license": {
"key": "XXXX-XXXX-XXXX-XXXX",
"status": "active",
"active_entitlements": [
{
"key": "pro-features",
"expires_at": null,
"metadata": {}
},
{
"key": "beta-access",
"expires_at": "2024-12-31T23:59:59Z",
"metadata": { "beta_version": "2.0" }
}
]
}
}
Offline Support
Entitlements are included in offline machine files, allowing you to check them without network access:
{
"license": {
"key": "XXXX-XXXX-XXXX-XXXX",
"entitlements": [
{ "key": "pro-features", "expires_at": null },
{ "key": "beta-access", "expires_at": "2024-12-31T23:59:59Z" }
]
}
}
For SDKs that already support machine files, entitlements are read from the cached machine file when the network is unavailable. Older SDKs may still use signed offline tokens as a legacy compatibility path.
Granting Entitlements to Individual Licenses
Beyond plan-level entitlements, you can grant additional entitlements to specific licenses:
- Go to the license detail page in the dashboard
- In the "Entitlements" section, click "Grant new entitlement"
- Enter the feature key and expiration
This is useful for:
- Granting beta access to specific customers
- Extending a feature for a loyal customer
- Adding promotional features
Best Practices
Use Descriptive Keys
✓ pro-export, cloud-sync, api-access
✗ feat1, pro, x
Check Entitlements, Not Plans
Instead of checking the plan name:
// ✗ Fragile - breaks if you rename plans
if (license.plan_key === 'pro') { ... }
Check for specific capabilities:
// ✓ Flexible - works regardless of plan structure
if (sdk.hasEntitlement('advanced-export')) { ... }
Handle Missing Entitlements Gracefully
const result = sdk.checkEntitlement('new-feature');
if (!result.active && result.reason === 'not_found') {
// Feature not in their plan - show upgrade prompt
showUpgradeModal();
}
Use Expiring Entitlements for Trials
Instead of separate trial licenses, use time-limited entitlements:
| Plan | Entitlement | Expiration |
|---|---|---|
| Trial | full-access |
14 days |
| Pro | full-access |
Never |
This way, trial users automatically lose access after 14 days without requiring license revocation.
Next Steps
- JavaScript SDK — Full entitlement API reference
- Swift SDK — SwiftUI integration with
@EntitlementState - C# SDK — Events and reactive patterns
- C++ SDK — Thread-safe entitlement checking