Integrating License Key Activation
This guide covers software such as desktop apps (macOS or Windows), Chrome extensions, and SaaS products that rely on license key activation.
If you are integrating Freemius with a WordPress plugin, theme, or add-on, please follow the WordPress SDK integration guide.
Initial Steps
- Sign up for Freemius.
- Create a new SaaS or App product tailored to your needs.
- Go to the Plans and configure the plans and prices.
For pre-purchase registration, see the Checkout integration section in the SaaS Integration doc.
Revealing License Keys to Customers
This configuration is only relevant for SaaS products. For Apps, license keys are always shown to buyers.
- Log in to the developer dashboard.
- Navigate to Settings page.
- Under the License Keys section, toggle on the switch to "show license keys to customers". The setting is automatically saved.
Checkout Integration
Integrate the checkout with your buy buttons as a modal dialog triggered by JavaScript, or by using direct checkout links.
If you require registration prior to purchasing, check the Checkout integration section in the SaaS Integration doc.
License Key Integration
Create a license form in your app to validate the key.
License Activation
To activate a license key, send a POST request to the license activation API endpoint:
POST /v1/products/{product_id}/licenses/activate.json
Host: api.freemius.com
Content-Type: application/json
{
"uid": "{uuid}",
"license_key": "{license_key}",
"title": "{title}"
}
The following parameters must be included in the request body:
{title}– The name of the installation device. This helps you and your customer identify the device during deactivation. For example, "John's MacBook Pro".{license_key}– The entered license key{uuid}– An unique 32-character identifier. You need to generate it from your application. See below for examples.
You can also include additional parameters which you can find in our API documentation.
Generating a Unique Identifier (UUID)
Here are some code snippets to generate a unique identifier (UUID) for different platforms. The UUID should be consistent for the same device, so it can be used to track license activations and deactivations.
- Node.js
- Browser
- Windows
- MacOS
import nodeMachineId from 'node-machine-id';
import crypto from 'node:crypto';
// Works for any JS runtime, like Nodejs, Bun, Deno, etc.
function getDeviceGuid() {
const rawMachineId = nodeMachineId.machineIdSync();
return crypto
.createHash('sha256')
.update(`freemius-my-app:${rawMachineId}`)
.digest('hex')
.slice(0, 32);
}
console.log(getDeviceGuid());
// Store uuid in the local storage where the license is activated.
crypto.randomUUID().replace(/-/g, '');
// With C# using Microsoft.Win32;
using System.Security.Cryptography;
using System.Text;
string GetDeviceId()
{
string? machineGuid = null;
try
{
using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Cryptography");
machineGuid = key?.GetValue("MachineGuid")?.ToString();
}
catch
{
// ignore and fallback
}
// If MachineGuid exists → hash it
if (!string.IsNullOrWhiteSpace(machineGuid))
{
using var md5 = MD5.Create();
var bytes = Encoding.UTF8.GetBytes(machineGuid);
var hash = md5.ComputeHash(bytes);
return Convert.ToHexString(hash); // 32 chars
}
// Fallback → random 32-char ID
return Guid.NewGuid().ToString("N"); // also 32 chars
}
import Foundation
import IOKit
import CryptoKit
func getDeviceId() -> String {
if let uuid = getIOPlatformUUID(), !uuid.isEmpty {
return md5(uuid)
}
// fallback → random 32-char ID
return UUID().uuidString.replacingOccurrences(of: "-", with: "")
}
private func getIOPlatformUUID() -> String? {
let matching = IOServiceMatching("IOPlatformExpertDevice")
let service = IOServiceGetMatchingService(kIOMainPortDefault, matching)
defer {
IOObjectRelease(service)
}
guard service != 0 else { return nil }
if let cfUUID = IORegistryEntryCreateCFProperty(
service,
"IOPlatformUUID" as CFString,
kCFAllocatorDefault,
0
) {
return cfUUID.takeRetainedValue() as? String
}
return nil
}
private func md5(_ string: String) -> String {
let data = Data(string.utf8)
let digest = Insecure.MD5.hash(data: data)
return digest.map { String(format: "%02hhx", $0) }.joined().uppercased()
}
If the license key is valid and activated, the endpoint will return an object with various useful properties which you can find in the API documentation. The most important properties are:
install_id: The ID of the createdInstallentity. This is essentially the record of the activation for the specific device.install_api_token: A bearer token that can be used to update the properties of theInstallentity. More information can be found here.license_plan_name: The name of the plan associated with the activated license key. This is useful for showing the user which plan they are currently subscribed to.
Ensure to store the uuid, install_id, install_api_token and license_key in the local storage (for Chrome extension use chrome.storage) where the license is activated. You'll need these details during license validation and deactivation.
License Deactivation
To deactivate a license, send a POST request to the license deactivation API endpoint:
POST /v1/products/{product_id}/licenses/deactivate.json?fields=id%2Cname%2Cslug
Host: api.freemius.com
Content-Type: application/json
{
"uid": "{uuid}",
"install_id": "{install_id}",
"license_key": "{license_key}"
}
{uuid}– Must be replaced with the stored install’s uuid{install_id}– Must be replaced with the stored install’s ID{license_key}– Must be replaced with the stored license key
License Validation
To validate a license, first fetch the activated license with a GET request to the Retrieve an active license by ID API endpoint:
GET /v1/products/{product_id}/installs/{install_id}/license.json?uid={uuid}&license_key={license_key}
Host: api.freemius.com
{uuid}– Must be replaced with the stored install’s uuid{install_id}– Must be replaced with the stored install’s ID{license_key}– Must be replaced with the stored license key
If the license is activated on the specified install, the endpoint returns a License object that includes the expiration and is_cancelled properties (among others).
If is_cancelled is true, the license was canceled from the Developer Dashboard and is therefore invalid. If the license wasn’t canceled, expiration contains the license expiration date formatted as Y-m-d H:i:s (it can also be equal to null for lifetime licenses).
When sending any query parameter with a GET request, for example, the license key or the UUID, please make sure to encode the values. For example:
- PHP
- JavaScript
$url = "https://api.freemius.com...?license_key=" . url_encode($license_key);
const url = `https://api.freemius.com...?license_key=${encodeURIComponent(licenseKey)}`;
Distributing the Software
After integrating license key activation, the next step is to set up custom download links, where your customers can download the app files.