Skip to main content

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

ParameterTypeRequiredDescription
license_idstringLicense ID (JTI) to revoke
reasonstringRevocation reason code
effective_untildatetimeTemporary suspension end date (null = permanent)

Reason Codes

ReasonDescription
unspecifiedNo specific reason
violationTerms of service violation
fraudFraudulent activity detected
chargebackPayment chargeback
expired_subscriptionSubscription not renewed
key_compromiseLicense key was compromised
administrativeAdministrative 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

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

  1. Each validation stores the current epoch securely
  2. If a license claims an epoch lower than stored, validation fails
  3. 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"
}