API Documentation
LicenseKit provides a simple REST API to implement software license verification in any language or platform.
Quick Start
Integrate LicenseKit in three steps:
1. Register and get your API Key
Sign up at Dashboard, create a project, then generate your API key from the top-right corner.
2. Create a license
Create licenses manually in the Dashboard under Licenses, or generate them in bulk via the API, then distribute them to your users.
3. Call the verify endpoint in your app
curl -X POST https://api.saaslic.com/api/license/verify \
-H "Content-Type: application/json" \
-d '{
"license_key": "LIC-XXXXXXXX-XXXX",
"project_code": "YOUR_PROJECT_CODE",
"device_id": "unique-device-identifier"
}'
Authentication
Endpoints that require login (create / delete / list) use Bearer Token authentication. Pass your token in the request header:
Authorization: Bearer YOUR_JWT_TOKEN
The verify endpoint (POST /api/license/verify) does not require authentication — call it directly from your client application.
Verify License
Verify a license key and bind the device if not already bound. No authentication required — safe to call from client apps.
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| license_key | string | ✓ | License key, format LIC-XXXXXXXX-XXXX |
| project_code | string | ✓ | Project code, found in Dashboard project settings |
| device_id | string | ✓ | Unique device identifier — use hardware fingerprint or UUID |
| device_name | string | - | Device name, e.g. "MacBook Pro" |
| platform | string | - | Platform, e.g. "macOS" / "Windows" |
Success Response
{
"ok": true,
"session_token": "eyJ...",
"license": {
"project_name": "MyApp",
"project_code": "MY_APP",
"license_key": "LIC-MMKFFCBQ-D37J",
"expire_at": null,
"max_devices": 1
}
}
Error Response
{
"ok": false,
"message": "License invalid"
}
Code Examples
curl -X POST https://api.saaslic.com/api/license/verify \
-H "Content-Type: application/json" \
-d '{
"license_key": "LIC-XXXXXXXX-XXXX",
"project_code": "MY_APP",
"device_id": "my-device-001"
}'
import requests
resp = requests.post(
"https://api.saaslic.com/api/license/verify",
json={
"license_key": "LIC-XXXXXXXX-XXXX",
"project_code": "MY_APP",
"device_id": "my-device-001",
}
)
data = resp.json()
if data["ok"]:
print("Verified:", data["license"]["project_name"])
else:
print("Failed:", data["message"])
const res = await fetch("https://api.saaslic.com/api/license/verify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
license_key: "LIC-XXXXXXXX-XXXX",
project_code: "MY_APP",
device_id: "my-device-001",
}),
});
const data = await res.json();
if (data.ok) {
console.log("Verified:", data.license.project_name);
} else {
console.log("Failed:", data.message);
}
Create License
Create a single license key. Requires Bearer Token authentication.
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| project_id | number | ✓ | Project ID |
| expire_at | string | - | Expiry date in YYYY-MM-DD format. Omit for lifetime license. |
| max_devices | number | - | Max devices allowed. Defaults to 1. |
| customer_email | string | - | If provided, sends the license key to this email automatically. |
Response
{
"ok": true,
"message": "License created successfully",
"license": {
"id": 10,
"license_key": "LIC-MMQ75CC5-JVQV",
"expire_at": null,
"max_devices": 1
}
}
List Licenses
Returns all licenses for the authenticated account. Supports filtering by project. Requires Bearer Token.
Query Parameters
| Field | Type | Description |
|---|---|---|
| project_id | number | Filter by project. Returns all if omitted. |
Delete License
Deletes a license and all its bound device records. Requires Bearer Token.
List Devices
Returns all bound devices for the authenticated account. Requires Bearer Token.
Query Parameters
| Field | Type | Description |
|---|---|---|
| license_id | number | Filter by license |
Unbind Device
Unbinds a device from its license. The device can then be rebound to another license. Requires Bearer Token.
Error Codes
| HTTP Status | message | Description |
|---|---|---|
| 400 | Missing required fields | Incomplete request parameters |
| 401 | Token invalid or expired | Bearer Token missing or expired |
| 400 | License invalid | License expired, disabled, or device limit reached |
| 404 | License not found | Incorrect license_key or project_code |
| 500 | Server error | Contact [email protected] |
Python SDK
Skip the HTTP boilerplate — verify licenses in one line with automatic device fingerprinting.
Install
pip install saaslic
📦 Source: github.com/why5353/saaslic-sdk
Usage
from saaslic import LicenseKit
lk = LicenseKit("YOUR_PROJECT_CODE")
# Full response
result = lk.verify("LIC-XXXXXXXX-XXXX")
if result["ok"]:
print("Verified:", result["license"]["project_name"])
else:
print("Failed:", result["message"])
# Simple check
if lk.check("LIC-XXXXXXXX-XXXX"):
print("License valid — launching app")
PyPI: pypi.org/project/saaslic
Node.js SDK
Zero dependencies — verify licenses in one line with automatic device fingerprinting.
Install
npm install saaslic
📦 Source: github.com/why5353/saaslic-sdk
Usage
const { LicenseKit } = require("saaslic");
const lk = new LicenseKit("YOUR_PROJECT_CODE");
// Full response
const result = await lk.verify("LIC-XXXXXXXX-XXXX");
if (result.ok) {
console.log("Verified:", result.license.project_name);
} else {
console.log("Failed:", result.message);
}
// Simple check
if (await lk.check("LIC-XXXXXXXX-XXXX")) {
console.log("License valid — launching app");
}
Full Integration Example
A complete example of verifying a license at startup in a Python desktop app:
import requests
import hashlib
import platform
import sys
def get_device_id():
raw = platform.node() + platform.processor()
return hashlib.md5(raw.encode()).hexdigest()
def verify_license(license_key: str) -> bool:
try:
resp = requests.post(
"https://api.saaslic.com/api/license/verify",
json={
"license_key": license_key,
"project_code": "MY_APP",
"device_id": get_device_id(),
"device_name": platform.node(),
"platform": platform.system(),
},
timeout=5
)
data = resp.json()
if data["ok"]:
print(f"License valid — welcome to {data['license']['project_name']}")
return True
else:
print(f"License invalid: {data['message']}")
return False
except Exception as e:
print(f"Network error: {e}")
return False
key = input("Enter your license key: ")
if not verify_license(key):
sys.exit(1)