Skip to main content

License Models

Understanding the different types of licenses and how to use them.


Overview

QuantumLock™ supports flexible licensing models through the entitlement system. You can create any type of license by combining entitlements.


License Types

1. Subscription License

Time-limited license that requires periodic renewal.

# Create a 1-year subscription
artifact = client.create_license(
subject="customer:acme-corp",
valid_days=365,
grace_days=14,
entitlements=[
{"id": "tier:professional", "type": "tier", "value": "professional"},
{"id": "feature:all", "type": "feature", "value": True}
],
metadata={
"license_type": "subscription",
"renewal_url": "https://billing.example.com/renew"
}
)

Characteristics:

  • Fixed expiration date
  • Grace period for renewal
  • Typically includes all features for tier
  • Requires renewal workflow

2. Perpetual License

Never expires, but may have limited support/updates.

# Create perpetual license
# Using a far-future expiration (e.g., 100 years)
artifact = client.create_license(
subject="customer:acme-corp",
valid_days=36500, # ~100 years
grace_days=0,
entitlements=[
{"id": "tier:perpetual", "type": "tier", "value": "perpetual"},
{"id": "feature:core", "type": "feature", "value": True},
# Updates limited to 1 year
{
"id": "feature:updates",
"type": "feature",
"value": True,
"expires_at": "2026-12-30T00:00:00Z"
}
]
)

Characteristics:

  • Very long or no expiration
  • May have time-limited features (updates, support)
  • One-time purchase model

3. Trial License

Short-term license for evaluation.

# Create 14-day trial
artifact = client.create_license(
subject="trial:user@example.com",
valid_days=14,
grace_days=0, # No grace for trials
entitlements=[
{"id": "tier:trial", "type": "tier", "value": "trial"},
{"id": "feature:all", "type": "feature", "value": True},
{"id": "limit:watermark", "type": "feature", "value": True}
],
metadata={
"license_type": "trial",
"upgrade_url": "https://buy.example.com"
}
)

Characteristics:

  • Short duration (7-30 days)
  • Full or limited features
  • May include watermarks or limitations
  • No grace period

4. Seat-Based License

Limited to a number of concurrent users.

# Create 50-seat license
artifact = client.create_license(
subject="customer:acme-corp",
valid_days=365,
entitlements=[
{"id": "tier:team", "type": "tier", "value": "team"},
{"id": "seats:max", "type": "quantity", "value": 50},
{"id": "seats:concurrent", "type": "quantity", "value": 50}
]
)

Characteristics:

  • Quantity-based entitlements
  • Requires seat tracking in your application
  • May have concurrent vs. named user models

5. Usage-Based License

Limited by API calls, transactions, or other metrics.

# Create usage-based license
artifact = client.create_license(
subject="customer:acme-corp",
valid_days=365,
entitlements=[
{"id": "tier:usage", "type": "tier", "value": "usage"},
{"id": "quota:api_calls", "type": "quota", "value": 1000000},
{"id": "quota:storage_gb", "type": "quota", "value": 100}
]
)

Characteristics:

  • Quota-based entitlements
  • Requires usage tracking in your application
  • May reset monthly or be lifetime

6. Node-Locked License

Bound to specific hardware.

# Create node-locked license
artifact = client.create_license(
subject="device:server-prod-01",
valid_days=365,
binding={
"type": "hardware",
"value": "sha256:...",
"properties": ["cpu_id", "motherboard_serial", "disk_serial"]
},
entitlements=[
{"id": "tier:server", "type": "tier", "value": "server"},
{"id": "feature:all", "type": "feature", "value": True}
]
)

Characteristics:

  • Bound to hardware fingerprint
  • Cannot be moved to different machine
  • Requires device fingerprint during validation

7. Floating License

Pool of licenses that can be checked out.

