Integration Overview
This guide walks you through integrating the License Server API into your application. We'll cover common patterns, best practices, and complete implementation examples.
Integration Patterns
1. Basic License Verification
The simplest integration: verify a license key before allowing access to your application.
Use case: Simple license validation at application startup.
2. License Activation Pattern
More robust pattern that tracks which instances are using a license.
Use case: Desktop applications, server software that needs activation tracking.
3. Usage Tracking Pattern
Complete integration with usage monitoring and reporting.
Use case: SaaS applications, usage-based licensing, compliance monitoring.
Quick Start Examples
JavaScript/Node.js
javascript
const axios = require('axios');
class LicenseManager {
constructor(apiBaseUrl) {
this.apiBaseUrl = apiBaseUrl;
this.licenseKey = null;
this.instanceId = this.generateInstanceId();
}
// Basic license verification
async verifyLicense(key) {
try {
const response = await axios.post(`${this.apiBaseUrl}/verify-license`, {
key: key
});
if (response.data.valid) {
this.licenseKey = key;
return {
valid: true,
limits: response.data.limits,
tier: response.data.tier,
expiresAt: response.data.expires_at
};
}
return { valid: false, error: response.data.error };
} catch (error) {
console.error('License verification failed:', error.message);
return { valid: false, error: 'Network error' };
}
}
// License activation for this instance
async activateLicense(key) {
try {
const response = await axios.post(`${this.apiBaseUrl}/activate-license`, {
key: key,
instance_id: this.instanceId
});
if (response.data.activated) {
this.licenseKey = key;
return {
activated: true,
alreadyActivated: response.data.alreadyActivated
};
}
return { activated: false, error: 'Activation failed' };
} catch (error) {
if (error.response?.status === 403) {
return {
activated: false,
error: error.response.data.error || 'License invalid or expired'
};
}
return { activated: false, error: 'Network error' };
}
}
// Periodic validation check
async validateLicense() {
if (!this.licenseKey) return { valid: false };
try {
const response = await axios.post(`${this.apiBaseUrl}/validate-license`, {
key: this.licenseKey,
instance_id: this.instanceId
});
return { valid: response.data.valid };
} catch (error) {
return { valid: false };
}
}
// Report usage metrics
async trackUsage(usageData) {
if (!this.licenseKey) return false;
try {
const response = await axios.post(`${this.apiBaseUrl}/track-usage`, {
key: this.licenseKey,
usage: usageData
});
return response.data.tracked;
} catch (error) {
console.error('Usage tracking failed:', error.message);
return false;
}
}
generateInstanceId() {
const os = require('os');
return `${os.hostname()}-${process.pid}-${Date.now()}`;
}
}
// Usage
const licenseManager = new LicenseManager('https://your-license-api.com/v1');
async function initializeApp() {
const licenseKey = process.env.LICENSE_KEY || getUserLicenseKey();
// Verify license
const verification = await licenseManager.verifyLicense(licenseKey);
if (!verification.valid) {
console.error('Invalid license:', verification.error);
process.exit(1);
}
// Activate license for this instance
const activation = await licenseManager.activateLicense(licenseKey);
if (!activation.activated) {
console.error('License activation failed:', activation.error);
process.exit(1);
}
console.log('License activated successfully!');
console.log('License tier:', verification.tier);
console.log('License limits:', verification.limits);
// Start periodic validation
setInterval(async () => {
const validation = await licenseManager.validateLicense();
if (!validation.valid) {
console.error('License validation failed - shutting down');
process.exit(1);
}
}, 60000); // Check every minute
// Track usage periodically
setInterval(async () => {
await licenseManager.trackUsage({
active_users: getCurrentUserCount(),
api_calls: getAPICallCount(),
storage_gb: getStorageUsage()
});
}, 300000); // Report every 5 minutes
}
initializeApp();Python
python
import requests
import time
import threading
import uuid
import platform
from typing import Dict, Any, Optional
class LicenseManager:
def __init__(self, api_base_url: str):
self.api_base_url = api_base_url
self.license_key: Optional[str] = None
self.instance_id = self.generate_instance_id()
self.validation_thread: Optional[threading.Thread] = None
self.usage_thread: Optional[threading.Thread] = None
self.is_running = False
def verify_license(self, key: str) -> Dict[str, Any]:
"""Verify license key validity."""
try:
response = requests.post(
f'{self.api_base_url}/verify-license',
json={'key': key},
timeout=30
)
if response.status_code == 200:
data = response.json()
if data.get('valid'):
self.license_key = key
return {
'valid': True,
'limits': data.get('limits', {}),
'tier': data.get('tier'),
'expires_at': data.get('expires_at')
}
return {
'valid': False,
'error': response.json().get('error', 'Unknown error')
}
except requests.RequestException as e:
return {'valid': False, 'error': f'Network error: {str(e)}'}
def activate_license(self, key: str) -> Dict[str, Any]:
"""Activate license for this instance."""
try:
response = requests.post(
f'{self.api_base_url}/activate-license',
json={
'key': key,
'instance_id': self.instance_id
},
timeout=30
)
if response.status_code == 200:
data = response.json()
if data.get('activated'):
self.license_key = key
return {
'activated': True,
'already_activated': data.get('alreadyActivated', False)
}
error_msg = 'Activation failed'
if response.status_code == 403:
error_msg = response.json().get('error', 'License invalid or expired')
return {'activated': False, 'error': error_msg}
except requests.RequestException as e:
return {'activated': False, 'error': f'Network error: {str(e)}'}
def validate_license(self) -> bool:
"""Check if license is still valid."""
if not self.license_key:
return False
try:
response = requests.post(
f'{self.api_base_url}/validate-license',
json={
'key': self.license_key,
'instance_id': self.instance_id
},
timeout=30
)
return response.status_code == 200 and response.json().get('valid', False)
except requests.RequestException:
return False
def track_usage(self, usage_data: Dict[str, Any]) -> bool:
"""Report usage metrics."""
if not self.license_key:
return False
try:
response = requests.post(
f'{self.api_base_url}/track-usage',
json={
'key': self.license_key,
'usage': usage_data
},
timeout=30
)
return response.status_code == 200 and response.json().get('tracked', False)
except requests.RequestException as e:
print(f'Usage tracking failed: {e}')
return False
def start_background_tasks(self):
"""Start background validation and usage tracking."""
self.is_running = True
# Start validation thread
self.validation_thread = threading.Thread(target=self._validation_loop)
self.validation_thread.daemon = True
self.validation_thread.start()
# Start usage tracking thread
self.usage_thread = threading.Thread(target=self._usage_tracking_loop)
self.usage_thread.daemon = True
self.usage_thread.start()
def stop_background_tasks(self):
"""Stop background tasks."""
self.is_running = False
def _validation_loop(self):
"""Background license validation."""
while self.is_running:
try:
if not self.validate_license():
print('License validation failed - application should shut down')
# You might want to call a shutdown handler here
break
time.sleep(60) # Check every minute
except Exception as e:
print(f'Validation loop error: {e}')
time.sleep(60)
def _usage_tracking_loop(self):
"""Background usage tracking."""
while self.is_running:
try:
# You would implement these functions based on your app
usage_data = {
'active_users': self.get_active_user_count(),
'api_calls': self.get_api_call_count(),
'storage_gb': self.get_storage_usage()
}
self.track_usage(usage_data)
time.sleep(300) # Report every 5 minutes
except Exception as e:
print(f'Usage tracking loop error: {e}')
time.sleep(300)
def generate_instance_id(self) -> str:
"""Generate unique instance identifier."""
hostname = platform.node()
return f'{hostname}-{uuid.uuid4().hex[:8]}'
# Placeholder methods - implement based on your application
def get_active_user_count(self) -> int:
return 0
def get_api_call_count(self) -> int:
return 0
def get_storage_usage(self) -> float:
return 0.0
# Usage
def initialize_app():
license_manager = LicenseManager('https://your-license-api.com/v1')
# Get license key (from environment, config file, user input, etc.)
license_key = input('Enter your license key: ')
# Verify license
print('Verifying license...')
verification = license_manager.verify_license(license_key)
if not verification['valid']:
print(f'Invalid license: {verification["error"]}')
return False
# Activate license
print('Activating license...')
activation = license_manager.activate_license(license_key)
if not activation['activated']:
print(f'License activation failed: {activation["error"]}')
return False
print('License activated successfully!')
print(f'License tier: {verification["tier"]}')
print(f'License limits: {verification["limits"]}')
# Start background tasks
license_manager.start_background_tasks()
return True
if __name__ == '__main__':
if initialize_app():
print('Application started with valid license')
try:
# Your application logic here
while True:
time.sleep(1)
except KeyboardInterrupt:
print('Shutting down...')
else:
print('Failed to start application - invalid license')Integration Checklist
Basic Implementation
- [ ] License key verification on startup
- [ ] Handle network errors gracefully
- [ ] Display meaningful error messages to users
- [ ] Respect rate limits (implement backoff/retry)
Robust Implementation
- [ ] License activation tracking
- [ ] Periodic validation checks
- [ ] Graceful shutdown on license revocation
- [ ] Cache license verification results
- [ ] Implement exponential backoff for retries
Production Ready
- [ ] Usage tracking and reporting
- [ ] Comprehensive error handling
- [ ] Logging and monitoring integration
- [ ] License file support (if needed)
- [ ] Offline license validation (cached)
- [ ] Security best practices (secure key storage)
Common Integration Patterns
Desktop Applications
- License key entry dialog
- Activation during installation/first run
- Periodic validation (hourly/daily)
- Grace period for network issues
- License file import/export
Web Applications
- License verification on server startup
- Per-user license limits enforcement
- Usage tracking integration
- Admin dashboard for license management
Server Software
- License validation during installation
- Instance-based activation tracking
- High-availability license validation
- Usage reporting for compliance
SaaS Applications
- User registration with license key
- Feature gating based on license tier
- Real-time usage monitoring
- Automated license provisioning
Next Steps
Now that you understand the basic patterns, dive into specific implementation guides:
- License Verification - Detailed verification patterns
- License Activation - Activation and instance tracking
- Usage Tracking - Monitoring and reporting
- Client Examples - Language-specific implementations