One Platform to License, Protect & Monetize Your Software.
ScaleGate gives independent software vendors a complete white-labelled licensing engine. Issue keys, enforce device limits, accept payments and track revenue, all under your own brand.
License keys issued automatically on payment confirmation
Activate on desktop (WPF/WinForms) via .NET SDK
Activate web apps via domain fingerprinting
Manage registered devices and free slots remotely
Download app binaries with license pre-configured
Offline grace period (configurable days) during connectivity loss
View payment history and download PDF invoices
Everything a Software Vendor Needs
Built to cover the complete ISV lifecycle, from first app to enterprise scale, under your own brand.
🎨
White-Label Branding
Custom logo, colours, fonts, and CSS. Your customers never see ScaleGate. They see you.
🌐
Custom Domains + SSL
Point your own domain (e.g., licenses.yourbrand.com). ULS auto-provisions Let's Encrypt TLS with zero configuration.
💳
Secure Payments
Accept KES payments natively. Invoices generated as PDF. Revenue share disbursed automatically to your merchant account.
🔑
License Lifecycle Management
Issue, override, extend, and revoke keys in seconds. Bulk operations supported. Full status history per license.
🖥
Desktop SDK
Add the ScaleGate SDK to any Windows desktop app. Activate, validate, auto-update, and revoke in five lines of code.
🌍
Web License API
Six REST endpoints for web and SaaS apps. Domain fingerprinting, feature flags, server-to-server validation, and heartbeat checks.
🛡
Role-Based Access Control
16 granular permissions. Custom roles. MasterAdmin bypass. Every access decision is audited.
📊
Revenue Dashboard
Real-time MRR, active licenses, device counts, and customer activity, all in your white-labelled portal.
📱
Device Management
Enforce per-plan device limits. Customers manage their own devices. Admins can override remotely.
⚡
Feature Flags by Plan
Ship one codebase. Unlock features based on the customer's plan tier: SSO, API access, analytics, and more.
🔄
JWT Key Rotation
Rotate your tenant signing key on demand. All existing sessions are immediately invalidated.
📋
Audit Logs
20+ action types logged with IP address, user agent, actor identity, and full metadata. Compliance-ready.
💾
Offline & Air-Gapped Licensing
Sell to factories, labs, and secure sites with no internet. Ship a USB bundle. Collect a USB journal. Full enforcement, full audit trail, zero network required. Setup guide →
License the Machines That Never Touch the Internet
Factories, labs, military sites, hospitals, remote installations. Your software can now be sold into environments where the licensing server is physically unreachable — without dropping enforcement, audit, or revenue control.
💾
Step 1 · Export
Generate a USB bundle
Admin picks the license, device count, and validity window in the portal
A single file is produced — sealed, versioned, and unique to that customer
Optional: embed the latest application installer so the customer site gets updates too
One click. No certificate management. No key ceremony.
🔑
Step 2 · Install
Customer activates offline
Bundle is carried to the air-gapped site on a USB stick or secure courier
The app validates the bundle locally — no network calls, ever
Runs for the validity window set by the admin (days, weeks, months — your choice)
Every activation, validation, and renewal is recorded in a sealed local journal
📊
Step 3 · Reconcile
Return journal, full visibility
Periodically, the customer exports a signed return file and hands it back
Admin uploads it via the portal — same drag-and-drop you use for anything else
See exactly which devices activated, when, and whether anyone exceeded the limit
Any over-activation, expired use, or tampering attempt is flagged in red
🛡 Enforcement built into every bundle
Offline doesn't mean honour-system. The same protections you get from the online path are carried with the bundle itself.
🔒 Tamper-proof sealEvery bundle is cryptographically sealed by your platform. Change a single byte — the expiry, the device count, anything — and the app refuses to run. Customers can't forge their own bundles.
💻 Hardware bindingA 5-seat bundle runs on 5 specific machines. Activation #6 is rejected by the app itself, not by your server. Bundles can't be cloned across a datacentre.
🕓 Clock-rollback detectionSetting the system clock backwards to dodge expiry doesn't work. The app remembers the last time it saw and refuses to validate if time appears to move backwards.
⏱ Hard expiry windowEvery bundle has a baked-in end date. When the window closes, the app stops. No network retrieval can extend it — only a fresh bundle from you.
🔧 Travelling revocation listStolen or leaked keys are blocked by the bundle itself. Today's bundle knows about last week's compromises, and stale blocklists automatically demote the bundle to “needs refresh”.
🚨 Over-activation alertsThe return journal is cross-checked against the bundle's limits. Over-activation, future-dated events, and counter resets all surface in the portal — and in your audit log — the moment telemetry lands.
🔀 Signed return journalsThe telemetry file is signed by the device itself, not the customer. You can't edit it on the way back to hide over-use — the signature breaks and the portal refuses to import.
🔍 Full audit trailEvery bundle export, every reconcile upload, every over-activation event is written to the same audit log as the rest of your tenant — no separate silo, no blind spots for compliance.
Offline licensing is available on Professional and Enterprise plans and can be toggled per tenant. Existing online customers are unaffected.
Two SDKs. Every Platform.
Production-ready client libraries for desktop and web. Activate, validate, enforce, and auto-update with real API calls.
The ScaleGate Desktop SDK targets Windows desktop apps with hardware fingerprinting, offline caching, and self-update. The ScaleGate Web SDK covers browser apps and server-side backends with domain fingerprinting and server-to-server validation.
.NET📦dotnet add package ScaleGate.Licensing.SDK
npm📦npm i @scalegate/licensing-web-sdk
WPF Desktop Application
Windows DesktopNuGet
Install Licensing.SDK via NuGet. The builder pattern configures your API URL, offline cache, grace period, and auto-revalidation -then activates the device with a single async call. Hardware fingerprinting (CPU + motherboard + machine SID, SHA-256 hashed) is automatic.
Identical SDK, different UI framework. The LicenseClient is framework-agnostic -events marshal back to the UI thread using Invoke(). Activation, validation, revocation, and auto-update work identically to WPF.
Program.cs -Entry Point Guard
using Licensing.SDK;
static classProgram
{
internal staticLicenseClient? License;
[STAThread]
static asyncTaskMain()
{
ApplicationConfiguration.Initialize();
var key = Settings.Default.LicenseKey;
if (string.IsNullOrEmpty(key))
{
using var dlg = newActivationForm();
if (dlg.ShowDialog() != DialogResult.OK)
return;
key = dlg.LicenseKey;
}
License = awaitLicenseClient
.Create("my-winforms-app", key)
.WithApiUrl("https://acme.scalegate.io")
.WithOfflineValidation(true)
.WithGracePeriod(7)
.WithAutoRevalidation(true, 60)
.BuildAndActivateAsync();
if (!License.IsValid)
{
MessageBox.Show(
License.CurrentStatus.Message,
"License Error");
return;
}
Application.Run(newMainForm());
}
}
MainForm.cs -Status Bar & Deactivation
public partial classMainForm : Form
{
publicMainForm()
{
InitializeComponent();
var lic = Program.License!;
var s = lic.CurrentStatus!;
// Show license info in status strip
lblPlan.Text = $"Plan: {s.PlanName}";
lblDevices.Text =
$"Devices: {s.ActiveDevices}/{s.MaxDevices}";
lblExpiry.Text =
$"Expires: {s.ExpiryDate:MMM dd, yyyy}";
// Warn on grace period
lic.LicenseStatusChanged += (_, e) =>
{
Invoke(() =>
{
if (e.NewStatus == LicenseStatus.GracePeriod)
warningPanel.Visible = true;
if (e.NewStatus == LicenseStatus.Expired)
{
MessageBox.Show("License expired.");
Close();
}
});
};
}
// Deactivate on uninstall / sign-outprivate async voidbtnDeactivate_Click(
object s, EventArgs e)
{
var result = awaitProgram.License!
.RevokeAsync();
if (result.IsValid)
{
Program.License.Dispose();
Settings.Default.LicenseKey = "";
Settings.Default.Save();
Application.Restart();
}
}
}
WinForms.NET 8 / 9.NET Framework 4.6.1+Offline CacheDevice RevocationGrace Period
TypeScript / JavaScript
npmESM + CJS
Install @scalegate/licensing-web-sdk from npm. The client auto-detects browser vs. server mode, registers the domain or IP, and starts periodic validation with configurable callbacks for invalid/valid transitions.
Initialisation & Validation
import { LicenseClient } from'@scalegate/licensing-web-sdk';
// Create and initialise the clientconst client = newLicenseClient({
apiUrl: 'https://acme.scalegate.io',
licenseKey: 'XXXX-XXXX-XXXX-XXXX',
appId: 'my-saas-app',
mode: 'web', // 'web' = browser, 's2s' = server
validateInterval: 300000, // 5 min periodic check
onInvalid: (status) => {
console.error(`License invalid: ${status.message}`);
showPaywall();
},
onValid: (status) => {
console.log(`License OK -${status.daysRemaining}d left`);
},
});
// Register this domain and start validation loopconst status = await client.initialise();
if (status.isValid) {
console.log(`Plan: ${status.planName}`);
console.log(`Domains: ${status.activeDomains}/${status.maxDomains}`);
}
Feature Flags & Status
// Check which features the plan unlocksconst features = await client.checkFeatures(
['sso', 'api_access', 'analytics', 'white_label']
);
if (features.valid) {
console.log(`Plan: ${features.planName}`);
if (features.features.sso)
enableSSOLogin();
if (features.features.analytics)
loadAnalyticsDashboard();
}
// Full status with registered domainsconst detail = await client.getStatus();
console.log(detail.currentDomainRegistered);
console.log(detail.registeredDomains);
console.log(detail.featureFlags);
// Lightweight heartbeat (returns boolean)const alive = await client.heartbeat();
// Cached status (no network call)const cached = client.getCachedStatus();
// Cleanup on unmount / shutdown
client.destroy();
🌐
Domain Fingerprint
Automatic Origin header detection in browser mode
⚡
Feature Flags
Check plan-gated features with one API call
🔁
Periodic Validation
Configurable interval with onValid/onInvalid callbacks
🔒
Dual Mode
'web' for browsers, 's2s' for server-to-server with IP
getCachedStatus() returns last result without network call
onValid / onInvalid callbacks for periodic validation events
LicenseError class with httpStatus and licenseStatus properties
destroy() stops interval and cleans up resources
Full TypeScript definitions included (.d.ts)
React Integration
React 18/19Hooks
Wrap the Web SDK in a React context provider and a custom hook. The provider initialises the license on mount, cleans up on unmount, and exposes status + feature flags to every component in your tree.
Use mode: 's2s' for server-side validation. The SDK sends the server's IP address instead of the browser Origin header. Ideal for protecting API backends, microservices, and server-rendered apps.
Don't use .NET or JavaScript? Call the licensing API directly from any language. All endpoints accept and return JSON. Desktop endpoints use hardware fingerprints; web endpoints use domain or IP fingerprinting.
💻 Desktop SDK Endpoints
Method
Endpoint
Description
POST
/api/licenses/activate
Register a device with a license key. Sends appId, licenseKey, and hardware fingerprint. Returns full validation result.
POST
/api/licenses/validate
Validate a license. Returns isValid, status, expiry, plan name, device counts, and days remaining.
POST
/api/licenses/renew
Renew a license with a new plan ID. Updates expiry and plan details.
POST
/api/licenses/revoke
Deregister a device, freeing its slot for another machine.
POST
/api/licenses/check-update
Check if a newer binary version is available. Returns version, release notes.
POST
/api/licenses/download-token
Get a time-limited token for downloading an update binary from Azure Blob Storage.
🌐 Web SDK Endpoints
Method
Endpoint
Description
POST
/api/web-licenses/initialise
Register a domain with a web license. Browser mode uses Origin header for fingerprinting.
POST
/api/web-licenses/validate
Validate a web license from the browser. Returns status, plan, expiry, domain counts.
POST
/api/web-licenses/s2s/validate
Server-to-server validation using the server's IP address as fingerprint.
GET
/api/web-licenses/status/{key}
Full status detail: registered domains, feature flags, current domain registration, plan info.
POST
/api/web-licenses/features
Check which feature flags are enabled for a license's plan. Accepts array of feature keys.
GET
/api/web-licenses/heartbeat/{key}
Lightweight alive check -returns boolean. Use for fast polling without full validation overhead.
📋 License Status Values (Both SDKs)
ActiveValid and online-verified
GracePeriodExpired but within offline grace window