Entitlements
Define and manage feature access with entitlements
Entitlements
Entitlements define what limits and features each plan includes. They're the bridge between your pricing and your application's access control.
What Are Entitlements?
Entitlements answer: "What can this customer do?"
- How many projects can they create?
- What's their API rate limit?
- Do they have access to SSO?
- Is audit logging enabled?
Defining Entitlements
Define entitlements at the top level, then reference them in plans:
entitlements:
projects:
type: int
unit: project
description: Number of active projects
api_requests:
type: rate
unit: request
description: API rate limit
sso:
type: bool
description: Single sign-on support
plans:
- id: pro
limits:
projects: 25
api_requests: { limit: 1000, per: minute }
sso: falseEntitlement Properties
| Property | Type | Required | Description |
|---|---|---|---|
type | enum | Yes | int, bool, or rate |
unit | string | No | Unit name for display |
description | string | No | Human-readable description |
Entitlement Types
Integer (int)
For countable limits:
entitlements:
projects:
type: int
unit: project
team_members:
type: int
unit: seat
# In plans
limits:
projects: 25
team_members: 10
# or
projects: unlimitedValues:
- Any positive integer:
25 unlimited: No limit
Boolean (bool)
For feature flags:
entitlements:
sso:
type: bool
description: Single sign-on support
audit_logs:
type: bool
description: Audit log retention
# In plans
limits:
sso: true
audit_logs: falseValues: true or false
Rate (rate)
For time-based limits:
entitlements:
api_requests:
type: rate
unit: request
# In plans
limits:
api_requests: { limit: 1000, per: minute }Rate object:
limit: Number of requests allowedper: Time period (second,minute,hour,day)
Using Entitlements in Plans
entitlements:
projects:
type: int
unit: project
team_members:
type: int
unit: seat
api_requests:
type: rate
unit: request
sso:
type: bool
audit_logs:
type: bool
plans:
- id: free
name: Free
limits:
projects: 3
team_members: 1
api_requests: { limit: 100, per: minute }
sso: false
audit_logs: false
- id: pro
name: Pro
limits:
projects: 25
team_members: 25
api_requests: { limit: 1000, per: minute }
sso: false
audit_logs: true
- id: enterprise
name: Enterprise
limits:
projects: unlimited
team_members: unlimited
api_requests: { limit: 50000, per: minute }
sso: true
audit_logs: trueSpecial Values
Unlimited
Remove the limit entirely:
limits:
projects: unlimited
team_members: unlimitedZero
Explicitly set to zero (different from not defined):
limits:
extra_storage: 0Entitlements in Addons
Addons can modify entitlement values:
addons:
- id: extra_projects
name: Extra Projects Pack
price: { amount: 1000 }
grants:
projects: "+10" # Add 10 to existing limit
- id: unlimited_projects
name: Unlimited Projects
price: { amount: 5000 }
grants:
projects: unlimited # Set to unlimited
- id: sso_addon
name: SSO Add-on
price: { amount: 2000 }
grants:
sso: true # Enable featureGrant Syntax
| Syntax | Meaning |
|---|---|
"+10" | Add 10 to existing limit |
"-5" | Subtract 5 from existing limit |
25 | Set to exactly 25 |
true | Enable boolean feature |
unlimited | Remove limit entirely |
Best Practices
1. Use Descriptive Names
# Good
entitlements:
max_team_members:
type: int
unit: member
description: Maximum team members per workspace
# Avoid
entitlements:
mtm:
type: int2. Document Everything
entitlements:
api_requests:
type: rate
unit: request
description: API rate limit per minute for REST endpoints3. Plan for Growth
Add entitlements before you need them:
entitlements:
# Current features
projects:
type: int
unit: project
# Future features (set to false for now)
ai_features:
type: bool
description: AI-powered features (coming soon)4. Be Consistent
Use the same naming convention throughout:
# Consistent snake_case
entitlements:
team_members:
type: int
api_requests:
type: rate
audit_logs:
type: boolChecking Entitlements in Code
Your backend reads the billing config and checks limits:
// Example: Check if user can create another project
function canCreateProject(userPlan: string, currentCount: number): boolean {
const plan = billingConfig.plans.find(p => p.id === userPlan);
const limit = plan?.limits?.projects;
if (limit === 'unlimited') return true;
if (typeof limit === 'number') return currentCount < limit;
return false;
}
// Example: Check rate limit
function isWithinRateLimit(
userPlan: string,
requestsInWindow: number
): boolean {
const plan = billingConfig.plans.find(p => p.id === userPlan);
const rateLimit = plan?.limits?.api_requests;
if (!rateLimit) return true;
return requestsInWindow < rateLimit.limit;
}Complete Example
version: 1
entitlements:
# Numeric limits
projects:
type: int
unit: project
description: Number of active projects
team_members:
type: int
unit: seat
description: Team members per workspace
storage_gb:
type: int
unit: GB
description: Cloud storage allocation
# Rate limits
api_requests:
type: rate
unit: request
description: API rate limit
# Feature flags
sso:
type: bool
description: Single sign-on (SAML/OIDC)
audit_logs:
type: bool
description: Audit log retention
custom_domains:
type: bool
description: Custom domain support
priority_support:
type: bool
description: Priority support access
plans:
- id: free
name: Free
limits:
projects: 3
team_members: 1
storage_gb: 1
api_requests: { limit: 100, per: minute }
sso: false
audit_logs: false
custom_domains: false
priority_support: false
- id: pro
name: Pro
limits:
projects: 25
team_members: 25
storage_gb: 50
api_requests: { limit: 1000, per: minute }
sso: false
audit_logs: true
custom_domains: true
priority_support: true
- id: enterprise
name: Enterprise
limits:
projects: unlimited
team_members: unlimited
storage_gb: unlimited
api_requests: { limit: 50000, per: minute }
sso: true
audit_logs: true
custom_domains: true
priority_support: true