A dead-simple software licensing API built for developers

License and protect your business's desktop apps, on-premise software, and other digital products.


"Using Keygen saved me the trouble of building and maintaining my own licensing server and strategy. It is easy to work with, reliable, and affordable." – GuideGuide

Get Started for FreeView Pricing

Developer time is expensive

Making it more productive is a no-brainer

  • checkSkip the in-house licensing solutions. Save your business development time and money with our developer APIs.
  • checkSecurely integrate our developer APIs to manage the licensing and distribution of your software products.
Get Started for Free
# Create a new license for a user of the “ecorp” account
curl https://api.keygen.sh/v1/accounts/ecorp/licenses -X POST \
  -H 'Authorization: Bearer a9f93c31b41642248db99fc04f4e8482.ebbe297ffbed4ccc837733e335bd8181…' \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -d '{
        "data": {
          "type": "licenses",
          "attributes": {
            "key": "B8A5-91D7-CB9A-DAE4-4F6E-1128"
          },
          "relationships": {
            "policy": {
              "data: { "type": "policies", "id": "fbc29532…" }
            },
            "user": {
              "data: { "type": "users", "id": "592032dd…" }
            }
          }
        }
      }'
security

Licensing Policies

Control what types of licenses each product offers using Keygen's powerful license policies. From node-locked licenses to timed trials, we have your licensing needs covered.

people

Identity Management

Utilize Keygen's identity management features to support multiple licenses per-user, and allow users to perform self-management actions for their licenses and machines.

fingerprint

Machine Activations

Enforce where your products can and cannot be used by managing each license's machine activations. Our policies enforce everything from node-locked to floating licenses.

Bring your own programming language

Quickly implement Keygen's API in any programming language.

const fetch = require('node-fetch')

const res = await fetch('https://api.keygen.sh/v1/accounts/demo/licenses/actions/validate-key', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
    'Accept': 'application/vnd.api+json'
  },
  body: JSON.stringify({
    meta: {
      key: 'B8A5-91D7-CB9A-DAE4-4F6E-1128'
    }
  })
})

const { meta } = await res.json()

if (meta.valid) {
  // Do something
} else {
  // Do something else
}
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/demo/licenses/actions/validate-key",
  method: .post,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json"
  ],
  parameters: [
    "meta": [
      "key": "B8A5-91D7-CB9A-DAE4-4F6E-1128"
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
  let valid = json["meta"]["valid"].bool

  if valid {
    // Do something
  } else {
    // Do something else
  }
}
using RestSharp;
using System;
using System.Collections.Generic;

var client = new RestClient("https://api.keygen.sh/v1/accounts/demo");
var request = new RestRequest(
  "licenses/actions/validate-key",
  Method.POST
);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddJsonBody(new {
  meta = new {
    key = "B8A5-91D7-CB9A-DAE4-4F6E-1128"
  }
});

var response = client.Execute<Dictionary<string, object>>(request);
var meta = (Dictionary<string, object>) response.Data["meta"];

if ((bool) meta["valid"])
{
  // Do something
}
else
{
  // Do something else
}
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "meta" to mapOf(
    "key" to "B8A5-91D7-CB9A-DAE4-4F6E-1128"
  )
))

val res = Unirest.post("https://api.keygen.sh/v1/accounts/demo/licenses/actions/validate-key")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()

val data = res.getBody().getObject()
val meta = data.getJSONObject("meta")

if (meta.getBoolean("valid")) {
  // Do something
} else {
  // Do something else
}
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;
import org.json.*;

import static java.util.Map.ofEntries;
import static java.util.Map.entry;

JSONObject body = new JSONObject(ofEntries(
  entry("meta", ofEntries(
    entry("key", "B8A5-91D7-CB9A-DAE4-4F6E-1128")
  ))
));

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/demo/licenses/actions/validate-key")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();

JSONObject data = res.getBody().getObject();
JSONObject meta = data.getJSONObject("meta");

if (meta.getBoolean("valid"))
{
  // Do something
}
else
{
  // Do something else
}
#include <iostream>
#include <string>
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>

using namespace std;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace web::json;
using namespace utility;

http_client client("https://api.keygen.sh/v1/accounts/demo");
http_request req;

value meta;
meta["key"] = value::string("B8A5-91D7-CB9A-DAE4-4F6E-1128");

value body;
body["meta"] = meta;

req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/actions/validate-key");
req.set_method(methods::POST);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
    auto meta = data.at("meta");

    if (meta.at("valid").as_bool())
    {
      // Do something
    }
    else
    {
      // Do something else
    }
  })
  .wait();
import requests
import json

data = requests.post(
  "https://api.keygen.sh/v1/accounts/demo/licenses/actions/validate-key",
  headers={
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json"
  },
  data=json.dumps({
    "meta": {
      "key": "B8A5-91D7-CB9A-DAE4-4F6E-1128"
    }
  })
).json()

