How to Add License Key Validation to Your Software in 10 Minutes
Stop building from scratch. Use a REST API to validate license keys in any language — JavaScript, PHP, Python. Ships in under 10 minutes.
Every developer building paid software hits the same wall: how do I actually enforce who can use my app?
You could build a license key system from scratch — database, key generation, validation logic, expiry handling, IP tracking. That's weeks of work on infrastructure that's not your product. Or you can use a validation API and ship in 10 minutes.
This guide uses KeyPort. The approach works for any language.
Why License Validation Matters
Without enforcement, anyone who copies your software binary can use it. Even well-meaning users share keys. License validation closes that gap: your app checks in with the API on startup, the API confirms whether the key is valid, and your app acts accordingly.
The validation happens server-side, so there's nothing to crack locally.
Step 1 — Create Your Product on KeyPort
Sign up at app.keyport.sbs (free, no credit card). Create an organization, then create a product. You'll get a product API key — keep it server-side, never expose it in client code.
# Your product API key (keep secret, server-side only)
KEYPORT_API_KEY=kp_live_xxxxxxxxxxxxxxxxxxxxStep 2 — Issue a License Key to a Customer
From the KeyPort dashboard, navigate to your product and click New license. Enter the customer email and set an expiry date if required. You'll get a license key in the format XXXX-XXXX-XXXX-XXXX. Give this to your customer at checkout.
Step 3 — Validate From Your Application
On every app startup (or periodically), make a POST request to the validate endpoint.
JavaScript / Node.js
const res = await fetch('https://api.keyport.sbs/api/v1/validate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.KEYPORT_API_KEY}`
},
body: JSON.stringify({ license_key: 'ABCD-EFGH-IJKL-MNOP' })
});
const data = await res.json();
if (data.valid) {
console.log('License valid. Status:', data.status);
} else {
console.log('License invalid. Reason:', data.status);
// data.status: expired | revoked | ip_blocked | not_found
}PHP
function validateLicense(string $key): array {
$ch = curl_init('https://api.keyport.sbs/api/v1/validate');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $_ENV['KEYPORT_API_KEY']
],
CURLOPT_POSTFIELDS => json_encode(['license_key' => $key])
]);
return json_decode(curl_exec($ch), true);
}
$result = validateLicense('ABCD-EFGH-IJKL-MNOP');
if ($result['valid']) { /* start app */ }
else { die('Invalid license: ' . $result['status']); }Python
import requests, os
def validate_license(key: str) -> dict:
return requests.post(
'https://api.keyport.sbs/api/v1/validate',
headers={
'Authorization': f"Bearer {os.environ['KEYPORT_API_KEY']}",
'Content-Type': 'application/json'
},
json={'license_key': key}
).json()
result = validate_license('ABCD-EFGH-IJKL-MNOP')
if not result['valid']:
print(f"Blocked. Reason: {result['status']}")
exit(1)Status Codes to Handle
| Status | Meaning | Recommended action |
|---|---|---|
active | License is valid | Allow full access |
expired | Past expiry date | Show renewal prompt |
revoked | Manually disabled | Show contact support |
ip_blocked | IP is blocked | Show contact support |
not_found | Key doesn't exist | Show invalid key error |
Next Steps
- Enable IP tracking to limit machines per key
- Add webhooks to get notified on events
- Share the customer portal link so users can view their own keys