License Revocation
Manage license revocation to immediately invalidate compromised or terminated licenses.
Overview
QuantumLock™ uses an epoch-based revocation system:
- Each revocation increments the global epoch counter
- Clients must have the current epoch to validate licenses
- Anti-rollback protection prevents using old revocation sets
Revoke a License
Endpoint
POST /api/v1/v2/revoke
Request
{
"license_id": "b28a923a-c747-49b2-bc90-d87004c10379",
"reason": "violation",
"effective_until": null
}
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
license_id | string | ✅ | License ID (JTI) to revoke |
reason | string | ❌ | Revocation reason code |
effective_until | datetime | ❌ | Temporary suspension end date (null = permanent) |
Reason Codes
| Reason | Description |
|---|---|
unspecified | No specific reason |
violation | Terms of service violation |
fraud | Fraudulent activity detected |
chargeback | Payment chargeback |
expired_subscription | Subscription not renewed |
key_compromise | License key was compromised |
administrative | Administrative action |
Response (200 OK)
{
"success": true,
"license_id": "b28a923a-c747-49b2-bc90-d87004c10379",
"epoch": 42,
"reason": "violation",
"revoked_at": "2025-12-30T15:30:00Z"
}
Un-revoke a License
Re-enable a previously revoked license.
Endpoint
DELETE /api/v1/v2/revoke/{license_id}
Example
curl -X DELETE "https://quantumlock.softquantus.com/api/v1/v2/revoke/b28a923a-c747-49b2-bc90-d87004c10379" \
-H "Authorization: Bearer ql_your_api_key"
Response (200 OK)
{
"success": true,
"license_id": "b28a923a-c747-49b2-bc90-d87004c10379",
"epoch": 43,
"message": "License restored"
}
Get Revocation Set
Get the current revocation set for synchronization.
Endpoint
GET /api/v1/v2/revocation
Query Parameters
| Parameter | Type | Description |
|---|---|---|
since_epoch | integer | Only return changes since this epoch (delta sync) |
Response (200 OK)
{
"epoch": 42,
"revoked_ids": [
"b28a923a-c747-49b2-bc90-d87004c10379",
"a1b2c3d4-e5f6-7890-abcd-ef1234567890"
],
"issued_at": "2025-12-30T15:30:00Z",
"valid_until": "2025-12-30T16:30:00Z",
"signature": "base64-encoded-signature..."
}
Delta Sync
To get only changes since a specific epoch:
curl "https://quantumlock.softquantus.com/api/v1/v2/revocation?since_epoch=40" \
-H "Authorization: Bearer ql_your_api_key"
Examples
Revoke for Violation
curl -X POST "https://quantumlock.softquantus.com/api/v1/v2/revoke" \
-H "Authorization: Bearer ql_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"license_id": "b28a923a-c747-49b2-bc90-d87004c10379",
"reason": "violation"
}'
Temporary Suspension
Suspend a license until a specific date:
curl -X POST "https://quantumlock.softquantus.com/api/v1/v2/revoke" \
-H "Authorization: Bearer ql_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"license_id": "b28a923a-c747-49b2-bc90-d87004c10379",
"reason": "administrative",
"effective_until": "2026-01-15T00:00:00Z"
}'
Python SDK
from quantumlock_sdk import QuantumLockClient
client = QuantumLockClient(api_key="ql_your_api_key")
# Revoke a license
result = client.revoke_license(
license_id="b28a923a-c747-49b2-bc90-d87004c10379",
reason="violation"
)
print(f"License revoked at epoch {result.epoch}")
# Check revocation status
revocation_set = client.get_revocation_set()
print(f"Current epoch: {revocation_set.epoch}")
print(f"Revoked licenses: {len(revocation_set.revoked_ids)}")
Anti-Rollback Protection
QuantumLock™ includes anti-rollback protection to prevent attackers from using old revocation sets:
How It Works
- Each validation stores the current epoch securely
- If a license claims an epoch lower than stored, validation fails
- Epoch state is stored in OS secure storage:
- macOS: Keychain
- Windows: DPAPI
- Linux: Secret Service / libsecret
Client Implementation
from quantumlock_sdk import AntiRollbackGuard
guard = AntiRollbackGuard(namespace="myapp")
# Check epoch during validation
current_epoch = get_revocation_epoch()
if not guard.verify_epoch(current_epoch):
raise SecurityError("Epoch rollback detected!")
# Update stored epoch after successful validation
guard.update_epoch(current_epoch)
Best Practices
1. Sync Revocation Sets Regularly
import schedule
def sync_revocation():
revocation = client.get_revocation_set(since_epoch=last_epoch)
update_local_cache(revocation)
# Sync every 5 minutes
schedule.every(5).minutes.do(sync_revocation)
2. Handle Network Failures
def validate_with_fallback(license_token):
try:
# Try online validation
return client.validate(artifact_compact=license_token)
except NetworkError:
# Fall back to cached revocation set
return validate_offline(license_token, cached_revocation_set)
3. Log Revocation Events
result = client.revoke_license(license_id, reason="violation")
audit_log.info(
"License revoked",
license_id=license_id,
reason="violation",
epoch=result.epoch,
operator=current_user
)
Error Responses
404 Not Found
{
"detail": "License not found: b28a923a-c747-49b2-bc90-d87004c10379"
}
409 Conflict
{
"detail": "License already revoked"
}