if data["meta"]["valid"]:
  # Do something
else:
  # Do something else
require 'httparty'

data = HTTParty.post(
  'https://api.keygen.sh/v1/accounts/demo/licenses/actions/validate-key',
  headers: {
    'Content-Type' => 'application/vnd.api+json',
    'Accept' => 'application/vnd.api+json'
  },
  body: {
    meta: {
      key: 'B8A5-91D7-CB9A-DAE4-4F6E-1128'
    }
  }
)

if data['meta']['valid']
  # Do something
else
  # Do something else
end
<?php

$url = 'https://api.keygen.sh/v1/accounts/demo/licenses/actions/validate-key';
$ch = curl_init($url);

$body = json_encode([
  'meta' => [
    'key' => 'B8A5-91D7-CB9A-DAE4-4F6E-1128'
  ]
]);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
  'Content-Type: application/json',
  'Accept: application/json'
]);

$json = curl_exec($ch);
$data = json_decode($json);

if ($data->meta->valid) {
  // Do something
} else {
  // Do something else
}

A better answer to Build vs. Buy

Businesses of all sizes face the question of whether to build or buy a product licensing solution. Keygen's developer APIs give you a better option.

  • check

    Building blocks for implementing countless licensing models.

  • check

    Clear developer documentation covering how to integrate Keygen.

  • check

    Laser-focused on making your development team productive.


"The API documentation lives up to the newest standards, just like Stripe and WooCommerce. Easy integration with almost any type of software." – StorePilot

Get Started for Free or explore the API

"Saved time, money and made our customers happy. My staff are able to manage licenses with ease." – Anthony O.


FAQs

  • What licensing models are supported?

    Keygen supports almost any licensing model: perpetual licenses, machine leasing, subscription-based models, concurrency models, single machine-locked licenses, floating licenses with and without machine limits, feature-based licenses, limited pre-determined pool-based licenses, licenses that require periodic check-in, and even a combination of most of those.

  • Does Keygen prevent sharing licenses?

    Yes! Keygen offers API endpoints to help you track user machine usage, and license policies can be configured to strict, invalidating licenses that go over any configured machine limit. You can also set license policies to floating to allow licenses to be valid across multiple machines.

  • Does Keygen prevent cracking?

    Not entirely. Keygen provides tools to help prevent attempts to crack your software. We provide tools such as request signatures to prevent man-in-the-middle attacks, but most crack prevention will fall on your team and will depend on many factors such as the platform and programming language your software uses.

  • Where can I monitor Keygen's uptime?

    We strive to provide the highest uptime possible for our customers through a distributed system hosted on battle-tested insfrastructure. You can monitor uptime and average response time for each of Keygen's services from our status page.

  • Is data within Keygen secure?

    Yes. We strive to ensure that the data stored within Keygen is as secure as possible. We never store passwords as plain text—they are always hashed and salted securely using bcrypt. We also do the same with all access tokens. We use 256-bit encryption at all levels of our software. All connections to our APIs are encrypted over TLS (i.e. we encrypt "in transit"), our databases are encrypted (i.e. we encrypt "at rest"), and all of our data backups are encrypted. Have additional questions or concerns? Get in touch.

  • Does Keygen work offline?

    Yes, we support several methods of cryptographically signing or encrypting license keys, which can be verified in offline environments. For more information, check out our API reference.

  • Does Keygen handle distribution?

    Yes! Using Keygen Dist, you can distribute your products to licensed users and even provide auto-updates using industry standard frameworks such as Sparkle, NSIS, Squirrel.Mac, Squirrel.Windows, and even updates for WordPress plugins and themes.

  • Does Keygen handle payments?

    No—only licensing. Since products handle payments in a variety of ways (and we don't want to become a payment platform), we have created a webhook system so that you can easily integrate your payment system with our API. Implementation is similar to how you would implement Stripe's webhook system. Learn more about webhooks.

  • Can I use Keygen for an iOS app?

    Yes and no. Unfortunately, it isn't possible at this time to use Keygen for in-app license purchases. Apple’s developer terms require that in-app purchases, such as premium content and add-ons are done through their native In-App Purchase API. But it is possible to use Keygen as a secondary licensing system, as long as it is not advertised in-app (i.e. purchases will need to be done via a web site, outside of the app).

  • Can I use Keygen for an Android app?

    Yes and no. If you're selling outside of the Google Play Store, then yes, you can use Keygen to handle licensing. But if you're selling within the Google Play Store, then unfortunately it isn't possible at this time to use Keygen for in-app license purchases. Google's developer policy requires that in-app purchases, such as premium features and add-ons are managed via their native In-App Billing API. But it is possible to use Keygen as a secondary licensing system, as long as it is not advertised in-app (i.e. purchases will need to be done via a web site, outside of the app).


"Keygen has flexible license management options backed by great customer support. Keygen is enabling us to very quickly get licensing off the ground for a reasonable price." – Mining & Metals