infoOverview
The License Management System provides a simple REST API for verifying licenses in your applications. This guide covers how to integrate license checking into Python, JavaScript, and other applications.
license key
calls API
validates
& cache locally
apiAPI Endpoints
Base URL:
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/license/activate |
Activate license on a device |
| POST | /api/license/check |
Verify license status |
| POST | /api/license/deactivate |
Deactivate device |
checklistIntegration Steps
1Create a Product
Go to Products page and create your software product. Note down the Product Code (e.g., my-app).
2Generate License Keys
Go to Licenses page and create licenses for your product. Each license has a unique key like LIC-XXXX-XXXX-XXXX-XXXX.
3Integrate SDK / API
Add license verification to your application using our SDK or direct API calls.
codeCode Examples
Using Python SDK
Download license_client.py from the SDK folder and add to your project:
from license_client import LicenseClient
# Initialize client
client = LicenseClient(
server_url="",
product_code="my-app" # Your product code
)
def check_license():
"""Check license at app startup"""
# First check if already activated
if client.is_valid():
print("✅ License valid!")
return True
# Prompt user for license key
key = input("Enter your license key: ")
# Activate
result = client.activate(key, email="user@example.com")
if result["success"]:
print("✅ License activated!")
return True
else:
print(f"❌ Error: {result['message']}")
return False
# Use in your app
if __name__ == "__main__":
if check_license():
# Run your main application
run_app()
else:
print("Valid license required to continue.")
Offline Mode
The SDK caches license data locally and allows offline use for a configured number of days:
# License info is cached automatically
# App works offline until offline_valid_until expires
info = client.get_license_info()
print(f"License type: {info['license']['type']}")
print(f"Expires: {info['license']['expires_at']}")
print(f"Offline valid until: {info['offline_valid_until']}")
# Deactivate when user wants to switch devices
client.deactivate()
Using JavaScript (Browser/Node.js)
class LicenseClient {
constructor(serverUrl, productCode) {
this.serverUrl = serverUrl;
this.productCode = productCode;
this.cache = this.loadCache();
}
async activate(licenseKey, deviceId, email = null) {
const response = await fetch(`${this.serverUrl}/license/activate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
license_key: licenseKey,
product_code: this.productCode,
device_id: deviceId,
email: email,
os: navigator.platform,
app_version: '1.0.0'
})
});
const result = await response.json();
if (result.success) {
this.cache = result.data;
this.saveCache();
}
return result;
}
async check(licenseKey, deviceId) {
const response = await fetch(`${this.serverUrl}/license/check`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
license_key: licenseKey,
product_code: this.productCode,
device_id: deviceId
})
});
return response.json();
}
isValid() {
if (!this.cache) return false;
const offlineUntil = new Date(this.cache.offline_valid_until);
return offlineUntil > new Date();
}
loadCache() {
const data = localStorage.getItem(`license_${this.productCode}`);
return data ? JSON.parse(data) : null;
}
saveCache() {
localStorage.setItem(`license_${this.productCode}`, JSON.stringify(this.cache));
}
}
// Usage
const client = new LicenseClient('', 'my-app');
const deviceId = generateDeviceId(); // Implement based on your needs
const result = await client.activate('LIC-XXXX-XXXX-XXXX-XXXX', deviceId);
console.log(result);
Using C# (.NET)
using System.Net.Http;
using System.Text.Json;
public class LicenseClient
{
private readonly HttpClient _http;
private readonly string _serverUrl;
private readonly string _productCode;
public LicenseClient(string serverUrl, string productCode)
{
_http = new HttpClient();
_serverUrl = serverUrl;
_productCode = productCode;
}
public async Task<LicenseResult> ActivateAsync(string licenseKey, string deviceId)
{
var payload = new
{
license_key = licenseKey,
product_code = _productCode,
device_id = deviceId,
os = Environment.OSVersion.ToString(),
app_version = "1.0.0"
};
var response = await _http.PostAsJsonAsync(
$"{_serverUrl}/license/activate", payload);
var json = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<LicenseResult>(json);
}
public async Task<LicenseResult> CheckAsync(string licenseKey, string deviceId)
{
var payload = new
{
license_key = licenseKey,
product_code = _productCode,
device_id = deviceId
};
var response = await _http.PostAsJsonAsync(
$"{_serverUrl}/license/check", payload);
return await response.Content.ReadFromJsonAsync<LicenseResult>();
}
public string GenerateDeviceId()
{
// Combine hardware info for unique device ID
var info = $"{Environment.MachineName}_{Environment.ProcessorCount}";
using var sha = System.Security.Cryptography.SHA256.Create();
var hash = sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(info));
return BitConverter.ToString(hash).Replace("-", "").Substring(0, 32);
}
}
// Usage
var client = new LicenseClient("", "my-app");
var deviceId = client.GenerateDeviceId();
var result = await client.ActivateAsync("LIC-XXXX-XXXX-XXXX-XXXX", deviceId);
Using cURL (Direct API)
Activate License
curl -X POST /license/activate \
-H "Content-Type: application/json" \
-d '{
"license_key": "LIC-XXXX-XXXX-XXXX-XXXX",
"product_code": "my-app",
"device_id": "unique-device-hash",
"email": "user@example.com",
"os": "Windows 11",
"app_version": "1.0.0"
}'
Check License
curl -X POST /license/check \
-H "Content-Type: application/json" \
-d '{
"license_key": "LIC-XXXX-XXXX-XXXX-XXXX",
"product_code": "my-app",
"device_id": "unique-device-hash"
}'
Deactivate Device
curl -X POST /license/deactivate \
-H "Content-Type: application/json" \
-d '{
"license_key": "LIC-XXXX-XXXX-XXXX-XXXX",
"device_id": "unique-device-hash"
}'
data_objectAPI Response Format
Success Response
{
"success": true,
"message": "License activated successfully",
"data": {
"license": {
"key": "LIC-XXXX-XXXX-XXXX-XXXX",
"type": "full",
"status": "active",
"expires_at": null,
"max_devices": 2,
"active_devices": 1
},
"product": {
"name": "My App",
"code": "my-app"
},
"activation": {
"id": 1,
"device_id": "abc123...",
"activated_at": "2025-12-26 12:00:00",
"last_check_at": "2025-12-26 12:00:00"
},
"offline_valid_until": "2026-01-02 12:00:00"
}
}
Error Response
{
"success": false,
"message": "Maximum devices limit reached (2)"
}
Error Codes
| Code | Message | Action |
|---|---|---|
400 | Invalid license key | Check key format |
400 | License is suspended | Contact support |
400 | License has expired | Renew license |
400 | Maximum devices limit reached | Deactivate other device |
403 | Device not activated | Call /activate first |
404 | License not found | Verify license key |
lightbulbBest Practices
Device ID Generation
Create a unique, stable device ID by hashing hardware information:
- Machine name + MAC address
- CPU ID + Disk serial
- Avoid using values that change (IP address, temp files)
License Check Frequency
- Check at app startup
- Re-check every 24 hours if app runs continuously
- Allow offline use for configured period (default: 7 days)
- Show warning when offline grace period is ending
downloadDownload SDK
SDK files are located in your server's /sdk/ folder:
- Python:
/sdk/python/license_client.py
More SDKs coming soon: JavaScript, C#, PHP, Go