Status Proof
Get cryptographic proofs for offline license validation.
Overviewβ
A StatusProof is a signed statement about a license's status at a specific point in time. It allows offline validation without contacting the server.
Use Casesβ
- Desktop applications without constant internet
- Air-gapped systems
- Edge devices with intermittent connectivity
- Reducing API calls for cost optimization
Get Status Proofβ
Endpointβ
POST /api/v1/v2/status-proof
Requestβ
{
"license_id": "b28a923a-c747-49b2-bc90-d87004c10379",
"device_fingerprint": {
"cpu_id": "Intel-Core-i9-12900K",
"disk_serial": "WD-ABC123456"
},
"ttl_hours": 48
}
Parametersβ
| Parameter | Type | Required | Description |
|---|---|---|---|
license_id | string | β | License ID to get proof for |
device_fingerprint | object | β | Device properties to bind proof |
ttl_hours | integer | β | Proof validity in hours (1-168, default: 24) |
Responseβ
Success (200 OK)β
{
"proof": {
"license_id": "b28a923a-c747-49b2-bc90-d87004c10379",
"status": "valid",
"checked_at": "2025-12-30T15:30:00Z",
"valid_until": "2026-01-01T15:30:00Z",
"revocation_epoch": 42,
"binding_hash": "sha256:9f86d081884c7d659a2feaa0c55ad015...",
"entitlements": ["feature:api", "feature:export", "seats:max"],
"issuer_kid": "ql-api-v2",
"signature": "base64-encoded-signature..."
},
"compact": "eyJsaWNlbnNlX2lkIjogImIyOGE5...",
"valid_until": "2026-01-01T15:30:00Z"
}
Proof Fieldsβ
| Field | Type | Description |
|---|---|---|
license_id | string | License ID the proof is for |
status | string | License status at time of check |
checked_at | datetime | When the proof was issued |
valid_until | datetime | When the proof expires |
revocation_epoch | integer | Revocation epoch at time of check |
binding_hash | string | Hash of device fingerprint (if provided) |
entitlements | array | Active entitlements at time of check |
issuer_kid | string | Key ID used to sign the proof |
signature | string | Cryptographic signature |
Status Valuesβ
| Status | Description |
|---|---|
valid | License is active |
revoked | License has been revoked |
expired | License has expired |
grace_period | License is in grace period |
Examplesβ
Get Basic Proofβ
curl -X POST "https://quantumlock.softquantus.com/api/v1/v2/status-proof" \
-H "Authorization: Bearer ql_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"license_id": "b28a923a-c747-49b2-bc90-d87004c10379",
"ttl_hours": 24
}'
Get Device-Bound Proofβ
curl -X POST "https://quantumlock.softquantus.com/api/v1/v2/status-proof" \
-H "Authorization: Bearer ql_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"license_id": "b28a923a-c747-49b2-bc90-d87004c10379",
"device_fingerprint": {
"cpu_id": "Intel-Core-i9-12900K",
"motherboard_serial": "MS-12345",
"disk_serial": "WD-ABC123456"
},
"ttl_hours": 72
}'
Python SDKβ
from quantumlock_sdk import QuantumLockClient
import json
client = QuantumLockClient(api_key="ql_your_api_key")
# Get a proof valid for 48 hours
proof = client.get_status_proof(
license_id="b28a923a-c747-49b2-bc90-d87004c10379",
device_fingerprint={
"cpu_id": get_cpu_id(),
"disk_serial": get_disk_serial()
},
ttl_hours=48
)
# Store for offline use
with open("proof_cache.json", "w") as f:
json.dump({
"proof": proof.to_dict(),
"compact": proof.compact,
"valid_until": proof.valid_until.isoformat()
}, f)
print(f"Proof valid until: {proof.valid_until}")
Offline Validationβ
Use cached proofs to validate licenses offline:
Python SDKβ
from quantumlock_sdk import OfflineValidator, StatusProof
import json
from datetime import datetime
# Load cached data
with open("proof_cache.json", "r") as f:
cache = json.load(f)
with open("license.qlf", "r") as f:
license_data = json.load(f)
# Create validator with cached public keys
validator = OfflineValidator(public_keys=cached_public_keys)
# Parse proof
proof = StatusProof.from_dict(cache["proof"])
# Validate
result = validator.validate_offline(
artifact=license_data,
proof=proof,
device_fingerprint={
"cpu_id": get_cpu_id(),
"disk_serial": get_disk_serial()
}
)
if result.is_valid:
print("β
License valid (offline validation)")
print(f" Status: {result.status}")
print(f" Proof expires: {proof.valid_until}")
else:
print(f"β Validation failed: {result.error}")
Validation Flowβ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β OFFLINE VALIDATION β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β 1. Load cached proof and license β
β β β
β 2. Check proof expiration β
β β β
β 3. Verify proof signature β
β β β
β 4. Check license ID matches proof β
β β β
β 5. Verify device fingerprint (if bound) β
β β β
β 6. Check revocation epoch β
β β β
β 7. Return validation result β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Best Practicesβ
1. Refresh Proofs Before Expirationβ
from datetime import datetime, timedelta
def should_refresh_proof(proof):
"""Refresh when 75% of TTL has passed."""
total_ttl = proof.valid_until - proof.checked_at
threshold = proof.checked_at + (total_ttl * 0.75)
return datetime.utcnow() > threshold
if should_refresh_proof(cached_proof):
try:
new_proof = client.get_status_proof(license_id)
save_proof(new_proof)
except NetworkError:
# Continue with existing proof
pass
2. Bind Proofs to Devicesβ
Device binding prevents proof reuse on different machines:
proof = client.get_status_proof(
license_id=license_id,
device_fingerprint=get_device_fingerprint()
)
3. Cache Multiple Proof Durationsβ
For applications with varying connectivity:
# Short-lived proof for online scenarios
short_proof = client.get_status_proof(license_id, ttl_hours=1)
# Long-lived proof for offline scenarios
long_proof = client.get_status_proof(license_id, ttl_hours=168)
Error Responsesβ
404 Not Foundβ
{
"detail": "License not found: b28a923a-c747-49b2-bc90-d87004c10379"
}
400 Bad Requestβ
{
"detail": "ttl_hours must be between 1 and 168"
}
Security Considerationsβ
- Proof Expiration: Short TTLs are more secure but require more frequent renewals
- Device Binding: Prevents proof reuse but requires consistent fingerprinting
- Revocation Epoch: Always verify the epoch hasn't been rolled back
- Signature Verification: Always verify the proof signature before trusting it