# Create floating license pool
for i in range(10):
artifact = client.create_license(
subject=f"pool:acme-corp:seat-{i}",
valid_days=365,
entitlements=[
{"id": "tier:floating", "type": "tier", "value": "floating"},
{"id": "pool:id", "type": "metadata", "value": "acme-pool-1"}
]
)

Characteristics:

  • Multiple licenses in a pool
  • License server manages checkouts
  • Maximum concurrent users = pool size

Entitlement Types

feature

Boolean feature flag.

{"id": "feature:api", "type": "feature", "value": True}
{"id": "feature:export", "type": "feature", "value": True}
{"id": "feature:admin", "type": "feature", "value": False}

quantity

Numeric limit.

{"id": "seats:max", "type": "quantity", "value": 50}
{"id": "projects:limit", "type": "quantity", "value": 10}
{"id": "storage:mb", "type": "quantity", "value": 5000}

quota

Usage-based limit (may reset).

{"id": "api:requests_monthly", "type": "quota", "value": 100000}
{"id": "reports:monthly", "type": "quota", "value": 100}

tier

Feature tier or plan level.

{"id": "tier:plan", "type": "tier", "value": "enterprise"}

module

Optional product module.

{"id": "module:analytics", "type": "module", "value": True}
{"id": "module:reporting", "type": "module", "value": True}

Checking Entitlements

Python SDK

result = client.validate(artifact_compact=token)

if result.is_valid:
# Check feature
if "feature:api" in result.entitlements:
enable_api()

# Check tier
tier = get_entitlement_value(result, "tier:plan")
if tier == "enterprise":
enable_enterprise_features()

# Check quantity
max_seats = get_entitlement_value(result, "seats:max")
if current_users > max_seats:
show_upgrade_prompt()

Helper Function

def get_entitlement_value(validation_result, entitlement_id):
"""Get the value of a specific entitlement."""
for ent in validation_result.entitlements_full:
if ent["id"] == entitlement_id:
return ent["value"]
return None

def has_feature(validation_result, feature_id):
"""Check if a feature is enabled."""
return f"feature:{feature_id}" in validation_result.entitlements

Grace Periods

Grace periods allow continued access after expiration:

artifact = client.create_license(
subject="customer:acme-corp",
valid_days=365,
grace_days=14 # 14-day grace after expiration
)

During grace period:

  • is_valid = True
  • in_grace_period = True
  • Show renewal warnings to user
result = client.validate(artifact_compact=token)

if result.is_valid:
if result.in_grace_period:
days_left = calculate_grace_remaining(result)
show_warning(f"License expired! {days_left} days to renew.")

Best Practices

1. Use Meaningful Entitlement IDs

# Good
{"id": "feature:sso", ...}
{"id": "module:analytics", ...}
{"id": "seats:max", ...}

# Bad
{"id": "f1", ...}
{"id": "ent_001", ...}

2. Include Tier Information

# Always include a tier for easy checking
{"id": "tier:plan", "type": "tier", "value": "enterprise"}

3. Set Appropriate Grace Periods

License TypeRecommended Grace
Trial0 days
Monthly subscription3 days
Annual subscription14-30 days
Enterprise30-60 days

4. Track Renewals

# Store renewal metadata
metadata = {
"original_license": "previous-license-id",
"renewal_count": 3,
"customer_since": "2022-01-15"
}

Migration from Other Systems

From Simple Key Systems

# Old: Single license key
# New: Create artifact with same features

old_key = "XXXX-XXXX-XXXX-XXXX"
customer_data = lookup_old_key(old_key)

new_artifact = client.create_license(
subject=f"migrated:{customer_data['email']}",
valid_days=customer_data['days_remaining'],
entitlements=convert_features(customer_data['features']),
metadata={
"migrated_from": old_key,
"migration_date": datetime.now().isoformat()
}
)

From Other Licensing Systems

  1. Export customer/license data from old system
  2. Map feature names to QuantumLock entitlements
  3. Create artifacts with equivalent expiration
  4. Update validation code to use new SDK
  5. Provide migration path for existing users