A dead-simple software licensing API built for developers

For licensing desktop apps, on-premise software, and other digital products.

Get Started Free

Quit wasting time fighting with other licensing “solutions”

  • checkEasily sell, license and distribute your desktop/server software by utilizing our powerful licensing and distribution APIs.
  • checkShip faster and stop wasting time (and money!) writing custom licensing servers that don't have all the features you want.
  • checkSupport a wider range of platforms by using a licensing and auto-update service that doesn't rely on a specific OS.

and last but not least…

  • closeNo gimmicky third-party activation wizards that you need to package with your product (and that you have no control over!)
# 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

Control

Control what types of licenses your product offers using powerful license policies—from feature licenses to timed trials, we got you covered.

verified_user

Monitor

Quit guessing how many machines your users have—using our machine tracking endpoints you can know exactly where your product is being used.

Know what's working

…and what isn't. With Keygen's dashboard, you can always be on top of what's happening with your products.

  • trending_upView recent trends for new users, licenses, and much more
  • listWatch an up-to-date activity feed of what's happening
  • timelineSee all recent successful and failed license validations
  • memoryInstantly see new machine activations in full detail

Use your favorite language

Quickly implement Keygen in the programming language of your choice.

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
}

Learn how to…

and of course…

Join our newsletter to stay updated

FAQs

  • What is Keygen?

    Keygen is a cloud-based LaaS (licensing as a service) that provides secure license and user management for desktop apps and other types of software. Keygen's primary product is a set of APIs that enable developers to quickly set up licensing, user management, and product distribution.

  • Who is Keygen for?

    Keygen is primarily built for small- to medium-sized businesses who build desktop applications, on-premise software, and other digital products e.g. WordPress plugins, etc. We also offer on-premise options for larger companies that are interested in using Keygen.

  • Why was Keygen created?

    Keygen aims to make licensing software for small- to medium-businesses easy by letting you ship your product earlier and not waste time building custom licensing servers and managing infrastructure.

  • Can Keygen help lower support costs?

    Yes! One of the things that makes Keygen unique is that we encourage you to allow your users to manage their own resources i.e. their licenses and machines, while you respond to the appropriate webhook events to handle billing using your payment provider. This not only gives your users freedom to purchase additional licenses directly from within your product without your help (offering a great user-experience and potential for more sales!) but can also lower your licensing-related support costs.

  • What licensing models are supported?

    Keygen supports almost any licensing model: perpetual licenses, 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?

    No. Keygen does nothing to prevent a user from removing your licensing logic altogether if they have access to your application's code. In the end, you will have to make the choice on how to deal with cracking by e.g. requiring a valid license for updates, requiring a licensed user-account for support requests, etc.

  • 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, and offer the ability to hash license keys as well. All network traffic is encrypted over TLS with at least 128-bit AES encryption. Have additional questions or concerns? Get in touch.

  • Does Keygen work offline?

    Yes, but it requires additional work. We have an example on GitHub of how you could go about implementing license activation for air-gapped machines using TOTP, QR codes, and a mobile device.

  • 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.

  • Do you offer on-premise API plans?

    Yes. We're very interested in talking with companies that would rather host our software licensing server in-house. Get in touch.

  • Can I use Keygen for an iOS app?

    Yes and no. Unfortunately, it isn't possible at this time to use Keygen for paid app-related licenses. Apple’s developer terms require that purchases related to an app, such as premium content and add-ons are managed via their native In-App Purchase API.

  • 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 paid app-related licenses. Google's developer policy requires that purchases related to an app, such as premium features and add-ons are managed via their native In-App Billing API.