linkAPI Reference

The Keygen API is organized around REST principles. All requests must be made over TLS/SSL. In addition, all request and response bodies, including errors, are encoded in JSON format.

The API has predictable, resource-oriented URLs, and uses standard HTTP response codes to indicate API errors. We use built-in HTTP features, like authentication and HTTP verbs, which are understood by off-the-shelf HTTP clients. We support cross-origin resource sharing, allowing you to interact securely with our API from any client-facing software application.

linkYour Keygen Account

In order to make requests to our licensing API, you will need to use your Keygen account's unique ID, or its slug that you chose during sign up. Every API request will utilize your account's ID or slug within the URL path, i.e. /v1/accounts/{ID} or /v1/accounts/{SLUG}. Your account's ID and slug can be used interchangably as URL params.

You can find your account's ID and slug in your account settings.

Account Permissions

By default, your Keygen account will allow public user registration, user token generation (authentication), and will also allow users to create their own licenses and machines while authenticated. This is referred to as an unprotected account, allowing client-side resource management (i.e. by your users), while you respond to those events using webhooks.

For example, you can allow users to create and delete their licenses and machine activations, while you respond to those events to handle billing, e.g. charge them for new licenses, update their subscription to match their license and machine count, etc.

If you do not want your users to be able to create and manage their own licenses and machines client-side (which necessitates listening for webhook events) then you should set your account to protected, which will require admin authentication to create and manage all resources.

Setting your account to protected is the recommended approach when using Keygen 100% server-side. You can change your account permissions from your account settings page.

See the security section for more tips.

linkAccepted Content Types

Our JSON API accepts the following content types specified via the HTTP Content-Type header:

  • application/vnd.api+json
  • application/json

In addition, our JSON API is able to respond with the following content types specified via the HTTP Accept header:

  • application/vnd.api+json
  • application/json

By default our API will respond with application/vnd.api+json, unless asked otherwise through the standard HTTP Accept header. All other content types will be rejected with a 400 status code.

linkClient Libraries

At the moment we're focused on our HTTP API endpoints. As time goes by we'll be featuring here some more of our open-source clients for different languages and frameworks, as well as those contributed by the community.

If you have written one yourself, please let us know. We will feature your name along with the client library, unless asked to do otherwise.

We will collaborate with project maintainers to keep open source libraries up-to-date as our systems evolve. If you would like us to add documentation examples for a specific language, or if you would like us to add an open-source library you created, please email [email protected].

linkPre-populated Examples

When you're logged in to your dashboard, your authentication token is pre-populated in all the examples on this page so you can test any example right away. Only you can see these values.

The pre-populated token is an admin token and is not meant to be used in client-facing code, stored in version control, and so forth.

linkArchitecture

How to model the communication layer between your app and Keygen. Although these are not the only way, they are some of the most common setups.

A) Direct

First up is the direct approach, utilizing a direct communication channel from your app to Keygen's API. This allows users to for example create licenses from within your app, while your server responds to webhook events accordingly, updating records to reflect any changes made server-side as well as to handle invoicing your users for any purchased licenses.

Using the direct architecture also lightens the load on your servers, allowing users to interact directly with Keygen's APIs for most of their transactions, e.g. license validation and creation, as well as managing their machines. You can then respond to the appropriate webhook events to for example charge a customer for a new license.

On the topic of billing, it is recommended that your users register through your server, so that you can handle the initial collection of user billing information. We recommend using Stripe for billing. After you've created a user account, you can attach their Stripe customer_id to the user's metadata attribute.

If you'd like to allow registration directly from your app, you will need to collect a Stripe token and attach that as metadata, so that your server can respond to Keygen's user.created webhook event and finish the billing process. If your app is free to use, then registration is as simple as creating a new user.

Do not attach sensitive information directly to your users using the metadata attribute. Doing so is a violation of our terms of use. If you're using Stripe, you need only attach their Stripe customer_id, or a secure representation of a card (such as a stripe_token), which can then be used to look up their information server-side when required.

B) Middleman

Next is an alternate approach, using your server as a middleman for communication between your app and Keygen's API. This architecture allows you to more easily manage and validate events, instead of relying solely on listening for webhook events.

In addition, this approach also allows you to store user accounts within your own database, instead of utilizing Keygen's user-management features. You may do so by associating the unique id of a user-less license to a user model within your database.

Did you know that you can create a license without a user? You can do so by going through the usual license creation flow, while ommiting the user relationship. This can be used to create licenses for users stored within your own database.

linkVersioning

When we introduce breaking changes to the API, we will release a new numbered version, e.g. we will go from v1 to v2. The current version is v1. All changes will be detailed within our changelog.

linkAPI Stability

We will not introduce breaking changes into the API without bumping the current version. You can rest assured that the endpoints you're utilizing within your product are stable.

Keep in mind that stable does not mean complete. We could potentially add new resources and actions, but existing resources will remain unchanged.

linkBackwards Compatibility

What do we consider to be “backwards-compatible” changes?

  • Adding new API resources
  • Adding new optional request parameters to existing API endpoints
  • Adding new properties to existing API resources and responses
  • Changing the order of properties in existing API responses
  • Changing the length or format of resource IDs, future tokens, future auto-generated license keys, or other opaque strings (this includes adding or removing prefixes)
  • You can safely assume resource IDs we generate will never exceed 255 characters (but you should be able to handle IDs of up to that length)
  • Adding new event types (your webhook listeners should gracefully handle unfamiliar events types)

linkSecurity

  1. Do not store your API tokens in version control. If you're using version control like Git or Subversion, do not store your API tokens in version control. It is recommended that you store tokens in a file that is never checked into the repository, or within the ENV.

    If one of your API tokens become compromised, quickly revoke it from your admin dashboard.

  2. Do not embed your admin or product API tokens within your product's source code. If you're using Keygen client-side, do not embed your admin or product tokens within your product's source code. Doing so exposes your tokens and opens your account up to attackers.

    Instead, you can perform license and machine creation requests client-side while authenticated as one of your users and then you can listen for the corresponding webhook events to act accordingly e.g., charging them for new licenses, crediting them for deleted licenses or machines, etc. For an example of responding to user actions, see our Paddle integration example.

    If you're using Keygen server-side, see the above tip.

  3. Embedding account, product and policy IDs directly into your product i.e. client-side code is perfectly safe. In fact, you won't be able to communicate with Keygen's API unless you do so, and managing e.g. feature licenses without being able to embed policy IDs wouldn't be feasible. With that in mind, it is recommended that you use your account ID over your account slug, as unlike your account slug, your ID is unchangable.

  4. If you do not want your users to be able to create and manage their own licenses and machines (which necessitates listening for webhook events) then you should set your account to protected, which will require admin authentication to create and manage all resources, aside from token creation and license validation. Setting your account to protected can be done within your account settings.

    Alternatively, you can set individual license policies to protected (which by default is inherited from the account's current protected state), which will only disallow users from creating and managing licenses which implement that particular policy and their associated machines, rather than all resources e.g. public user creation, licenses that implement other unprotected policies, etc.

    By default, your account is unprotected, which allows user registration as well as the ability for users to manage their own resources.

  5. To validate license keys offline, you will need to manually generate license keys server-side using a public/private keypair. For example, when creating a new license, you would specify the key attribute with a value generated from your private key. You would then validate the license key client-side by embedding a derived public key within your software. Here's an example of doing so using Node.

    Alternatively, you can set up "air-gapped" license activation using RSA cryptography, QR codes, and a mobile device. View our example implementation.

    Offline license validation cannot use metrics outside of simple expiry validation, as it would require an internet connection to e.g. validate against a license's machine requirements, etc. Keep that in mind.

  6. If you only need to validate license keys, then you do not need to implement user authentication. The license validate-key action does not require authentication. If you're doing anything else e.g. validating multiple license resources per-user, tracking machines, etc., user authentication will be required in order to communicate with Keygen's API client-side.

    You can add required scopes to your policies to e.g. require a machine fingerprint, etc., which helps implement certain license models without the need for any additional server-side logic such as a webhook handler.

  7. If you do not want the overhead of implementing webhooks, then you should only use Keygen server-side alongside your payment provider. Implementing Keygen client-side necessitates listening for webhook events, unless you're simply validating license keys directly, as mentioned above.

    When using Keygen client-side, you should utilize webhooks to e.g. keep your billing state up to date with recent user actions.

linkResponse Codes

Our API uses conventional HTTP response codes to indicate the success or failure of an API request. In general, codes in the 2xx range indicate success, codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, a validation failed, etc.), and codes in the 5xx range indicate an error with our servers (these are rare).

Code Status Meaning
200 OK Everything worked as expected.
201 Created The resource was created successfully.
202 Accepted The request has been accepted for processing.
204 No content Everything worked as expected, but there was nothing to respond with.
400 Bad Request The request was unacceptable, often due to missing or unpermitted parameters.
401 Unauthorized No valid API token provided.
403 Forbidden The authenticated entity does not have permission to complete the request.
404 Not Found The requested resource doesn't exist.
409 Conflict The request could not be completed because the resource already exists.
422 Unprocessable Entity A validation error occurred on the resource.
429 Too Many Requests Too many requests hit the API too quickly. We recommend an exponential backoff of your requests.
5xx Server Errors Something went wrong on our end. (These are rare.)

linkErrors

Below you will find the various attributes for request errors.

linkAttributes

  • linktitle

    string

    A short, human-readable summary of the problem.

  • linkdetail

    string

    A more detailed human-readable explanation of the problem.

  • linksource

    hash<string, any>

    A hash containing references to the source of the error. This may or may not be included in the error payload, depending on the error.

  • linksource.pointer

    string

    A pointer to the problem data, e.g. "/data" for the primary data, "/data/attributes/email" for a specific attribute, or "/data/relationships/user" for a problem with a relationship. This may or may not be included in the error payload, depending on the error.

  • linksource.parameter

    string

    A string indicating which URI query parameter caused the error. This may or may not be included in the error payload, depending on the error.

Example error

{
  "errors": [
    {
      "title": "Unprocessable entity",
      "detail": "must be a valid email",
      "source": {
        "pointer": "/data/attributes/email"
      }
    },
    …
  ]
}

linkAuthentication

Requests are authenticated using a bearer token in an Authorization header. Within the header, you will utilize a Token resource's token attribute, like so,

Authorization: Bearer {TOKEN}

If you want to interact with Keygen's API client-side, then you should do so using our user resources, which we created for this purpose. You can create users with email and password credentials, which can be used during token generation to authenticate a user. After a user is authenticated, they can interact with our API in a way that is limited to only their account.

Along with admins and users, a product can also authenticate using product tokens; to create a new product token, please see the Product token relationship. All user tokens have a 2 week expiry and can be regenerated as needed during that timeframe. Admin and product tokens do not expire, but should only be used server-side.

Admin and product tokens should only be used server-side, this is because they allow full near management of your Keygen account. This means that if an attacker were to obtain a product token from within your code, no matter how obfuscated, they will be able to create and manage licenses at-will—including those of your other customers.

Most API endpoints will require authentication, and access to resources depends on the token bearer's authorization and role.

You can manage tokens using the Tokens resource.

Security Warning

Tokens should be treated as passwords. Different tokens carry different privileges depending on the bearer of the token, so be sure to keep them secret! Do not share your admin or product API tokens in publicly accessible areas such as GitHub, client-facing code, and so forth. If in doubt, please reset or revoke the offending authentication token(s).

linkAuthorization

Access to certain resources is dependent upon a token bearer's role. Most of the time you will be authenticating as one of your users, which will allow access to a small subset of resources available to your account. In other cases, as when you are using the middleman architecture, you may be authenticating as a product, or even an admin; in these cases, you will have access to a wider range of resources.

Resource attributes and relationships marked with a "protected" badge are only allowed to be specified if the authenticated bearer is an admin of the account, or a product that owns the specified resource. Attributes and relationships marked with a "read only" badge can not be modified.

Many resource endpoints are automatically scoped according to the token bearer's role. For example, listing all licenses while authenticated as a product will only list licenses associated with that particular product. Attempting to access resources that the bearer does not have access to will respond with a 403 forbidden error.

Never hard-code authentication tokens within your client-facing product – doing so could leave your product open to major exploitations by allowing a malicious user the ability to fully manage your account's resources. The only time you should be using your admin or product token(s) directly is if you are working with Keygen server-side.

Here's a quick summary of the different authorization roles:

Role Authentication Authorization
None No Unauthenticated users can create a new user account (unless your account is protected), and validate license keys using the validate-key action. No other endpoints are accessisible to unauthenticated users.
User Yes Authenticated users may access certain resource endpoints, but all resources that are returned will be scoped to their user account, e.g. when a user makes a request to list all licenses, only the licenses which are associated with their user account will be returned.
Product Yes Authenticated products may access resources for their account that are associated with that particular product. All resources that are returned will be scoped to the product, e.g. when a product makes a request to list all licenses, only the licenses which are associated with the product will be returned.
Admin Yes Authenticated admin users may access all resources for their account.

linkRate Limiting

A single IP address can make a maximum burst of 100 requests per 10 second window, regardless of authentication. If we see patterns of abuse, this may be lowered or the IP may be temporarily blacklisted or in rare cases of significant abuse, permanently blacklisted.

You can check the returned HTTP headers of any API request to see your current rate limit status:

Header Description
X-RateLimit-Limit The maximum number of requests that the IP is permitted to make per 10 second window.
X-RateLimit-Remaining The number of requests remaining in the current rate limit window.
X-RateLimit-Reset The time at which the current rate limit window resets in UTC epoch seconds.
Need a higher rate limit? Give us a shout. We're open to making sure our API meets your requirements.

Example error

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1490973281
{
  "errors": [
    {
      "title": "Throttle limit reached",
      "detail": "Throttle limit has been reached for your IP address."
    }
  ]
}

linkRelationships

Throughout the API, many resources will have a relationships hash containing another resource which they are associated with. When creating or modifying a relationship, you will be introduced to what's called a "resource identifier object", or linkage for short.

A "resource identifier object" is a hash that identifies an individual resource. The linkage hash must contain a type and an id of the individual resource for the relationship.

Example resource identifier object

{
  "type": "policies",
  "id": "76805397-9b46-4dcf-ad90-177a0f0969e2"
}

linkMetadata

Many resources including products, users, licenses, machines and policies have a metadata attribute. You can use this attribute to attach key-value data to the given resource.

Metadata is useful for storing additional, structured information on an object. As an example, you could store your user's zipcode, their id within your own database (if applicable), or their Stripe customer_id for billing purposes.

Since the metadata attribute is simply a key-value store (hash), all write operations will overwrite the entire hash, so be sure to merge existing data on your end when performing updates.

Do not attach sensitive billing information directly to your users using the metadata attribute. Doing so is a violation of our terms of use. If you're using Stripe, you need only attach their Stripe customer_id, or a temporary secure representation of a card (such as a stripe_token), which can then be used to look up their information server-side when required.

You can specify up to 64 keys, with key names up to 256 characters long and values up to 512 characters long.

linkPagination

All top-level API resources have support for bulk fetches via "list" API methods. For instance you can list users, list licenses, and list machines. These list API methods share a common format, taking an optional page query parameter.

Our API utilizes a page-based strategy via the page[size] and page[number] parameters. All results are returned in reverse chronological order.

linkParameters

  • linkpage

    hash<string, integer>

    Hash containing page size and page number.

  • linkpage.size

    integer

    The page size. Must be a number between 1 and 100.

  • linkpage.number

    integer

    The page number.

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/users?page[size]=25&page[number]=2", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, links, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/users?page[size]=25&page[number]=2",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("users", Method.GET);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddParameter("page[size]", 25);
request.AddParameter("page[number]", 2);

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/users")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("page[size]", 25)
  .queryString("page[number]", 2)
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/users")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("page[size]", 25)
  .queryString("page[number]", 2)
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

uri_builder uri("/users");
uri.append_query("page[size]", 25);
uri.append_query("page[number]", 2);

req.set_request_uri(uri.to_uri());
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl 'https://api.keygen.sh/v1/accounts/<%= account %>/users?page[size]=25&page[number]=2' -g \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response

{
  "data": [
    {
      "id": "6ed498fe-5f5f-49af-82ee-cb7400cc4522",
      "type": "users",
      "links": {
        "self": "/v1/accounts/<%= account %>/users/6ed498fe-5f5f-49af-82ee-cb7400cc4522"
      },
      "attributes": {
        "fullName": "Marty McFly",
        "firstName": "Marty",
        "lastName": "McFly",
        "email": "[email protected]",
        "role": "user",
        "metadata": {},
        "created": "2017-01-02T19:48:50.077Z",
        "updated": "2017-01-02T19:48:50.077Z"
      },
      "relationships": {
        "account": {
          "links": {
            "related": "/v1/accounts/<%= account %>"
          },
          "data": {
            "type": "accounts",
            "id": "<%= account %>"
          }
        },
        "products": {
          "links": {
            "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/products"
          }
        },
        "licenses": {
          "links": {
            "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/licenses"
          }
        },
        "machines": {
          "links": {
            "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/machines"
          }
        },
        "tokens": {
          "links": {
            "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/tokens"
          }
        }
      }
    },
    …
  ],
  "links": {
    "self": "/v1/accounts/<%= account %>/users?page[size]=25&page[number]=2",
    "prev": "/v1/accounts/<%= account %>/users?page[size]=25&page[number]=1",
    "next": "/v1/accounts/<%= account %>/users?page[size]=25&page[number]=3",
    "first": "/v1/accounts/<%= account %>/users?page[size]=25&page[number]=1",
    "last": "/v1/accounts/<%= account %>/users?page[size]=25&page[number]=4"
  }
}

linkIdempotency

Some resources, such as webhook events may contain an idempotency token inside of a meta hash. In the case of webhook events, these tokens allow you to safely retry events without accidentally responding to the same event multiple times.

linkExample scenario

When a user creates a new license, you would want to make sure that the license.created webhook event that you're listening for would only be acted upon once, regardless of how many times you retry the event, to guarantee you only charge your user for a single license.

You can accomplish this by logging the idempotency token (to a database, for example) and ignoring future webhook events that come through with an identical token, signaling a retried event.

Although retrying a webhook event creates a new resource, the idempotency token will stay the same throughout the event's lifetime.

Example resource

A failed webhook event resource.

{
  "data": {
    "id": "2bc99fe1-f315-4877-ac5f-542240c4e883",
    "type": "webhook-events",
    "meta": {
      "idempotencyToken": "e8e0fbb598e8bcfd0e94ceb79199edc79e6ab53f4a4bbb32d7aede7964e7c3v1",
    },
    "links": {
      "self": "/v1/accounts/<%= account %>/webhook-events/2bc99fe1-f315-4877-ac5f-542240c4e883"
    },
    "attributes": {
      "endpoint": "https://example.com/webhooks",
      "payload": "{\"data\":{…}}",
      "event": "license.created",
      "status": "failed",
      "created": "2017-01-02T20:26:53.464Z",
      "updated": "2017-01-02T20:26:53.464Z"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      }
    }
  }
}

Example request

Retry the above failed webhook event resource.

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/2bc99fe1-f315-4877-ac5f-542240c4e883/actions/retry", {
  method: "POST",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/2bc99fe1-f315-4877-ac5f-542240c4e883/actions/retry",
  method: .post,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "webhook-events/2bc99fe1-f315-4877-ac5f-542240c4e883/actions/retry",
  Method.POST
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/2bc99fe1-f315-4877-ac5f-542240c4e883/actions/retry")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/2bc99fe1-f315-4877-ac5f-542240c4e883/actions/retry")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/webhook-events/2bc99fe1-f315-4877-ac5f-542240c4e883/actions/retry");
req.set_method(methods::POST);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/2bc99fe1-f315-4877-ac5f-542240c4e883/actions/retry \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response

Notice that it's a new resource, yet the idempotency token matches the original event.

{
  "data": {
    "id": "1bda5fd5-6d82-49f5-b5b8-71bb432a32bb",
    "type": "webhook-events",
    "meta": {
      "idempotencyToken": "e8e0fbb598e8bcfd0e94ceb79199edc79e6ab53f4a4bbb32d7aede7964e7c3v1",
    },
    "links": {
      "self": "/v1/accounts/<%= account %>/webhook-events/1bda5fd5-6d82-49f5-b5b8-71bb432a32bb"
    },
    "attributes": {
      "endpoint": "https://example.com/webhooks",
      "payload": "{\"data\":{…}}",
      "event": "license.created",
      "status": "queued",
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      }
    }
  }
}

linkSignatures

Each Keygen account is equipped with it's own unique RSA 2048-bit public/private keypair, which is used in signing response payloads using rsa-sha256. You can find your account's public key within your dashboard settings page, which you can use to verify response payloads.

You may utilize your account's public key to verify that successful requests, and webhooks, originated from Keygen. This is useful in preventing man-in-the-middle (MITM) attacks, where an attacker will redirect requests to a local server under their control which defaults to sending "valid" license responses.

We do not sign certain error payloads - please keep this in mind during implementation. We will always sign successful responses (2xx–3xx) and errors that occur while authenticated using your account's private key. Certain error responses, such as authentication errors, will not include the X-Signature header.
Header Description
X-Signature The base64 encoded rsa-sha256 signature of the response body.

To see an example of signature verfication, check out our example on GitHub. It will show you how to utilize your account's public key to verify that the response was signed using your account's private key.

Example signature

X-Signature: fUKlYwejbSxKGtWfqcx5SfeHlhw16c+5tb0JluFwkIOCyzcUug+F1vNMFiKg03Zs/wwS1UKNEdI9Cx8EvFUn/7XFuaNL5AqAPdjdBt5kW3D1wqFtDPSGjh4lmRNybn158yM3cZJOQcg1tCHjWjzSYERELZyTbS+gjLr8mnrcTiAl+vZr4AJkxzdT0NrK633oTwzcsk2564BRh96YqSsmbMhPKl9R8r3Ulqe23bvl0h5vCHwlspzm9dpywnvc+He+imFj6Cxuz9FXnlXx6SxXzwcfWEJPa1CPtZPLy8gIlHNL195lr5s1wPsMv1jz5bp8adWOFKA9Ed7ocODZYU/fgg==
{
  "data": {
    …
  }
}

linkTokens

linkThe token object

Below you will find the various attributes for the token resource, as well as the token resource's relationships. The actual token string is hashed before being stored in our databases, thus is only available directly after generating/regenerating a token.

linkAttributes

  • linktoken

    stringread only

    The raw token of the token. This attribute is only available to read directly after token generation.

  • linkexpiry

    timestampread only

    When the token expires.

  • linkcreated

    timestampread only

    When the token was created.

  • linkupdated

    timestampread only

    When the token was last updated.

linkRelationships

  • linkaccount

    individual

    The account that the token belongs to.

  • linkbearer

    individual

    The bearer of the token.

Example object

{
  "data": {
    "id": "6a7562be-b302-43d2-a550-30d6026247aa",
    "type": "tokens",
    "attributes": {
      "token": "9bc31b8d19a94d82a15742678d8f2540.6a7562beb30243d2a55030d6026247aa.edc19321739951dc8fe9ce7d27c703a74faabd7dee8228b8ad4ec6e69692d6959449d9694fd93eca48b33f023bd1319f14b90de1cba5001945dea6b66f5986v1",
      "expiry": "<%= expiry %>",
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "bearer": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298"
        },
        "data": {
          "type": "users",
          "id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298"
        }
      }
    }
  }
}

linkGenerate a token

Generate a new token resource for a user. To generate a token for a product, see the product token relationship.

Admin and product tokens should not be included in any client-facing code, as they offer full access to all of your account's resources. You should always authenticate as one of your users within your product. Admin and product tokens should only be used server-side.

linkAuthentication

  • linkBasic

    required

    The email and password of the user. Credentials MUST use a colon (i.e. ":") to separate the email and password (i.e. "EMAIL:PASSWORD"), and those credentials MUST then be base64 encoded.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkReturns

A 201 Created response will be returned along with the new token object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/tokens

Example request

const fetch = require("node-fetch")

const credentials = new Buffer("<%= email %>:<%= password %>").toString("base64")
const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/tokens", {
  method: "POST",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": `Basic ${credentials}`
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

let credentials = Data("<%= email %>:<%= password %>".utf8).base64EncodedString()

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/tokens",
  method: .post,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Basic \(credentials)"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;
using System;
using System.Text;

var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes("<%= email %>:<%= password %>"));

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("tokens", Method.POST);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", $"Basic {credentials}");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/tokens")
  .header("Accept", "application/vnd.api+json")
  .basicAuth("<%= email %>", "<%= password %>")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/tokens")
  .header("Accept", "application/vnd.api+json")
  .basicAuth("<%= email %>", "<%= password %>")
  .asJson();
#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 utility;

http_client_config config;
credentials cred("<%= email %>", "<%= password %>");
config.set_credentials(cred);

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>", config);
http_request req;

req.headers().add("Accept", "application/json");

req.set_request_uri("/tokens");
req.set_method(methods::POST);

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/tokens \
  -H 'Accept: application/vnd.api+json' \
  -u "<%= email %>:<%= password %>"

Example response / 201 Created

{
  "data": {
    "id": "6a7562be-b302-43d2-a550-30d6026247aa",
    "type": "tokens",
    "attributes": {
      "token": "9bc31b8d19a94d82a15742678d8f2540.6a7562beb30243d2a55030d6026247aa.edc19321739951dc8fe9ce7d27c703a74faabd7dee8228b8ad4ec6e69692d6959449d9694fd93eca48b33f023bd1319f14b90de1cba5001945dea6b66f598dv1",
      "expiry": "<%= expiry %>",
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "bearer": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298"
        },
        "data": {
          "type": "users",
          "id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298"
        }
      }
    }
  }
}

linkRetrieve a token

Retrieves the details of an existing token.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resource: either an admin or the token owner.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the token to be retrieved.

linkReturns

A 200 OK response will be returned along with a token object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/tokens/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "tokens/6a7562be-b302-43d2-a550-30d6026247aa",
  Method.GET
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/tokens/6a7562be-b302-43d2-a550-30d6026247aa");
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "6a7562be-b302-43d2-a550-30d6026247aa",
    "type": "tokens",
    "attributes": {
      "expiry": "<%= expiry %>",
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "bearer": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298"
        },
        "data": {
          "type": "users",
          "id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298"
        }
      }
    }
  }
}

linkRegenerate a token

Regenerate an existing token resource. This will replace the token attribute with a new secure token, and extend the expiry by 2 weeks.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin or the token owner.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, optional

    The identifier (UUID) of the token to be regenerated. If ommited, the token used to authenticate will be regenerated.

linkReturns

A 200 OK response will be returned along with the regenerated token object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/tokens/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa", {
  method: "PUT",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa",
  method: .put,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "tokens/6a7562be-b302-43d2-a550-30d6026247aa",
  Method.PUT
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.put("https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.put("https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/tokens/6a7562be-b302-43d2-a550-30d6026247aa");
req.set_method(methods::PUT);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X PUT https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "6a7562be-b302-43d2-a550-30d6026247aa",
    "type": "tokens",
    "attributes": {
      "token": "9bc31b8d19a94d82a15742678d8f2540.6a7562beb30243d2a55030d6026247aa.0e00ffa203dcc6871c010c7d85ce13556c7ff70abcc0df4287b40dab8ade4a5fc4d4eb7bf1ccdef2dc892ad21bb57c451191c3061296c417eaf590d6ae640bv1",
      "expiry": "<%= expiry %>",
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "bearer": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298"
        },
        "data": {
          "type": "users",
          "id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298"
        }
      }
    }
  }
}

linkRevoke a token

Permanently revokes a token. It cannot be undone. This action also immediately invalidates all sessions using the given token.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin or the token owner.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the token to be revoked.

linkReturns

A 204 No Content response will be returned.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/tokens/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa", {
  method: "DELETE",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa",
  method: .delete,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let status = response.response?.statusCode
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "tokens/6a7562be-b302-43d2-a550-30d6026247aa",
  Method.DELETE
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/tokens/6a7562be-b302-43d2-a550-30d6026247aa");
req.set_method(methods::DELETE);

client.request(req)
  .then([](http_response res) {
    auto status = res.status_code();
  })
  .wait();
curl -X DELETE https://api.keygen.sh/v1/accounts/<%= account %>/tokens/6a7562be-b302-43d2-a550-30d6026247aa \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 204 No Content

No content

linkList all tokens

Returns a list of tokens. The tokens are returned sorted by creation date, with the most recent tokens appearing first. Resources are automatically scoped to the authenticated bearer e.g. when authenticated as a product, only tokens that belong to the specific product will be listed.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resources.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkFilters

  • linklimit

    integer, default is10

    A limit on the number of tokens to be returned. Limit must be a number between 1 and 100.

    https://api.keygen.sh/v1/accounts/<%= account %>/tokens?limit=25
  • linkpage

    hash<string, integer>

    Hash containing page size and page number. Page size must be a number between 1 and 100

    https://api.keygen.sh/v1/accounts/<%= account %>/tokens?page[size]=15&page[number]=2

linkReturns

A 200 OK response will be returned along with a list of token objects.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/tokens{FILTERS}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/tokens?limit=15", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/tokens?limit=15",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("tokens", Method.GET);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddParameter("limit", 15);

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/tokens")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/tokens")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

uri_builder uri("/tokens");
uri.append_query("limit", 15);

req.set_request_uri(uri.to_uri());
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/tokens?limit=15 -g \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": [
    {
      "id": "6a7562be-b302-43d2-a550-30d6026247aa",
      "type": "tokens",
      "attributes": {
        "expiry": "<%= expiry %>",
        "created": "<%= created %>",
        "updated": "<%= created %>"
      },
      "relationships": {
        "account": {
          "links": {
            "related": "/v1/accounts/<%= account %>"
          },
          "data": {
            "type": "accounts",
            "id": "<%= account %>"
          }
        },
        "bearer": {
          "links": {
            "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298"
          },
          "data": {
            "type": "users",
            "id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298"
          }
        }
      }
    },
    …
  ]
}

linkProducts

linkThe product object

Below you will find the various attributes for the product resource, as well as the product resource's relationships.

linkAttributes

  • linkname

    string

    The name of the product.

  • linkurl

    string

    A related URL for the product e.g. the marketing website, company website, etc.

  • linkplatforms

    array<string>

    An array of platforms the product supports.

  • linkmetadata

    hash<string, scalar>

    Hash containing product metadata.

  • linkcreated

    timestampread only

    When the product was created.

  • linkupdated

    timestampread only

    When the product was last updated.

linkRelationships

  • linkaccount

    individual

    The account that the product belongs to.

  • linkpolicies

    collection

    The policies that are associated with the product.

  • linklicenses

    collection

    The licenses that are associated with the product.

  • linkmachines

    collection

    The machines that are associated with the product.

  • linkusers

    collection

    The users that own a license for the product.

  • linktokens

    collection

    The authentication tokens of the product.

Example object

{
  "data": {
    "id": "31339351-f7f5-4bdd-8346-5d8399a1ac07",
    "type": "products",
    "links": {
      "self": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07"
    },
    "attributes": {
      "name": "Product Hunt",
      "url": "https://producthunt.com",
      "platforms": ["iOS", "Android"],
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "policies": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/policies"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/licenses"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/machines"
        }
      },
      "users": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/users"
        }
      },
      "tokens": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/tokens"
        }
      }
    }
  }
}

linkCreate a product

Creates a new product resource.

linkAuthentication

  • linkBearer

    required

    An authentication token with admin privileges.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkAttributes

  • linkname

    string, required

    The name of the product.

  • linkurl

    string, optional

    A related URL for the product e.g. the marketing website, company website, etc. Must be a valid URL.

  • linkplatforms

    array<string>, optional

    An array of platforms the product supports.

  • linkmetadata

    hash<string, scalar>, optional

    Hash containing product metadata.

linkReturns

A 201 Created response will be returned along with the new product object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/products

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/products", {
  method: "POST",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "data": {
      "type": "products",
      "attributes": {
        "name": "Product Hunt",
        "url": "https://producthunt.com",
        "platforms": ["iOS", "Android"]
      }
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/products",
  method: .post,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "data": [
      "type": "products",
      "attributes": [
        "name": "Product Hunt",
        "url": "https://producthunt.com",
        "platforms": ["iOS", "Android"]
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("products", Method.POST);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  data = new {
    type = "products",
    attributes = new {
      name = "Product Hunt",
      url = "https://producthunt.com",
      platforms = new[] { "iOS", "Android" }
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "products",
    "attributes" to mapOf(
      "name" to "Product Hunt",
      "url" to "https://producthunt.com",
      "platforms" to listOf("iOS", "Android")
    )
  )
))

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/products")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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;
import static java.util.List.of;

JSONObject body = new JSONObject(ofEntries(
  entry("data", ofEntries(
    entry("type", "products"),
    entry("attributes", ofEntries(
      entry("name", "Product Hunt"),
      entry("url", "https://producthunt.com"),
      entry("platforms", of("iOS", "Android"))
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/products")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value platforms;
platforms[0] = value::string("iOS");
platforms[1] = value::string("Android");

value attrs;
attrs["name"] = value::string("Product Hunt");
attrs["url"] = value::string("https://producthunt.com");
attrs["platforms"] = platforms;

value data;
data["type"] = value::string("products");
data["attributes"] = attrs;

value body;
body["data"] = data;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/products");
req.set_method(methods::POST);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/products \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "data": {
          "type": "products",
          "attributes": {
            "name": "Product Hunt",
            "url": "https://producthunt.com",
            "platforms": ["iOS", "Android"]
          }
        }
      }'

Example response / 201 Created

{
  "data": {
    "id": "31339351-f7f5-4bdd-8346-5d8399a1ac07",
    "type": "products",
    "links": {
      "self": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07"
    },
    "attributes": {
      "name": "Product Hunt",
      "url": "https://producthunt.com",
      "platforms": ["iOS", "Android"],
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "policies": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/policies"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/licenses"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/machines"
        }
      },
      "users": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/users"
        }
      },
      "tokens": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/tokens"
        }
      }
    }
  }
}

linkRetrieve a product

Retrieves the details of an existing product.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resource: either an admin or the product.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the product to be retrieved.

linkReturns

A 200 OK response will be returned along with a product object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/products/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "products/31339351-f7f5-4bdd-8346-5d8399a1ac07",
  Method.GET
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/products/31339351-f7f5-4bdd-8346-5d8399a1ac07");
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07 \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "31339351-f7f5-4bdd-8346-5d8399a1ac07",
    "type": "products",
    "links": {
      "self": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07"
    },
    "attributes": {
      "name": "Product Hunt",
      "url": "https://producthunt.com",
      "platforms": ["iOS", "Android"],
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "policies": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/policies"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/licenses"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/machines"
        }
      },
      "users": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/users"
        }
      },
      "tokens": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/tokens"
        }
      }
    }
  }
}

linkUpdate a product

Updates the specified product resource by setting the values of the parameters passed. Any parameters not provided will be left unchanged.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin or the product.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the product to be updated.

linkAttributes

  • linkname

    string, optional

    The name of the product.

  • linkurl

    string, optional

    A related URL for the product e.g. the marketing website, company website, etc. Must be a valid URL.

  • linkplatforms

    array<string>, optional

    An array of platforms the product supports.

  • linkmetadata

    hash<string, scalar>, optional

    Hash containing product metadata.

linkReturns

A 200 OK response will be returned along with the updated product object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/products/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07", {
  method: "PATCH",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "data": {
      "type": "products",
      "attributes": {
        "platforms": [
          "iOS",
          "Android",
          "Windows"
        ]
      }
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07",
  method: .patch,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "data": [
      "type": "products",
      "attributes": [
        "platforms": [
          "iOS",
          "Android",
          "Windows"
        ]
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "products/31339351-f7f5-4bdd-8346-5d8399a1ac07",
  Method.PATCH
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  data = new {
    type = "products",
    attributes = new {
      platforms = new[] { "iOS", "Android", "Windows" }
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "products",
    "attributes" to mapOf(
      "platforms" to listOf("iOS", "Android", "Windows")
    )
  )
))

val res = Unirest.patch("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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;
import static java.util.List.of;

JSONObject body = new JSONObject(ofEntries(
  entry("data", ofEntries(
    entry("type", "products"),
    entry("attributes", ofEntries(
      entry("platforms", of("iOS", "Android", "Windows"))
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.patch("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value platforms;
platforms[0] = value::string("iOS");
platforms[1] = value::string("Android");
platforms[2] = value::string("Windows");

value attrs;
attrs["platforms"] = platforms;

value data;
data["type"] = value::string("products");
data["attributes"] = attrs;

value body;
body["data"] = data;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/products/31339351-f7f5-4bdd-8346-5d8399a1ac07");
req.set_method(methods::PATCH);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X PATCH https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07 \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "data": {
          "type": "products",
          "attributes": {
            "platforms": [
              "iOS",
              "Android",
              "Windows"
            ]
          }
        }
      }'

Example response / 200 OK

{
  "data": {
    "id": "31339351-f7f5-4bdd-8346-5d8399a1ac07",
    "type": "products",
    "links": {
      "self": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07"
    },
    "attributes": {
      "name": "Product Hunt",
      "url": "https://producthunt.com",
      "platforms": ["iOS", "Android", "Windows"],
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "policies": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/policies"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/licenses"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/machines"
        }
      },
      "users": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/users"
        }
      },
      "tokens": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/tokens"
        }
      }
    }
  }
}

linkDelete a product

Permanently deletes a product. It cannot be undone. This action also immediately deletes any policies, licenses and machines that the product is associated with.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin or the product.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the product to be deleted.

linkReturns

A 204 No Content response will be returned.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/products/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07", {
  method: "DELETE",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07",
  method: .delete,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let status = response.response?.statusCode
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "products/31339351-f7f5-4bdd-8346-5d8399a1ac07",
  Method.DELETE
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/products/31339351-f7f5-4bdd-8346-5d8399a1ac07");
req.set_method(methods::DELETE);

client.request(req)
  .then([](http_response res) {
    auto status = res.status_code();
  })
  .wait();
curl -X DELETE https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07 \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 204 No Content

No content

linkList all products

Returns a list of products. The products are returned sorted by creation date, with the most recent products appearing first.

linkAuthentication

  • linkBearer

    required

    An authentication token with admin privileges.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkFilters

  • linklimit

    integer, default is10

    A limit on the number of products to be returned. Limit must be a number between 1 and 100.

    https://api.keygen.sh/v1/accounts/<%= account %>/products?limit=25
  • linkpage

    hash<string, integer>

    Hash containing page size and page number. Page size must be a number between 1 and 100

    https://api.keygen.sh/v1/accounts/<%= account %>/products?page[size]=15&page[number]=2

linkReturns

A 200 OK response will be returned along with a list of product objects.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/products{FILTERS}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/products?limit=15", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/products?limit=15",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("products", Method.GET);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddParameter("limit", 15);

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/products")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/products")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

uri_builder uri("/products");
uri.append_query("limit", 15);

req.set_request_uri(uri.to_uri());
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/products?limit=15 -g \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": [
    {
      "id": "31339351-f7f5-4bdd-8346-5d8399a1ac07",
      "type": "products",
      "links": {
        "self": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07"
      },
      "attributes": {
        "name": "Product Hunt",
        "url": "https://producthunt.com",
        "platforms": ["iOS", "Android"],
        "metadata": {},
        "created": "<%= created %>",
        "updated": "<%= created %>"
      },
      "relationships": {
        "account": {
          "links": {
            "related": "/v1/accounts/<%= account %>"
          },
          "data": {
            "type": "accounts",
            "id": "<%= account %>"
          }
        },
        "policies": {
          "links": {
            "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/policies"
          }
        },
        "licenses": {
          "links": {
            "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/licenses"
          }
        },
        "machines": {
          "links": {
            "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/machines"
          }
        },
        "users": {
          "links": {
            "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/users"
          }
        },
        "tokens": {
          "links": {
            "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/tokens"
          }
        }
      }
    },
    …
  ]
}

linkGenerate a product token

Generates a new product token resource. Product tokens do not expire.

Product tokens should not be included in any client-facing code, as they offer full access to all of the product's resources. Only use these tokens server-side e.g. to consume webhooks or to create new resources in response to events from your payment provider.

linkAuthentication

  • linkBearer

    required

    An authentication token with admin privileges.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the product to generate a token for.

linkReturns

A 201 Created response will be returned along with the new token object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/products/{ID}/tokens

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/tokens", {
  method: "POST",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/tokens",
  method: .post,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "products/31339351-f7f5-4bdd-8346-5d8399a1ac07/tokens",
  Method.POST
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/tokens")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/tokens")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/tokens");
req.set_method(methods::POST);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07/tokens \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 201 Created

{
  "data": {
    "id": "07d52aa8-b96c-4b55-b05d-f5f570e1775a",
    "type": "tokens",
    "attributes": {
      "token": "cbe10f1ab9da4580bf5428cd7c1161f0.07d52aa8b96c4b55b05df5f570e1775a.4TzUcN9xMV2cUVT3AuDbPx8XWXnDRF4TzUcN9xMV2cUVT3AuDbPx8XWXnDRFnReibxxgBxXaY2gpb7DRDkUmZpyYi2sXzYfyVL4buWtbgyFD9zbd1319f14b90de1cv1",
      "expiry": "<%= expiry %>",
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "bearer": {
        "links": {
          "related": "/v1/accounts/<%= account %>/products/31339351-f7f5-4bdd-8346-5d8399a1ac07"
        },
        "data": {
          "type": "products",
          "id": "31339351-f7f5-4bdd-8346-5d8399a1ac07"
        }
      }
    }
  }
}

linkPolicies

linkThe policy object

Below you will find the various attributes for the policy resource, as well as the policy resource's relationships. Your policies define the different types of licenses that a given product offers.

linkAttributes

  • linkname

    string

    The name of the policy.

  • linkduration

    integer

    The duration for the policy in seconds. When a license implements the policy, the license's expiry is calculated with this value. If null, licenses will never expire.

  • linkstrict

    boolean, default isfalse

    When enabled, a license that implements the policy will be considered invalid if its machine limit is surpassed. In addition, strict requires a license to have at least 1 machine associated with it in order to pass validation.

  • linkfloating

    boolean, default isfalse

    When enabled, a license that implements the policy will be valid across multiple machines. Though this is not enforced i.e. it does not invalidate a license if it's associated with more than 1 machine unless the policy is strict.

  • linkconcurrent

    boolean, default istrue

    Whether or not to allow the activation of additional machines after a given license has reached its "max machines" limit, i.e. machine overages. This allows a "concurrent" licensing model, where you allow a set number of machines to be activated at one time, and exceeding that limit may invalidate all current sessions. When this is disabled and a user attempts to exceed the policy's machine limit, an error response will be returned. For example, when enabled, a license with a machine limit of 3 may exceed that limit by adding 4 or more machines, though the license may then become invalid if the policy is also "strict."

  • linkrequireProductScope

    boolean, default isfalse

    When enabled, validating a license that implements the policy will require a product scope that matches the licenses's product relationship by its identifier (UUID).

  • linkrequirePolicyScope

    boolean, default isfalse

    When enabled, validating a license that implements the policy will require a policy scope that matches the licenses's policy relationship by its identifier (UUID).

  • linkrequireMachineScope

    boolean, default isfalse

    When enabled, validating a license that implements the policy will require a machine scope that matches at least 1 of the licenses's machine relationships by its identifier (UUID).

  • linkrequireFingerprintScope

    boolean, default isfalse

    When enabled, validating a license that implements the policy will require a fingerprint scope that matches at least 1 of the licenses's machine relationships by its fingerprint.

  • linkrequireCheckIn

    boolean, default isfalse

    When enabled, a license that implements the policy will require check-in at a predefined interval to continue to pass validation i.e. if a license misses a check-in, it will be invalidated.

  • linkcheckInInterval

    string

    One of day, week, month or year. The frequency at which a license should check-in.

  • linkcheckInIntervalCount

    integer

    The number of intervals (specified in the check-in interval property) between each required check-in. For example, checkInInterval=week and checkInIntervalCount=2 requires check-in every 2 weeks. Must be a number between 1 and 365 inclusive.

  • linkusePool

    boolean, default isfalse

    Whether or not to pull license keys from a finite pool of pre-determined keys. This is useful for invite-only programs such as a private beta, when you need a limited set of licenses, or when you want to define the keys manually. This cannot be changed later on.

  • linkmaxMachines

    integer

    The maximum number of machines a license implementing the policy can have associated with it. This is only enforced when the policy is strict. When null, an unlimited number of machines may be associated with a license if the policy is floating. Must be a number greater than 0, and must be equal to 1 for non-floating policies.

  • linkmaxUses

    integer

    The maximum number of uses a license implementing the policy can have. When null, a license which implements the policy can have an unlimited number of uses. This attribute is not taken into account during license validation. See the license's usage-related actions for more details.

  • linkprotected

    boolean, default isinherited

    Whether or not the policy is protected. A protected policy disallows users the ability to create and manage licenses themselves, useful in situations where Keygen is only managed server-side or when you aren't listening for the appropriate user-initiated webhook events. If the account is protected, all policies automatically inherit that value when left blank.

  • linkmetadata

    hash<string, scalar>

    Hash containing policy metadata.

  • linkcreated

    timestampread only

    When the policy was created.

  • linkupdated

    timestampread only

    When the policy was last updated.

linkRelationships

  • linkaccount

    individual

    The account that the policy belongs to.

  • linkproduct

    individual

    The product that the policy is associated with.

  • linkpool

    collection

    The pool of pre-determined keys for the policy.

  • linklicenses

    collection

    The licenses that implement the policy.

Example object

{
  "data": {
    "id": "0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
    "type": "policies",
    "links": {
      "self": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065"
    },
    "attributes": {
      "name": "Premium Add-On",
      "duration": 1209600,
      "strict": false,
      "floating": true,
      "concurrent": true,
      "requireProductScope": false,
      "requirePolicyScope": false,
      "requireMachineScope": false,
      "requireFingerprintScope": false,
      "requireCheckIn": false,
      "checkInInterval": null,
      "checkInIntervalCount": null,
      "usePool": false,
      "maxMachines": 5,
      "maxUses": null,
      "encrypted": false,
      "protected": false,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/product"
        },
        "data": {
          "type": "products",
          "id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4"
        }
      },
      "pool": {
        "links": {
          "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/pool"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/licenses"
        }
      }
    }
  }
}

linkCreate a policy

Creates a new policy resource.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkAttributes

  • linkname

    string, required

    The name of the policy.

  • linkduration

    integer, optional

    The duration for the policy in seconds. When a license implements the policy, the license's expiry is calculated with this value. If null, licenses will never expire.

  • linkstrict

    boolean, optional

    When enabled, a license that implements the policy will be considered invalid if its machine limit is surpassed. In addition, strict requires a license to have at least 1 machine associated with it in order to pass validation.

  • linkfloating

    boolean, optional

    When enabled, a license that implements the policy will be valid across multiple machines. Though this is not enforced i.e. it does not invalidate a license if it's associated with more than 1 machine unless the policy is strict.

  • linkconcurrent

    boolean, optional

    Whether or not to allow the activation of additional machines after a given license has reached its "max machines" limit, i.e. machine overages. This allows a "concurrent" licensing model, where you allow a set number of machines to be activated at one time, and exceeding that limit may invalidate all current sessions. When this is disabled and a user attempts to exceed the policy's machine limit, an error response will be returned. For example, when enabled, a license with a machine limit of 3 may exceed that limit by adding 4 or more machines, though the license may then become invalid if the policy is also "strict."

  • linkrequireProductScope

    boolean, optional

    When enabled, validating a license that implements the policy will require a product scope that matches the licenses's product relationship by its identifier (UUID).

  • linkrequirePolicyScope

    boolean, optional

    When enabled, validating a license that implements the policy will require a policy scope that matches the licenses's policy relationship by its identifier (UUID).

  • linkrequireMachineScope

    boolean, optional

    When enabled, validating a license that implements the policy will require a machine scope that matches at least 1 of the licenses's machine relationships by its identifier (UUID).

  • linkrequireFingerprintScope

    boolean, optional

    When enabled, validating a license that implements the policy will require a fingerprint scope that matches at least 1 of the licenses's machine relationships by its fingerprint.

  • linkrequireCheckIn

    boolean, optional

    When enabled, a license that implements the policy will require check-in at a predefined interval to continue to pass validation i.e. if a license misses a check-in, it will be invalidated.

  • linkcheckInInterval

    string, optional

    One of day, week, month or year. The frequency at which a license should check-in.

  • linkcheckInIntervalCount

    integer, optional

    The number of intervals (specified in the check-in interval property) between each required check-in. For example, checkInInterval=week and checkInIntervalCount=2 requires check-in every 2 weeks. Must be a number between 1 and 365 inclusive.

  • linkusePool

    boolean, optional

    Whether or not to pull license keys from a finite pool of pre-determined keys. This is useful for invite-only programs such as a private beta, when you need a limited set of licenses, or when you want to define the keys manually. This cannot be changed later on.

  • linkmaxMachines

    integer, optional

    The maximum number of machines a license implementing the policy can have associated with it. This is only enforced when the policy is strict. When null, an unlimited number of machines may be associated with a license if the policy is floating. Must be a number greater than 0, and must be equal to 1 for non-floating policies.

  • linkmaxUses

    integer, optional

    The maximum number of uses a license implementing the policy can have. When null, a license which implements the policy can have an unlimited number of uses. This attribute is not taken into account during license validation. See the license's usage-related actions for more details.

  • linkprotected

    boolean, optional

    Whether or not the policy is protected. A protected policy disallows users the ability to create and manage licenses themselves, useful in situations where Keygen is only managed server-side or when you aren't listening for the appropriate user-initiated webhook events. If the account is protected, all policies automatically inherit that value when left blank.

  • linkmetadata

    hash<string, scalar>, optional

    Hash containing policy metadata.

linkRelationships

  • linkproduct

    linkage, required

    The product the policy is for.

linkReturns

A 201 Created response will be returned along with the new policy object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/policies

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/policies", {
  method: "POST",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "data": {
      "type": "policies",
      "attributes": {
        "name": "Basic"
      },
      "relationships": {
        "product": {
          "data": { "type": "product", "id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4" }
        }
      }
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/policies",
  method: .post,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "data": [
      "type": "policies",
      "attributes": [
        "name": "Basic"
      ],
      "relationships": [
        "product": [
          "data": ["type": "product", "id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4"]
        ]
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("policies", Method.POST);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  data = new {
    type = "policies",
    attributes = new {
      name = "Basic"
    },
    relationships = new {
      product = new {
        data = new { type = "product", id = "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4" }
      }
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "policies",
    "attributes" to mapOf(
      "name" to "Basic"
    ),
    "relationships" to mapOf(
      "product" to mapOf(
        "data" to mapOf(
          "type" to "products",
          "id" to "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4"
        )
      )
    )
  )
))

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/policies")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("data", ofEntries(
    entry("type", "policies"),
    entry("attributes", ofEntries(
      entry("name", "Basic")
    )),
    entry("relationships", ofEntries(
      entry("product", ofEntries(
        entry("data", ofEntries(
          entry("type", "products"),
          entry("id", "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4")
        ))
      ))
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/policies")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value attrs;
attrs["name"] = value::string("Basic");

value product_;
product_["type"] = value::string("products");
product_["id"] = value::string("3ab38aae-bbf7-4846-9c32-af9d94bf5ad4");

value product;
product["data"] = product_;

value rels;
rels["product"] = product;

value data;
data["type"] = value::string("policies");
data["attributes"] = attrs;
data["relationships"] = rels;

value body;
body["data"] = data;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/policies");
req.set_method(methods::POST);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/policies \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "data": {
          "type": "policies",
          "attributes": {
            "name": "Basic"
          },
          "relationships": {
            "product": {
              "data": { "type": "product", "id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4" }
            }
          }
        }
      }'

Example response / 201 Created

{
  "data": {
    "id": "0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
    "type": "policies",
    "links": {
      "self": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065"
    },
    "attributes": {
      "name": "Basic",
      "duration": null,
      "strict": false,
      "floating": false,
      "concurrent": true,
      "requireProductScope": false,
      "requirePolicyScope": false,
      "requireMachineScope": false,
      "requireFingerprintScope": false,
      "requireCheckIn": false,
      "checkInInterval": null,
      "checkInIntervalCount": null,
      "usePool": false,
      "maxMachines": 1,
      "maxUses": null,
      "encrypted": false,
      "protected": false,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/product"
        },
        "data": {
          "type": "products",
          "id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4"
        }
      },
      "pool": {
        "links": {
          "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/pool"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/licenses"
        }
      }
    }
  }
}

linkRetrieve a policy

Retrieves the details of an existing policy.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resource: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the policy to be retrieved.

linkReturns

A 200 OK response will be returned along with a policy object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/policies/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
  Method.GET
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065");
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065 \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
    "type": "policies",
    "links": {
      "self": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065"
    },
    "attributes": {
      "name": "Premium Add-On",
      "duration": 1209600,
      "strict": false,
      "floating": true,
      "concurrent": true,
      "requireProductScope": false,
      "requirePolicyScope": false,
      "requireMachineScope": false,
      "requireFingerprintScope": false,
      "requireCheckIn": false,
      "checkInInterval": null,
      "checkInIntervalCount": null,
      "usePool": false,
      "maxMachines": 5,
      "maxUses": null,
      "encrypted": false,
      "protected": false,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/product"
        },
        "data": {
          "type": "products",
          "id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4"
        }
      },
      "pool": {
        "links": {
          "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/pool"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/licenses"
        }
      }
    }
  }
}

linkUpdate a policy

Updates the specified policy resource by setting the values of the parameters passed. Any parameters not provided will be left unchanged.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the policy to be updated.

linkAttributes

  • linkname

    string, optional

    The name of the policy.

  • linkduration

    integer, optional

    The duration for the policy in seconds. When a license implements the policy, the license's expiry is calculated with this value. If null, licenses will never expire.

  • linkstrict

    boolean, optional

    When enabled, a license that implements the policy will be considered invalid if its machine limit is surpassed. In addition, strict requires a license to have at least 1 machine associated with it in order to pass validation.

  • linkfloating

    boolean, optional

    When enabled, a license that implements the policy will be valid across multiple machines. Though this is not enforced i.e. it does not invalidate a license if it's associated with more than 1 machine unless the policy is strict.

  • linkconcurrent

    boolean, optional

    Whether or not to allow the activation of additional machines after a given license has reached its "max machines" limit, i.e. machine overages. This allows a "concurrent" licensing model, where you allow a set number of machines to be activated at one time, and exceeding that limit may invalidate all current sessions. When this is disabled and a user attempts to exceed the policy's machine limit, an error response will be returned. For example, when enabled, a license with a machine limit of 3 may exceed that limit by adding 4 or more machines, though the license may then become invalid if the policy is also "strict."

  • linkrequireProductScope

    boolean, optional

    When enabled, validating a license that implements the policy will require a product scope that matches the licenses's product relationship by its identifier (UUID).

  • linkrequirePolicyScope

    boolean, optional

    When enabled, validating a license that implements the policy will require a policy scope that matches the licenses's policy relationship by its identifier (UUID).

  • linkrequireMachineScope

    boolean, optional

    When enabled, validating a license that implements the policy will require a machine scope that matches at least 1 of the licenses's machine relationships by its identifier (UUID).

  • linkrequireFingerprintScope

    boolean, optional

    When enabled, validating a license that implements the policy will require a fingerprint scope that matches at least 1 of the licenses's machine relationships by its fingerprint.

  • linkrequireCheckIn

    boolean, optional

    When enabled, a license that implements the policy will require check-in at a predefined interval to continue to pass validation i.e. if a license misses a check-in, it will be invalidated.

  • linkcheckInInterval

    string, optional

    One of day, week, month or year. The frequency at which a license should check-in.

  • linkcheckInIntervalCount

    integer, optional

    The number of intervals (specified in the check-in interval property) between each required check-in. For example, checkInInterval=week and checkInIntervalCount=2 requires check-in every 2 weeks. Must be a number between 1 and 365 inclusive.

  • linkmaxMachines

    integer, optional

    The maximum number of machines a license implementing the policy can have associated with it. This is only enforced when the policy is strict. When null, an unlimited number of machines may be associated with a license if the policy is floating. Must be a number greater than 0, and must be equal to 1 for non-floating policies.

  • linkmaxUses

    integer, optional

    The maximum number of uses a license implementing the policy can have. When null, a license which implements the policy can have an unlimited number of uses.

  • linkprotected

    boolean, optional

    Whether or not the policy is protected. A protected policy disallows users the ability to create licenses themselves, useful in situations where Keygen is only managed server-side.

  • linkmetadata

    hash<string, scalar>, optional

    Hash containing policy metadata.

linkReturns

A 200 OK response will be returned along with the updated policy object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/policies/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065", {
  method: "PATCH",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "data": {
      "type": "policies",
      "attributes": {
        "maxMachines": 15
      }
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
  method: .patch,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "data": [
      "type": "policies",
      "attributes": [
        "maxMachines": 15
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
  Method.PATCH
);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  data = new {
    type = "policies",
    attributes = new {
      maxMachines = 15
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "policies",
    "attributes" to mapOf(
      "maxMachines" to 15
    )
  )
))

val res = Unirest.patch("https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("data", ofEntries(
    entry("type", "policies"),
    entry("attributes", ofEntries(
      entry("maxMachines", 15)
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.patch("https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value attrs;
attrs["maxMachines"] = value::number(15);

value data;
data["type"] = value::string("policies");
data["attributes"] = attrs;

value body;
body["data"] = data;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065");
req.set_method(methods::PATCH);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X PATCH https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065 \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "data": {
          "type": "policies",
          "attributes": {
            "maxMachines": 15
          }
        }
      }'

Example response / 200 OK

{
  "data": {
    "id": "0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
    "type": "policies",
    "links": {
      "self": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065"
    },
    "attributes": {
      "name": "Premium Add-On",
      "duration": 1209600,
      "strict": false,
      "floating": true,
      "concurrent": true,
      "requireProductScope": false,
      "requirePolicyScope": false,
      "requireMachineScope": false,
      "requireFingerprintScope": false,
      "requireCheckIn": false,
      "checkInInterval": null,
      "checkInIntervalCount": null,
      "usePool": false,
      "maxMachines": 15,
      "maxUses": null,
      "encrypted": false,
      "protected": false,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/product"
        },
        "data": {
          "type": "products",
          "id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4"
        }
      },
      "pool": {
        "links": {
          "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/pool"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/licenses"
        }
      }
    }
  }
}

linkDelete a policy

Permanently deletes a policy. It cannot be undone. This action also immediately deletes any licenses that the policy is associated with.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the policy to be deleted.

linkReturns

A 204 No Content response will be returned.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/policies/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065", {
  method: "DELETE",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
  method: .delete,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let status = response.response?.statusCode
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
  Method.DELETE
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);

import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065");
req.set_method(methods::DELETE);

client.request(req)
  .then([](http_response res) {
    auto status = res.status_code();
  })
  .wait();
curl -X DELETE https://api.keygen.sh/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065 \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 204 No Content

No content

linkList all policies

Returns a list of policies. The policies are returned sorted by creation date, with the most recent policies appearing first. Resources are automatically scoped to the authenticated bearer e.g. when authenticated as a product, only policies of that specific product will be listed.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resources: either an admin or a product.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkFilters

  • linklimit

    integer, default is10

    A limit on the number of policies to be returned. Limit must be a number between 1 and 100.

    https://api.keygen.sh/v1/accounts/<%= account %>/policies?limit=25
  • linkpage

    hash<string, integer>

    Hash containing page size and page number. Page size must be a number between 1 and 100

    https://api.keygen.sh/v1/accounts/<%= account %>/policies?page[size]=15&page[number]=2
  • linkproduct

    string

    The identifier (UUID) of the product to filter by.

    https://api.keygen.sh/v1/accounts/<%= account %>/policies?product=3ab38aae-bbf7-4846-9c32-af9d94bf5ad4

linkReturns

A 200 OK response will be returned along with a list of policy objects.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/policies{FILTERS}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/policies?limit=15", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/policies?limit=15",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("policies", Method.GET);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddParameter("limit", 15);

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/policies")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/policies")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

uri_builder uri("/policies");
uri.append_query("limit", 15);

req.set_request_uri(uri.to_uri());
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/policies?limit=15 -g \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": [
    {
      "id": "0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
      "type": "policies",
      "links": {
        "self": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065"
      },
      "attributes": {
        "name": "Premium Add-On",
        "duration": 1209600,
        "strict": false,
        "floating": true,
        "concurrent": true,
        "requireProductScope": false,
        "requirePolicyScope": false,
        "requireMachineScope": false,
        "requireFingerprintScope": false,
        "requireCheckIn": false,
        "checkInInterval": null,
        "checkInIntervalCount": null,
        "usePool": false,
        "maxMachines": 5,
        "maxUses": null,
        "encrypted": false,
        "protected": false,
        "metadata": {},
        "created": "<%= created %>",
        "updated": "<%= created %>"
      },
      "relationships": {
        "account": {
          "links": {
            "related": "/v1/accounts/<%= account %>"
          },
          "data": {
            "type": "accounts",
            "id": "<%= account %>"
          }
        },
        "product": {
          "links": {
            "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/product"
          },
          "data": {
            "type": "products",
            "id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4"
          }
        },
        "pool": {
          "links": {
            "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/pool"
          }
        },
        "licenses": {
          "links": {
            "related": "/v1/accounts/<%= account %>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/licenses"
          }
        }
      }
    },
    …
  ]
}

linkPop key from pool

Pop off (delete) a key from the policy's pool of pre-determined keys. The returned key is only available directly after a pop, similar to authentication tokens. This cannot be undone.

This action does not create a license resource. What you do with the key after a pop is up to you e.g. create a license with it, discard it, etc. To pop a key and create a license in a single action, simply create a license that implements the pooled policy.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the policy to be retrieved.

linkReturns

A 200 OK response will be returned along with the popped key object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/policies/{ID}/pool

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool", {
  method: "DELETE",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool",
  method: .delete,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool",
  Method.DELETE
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);

import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool");
req.set_method(methods::DELETE);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X DELETE https://api.keygen.sh/v1/accounts/<%= account %>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "6331bcae-73c1-4a7e-bf02-bbf77cbb81d7",
    "type": "keys",
    "links": {
      "self": "/v1/accounts/<%= account %>/keys/6331bcae-73c1-4a7e-bf02-bbf77cbb81d7"
    },
    "attributes": {
      "key": "B8A5-91D7-CB9A-DAE4-4F6E-1128",
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool/product"
        },
        "data": {
          "type": "products",
          "id": "1f286fb6-c9bb-498b-a4e7-6c67748b1f4f"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool/policy"
        },
        "data": {
          "type": "policies",
          "id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298"
        }
      }
    }
  }
}

linkUsers

linkThe user object

Below you will find the various attributes for the user resource, as well as the user resource's relationships. To modify a relationship, you will need to use the canonical link for the given resource.

linkAttributes

  • linkfullName

    stringread only

    The full name of the user.

  • linkfirstName

    string

    The first name of the user.

  • linklastName

    string

    The last name of the user.

  • linkemail

    string

    The unique email of the user.

  • linkrole

    string

    The role of the user.

  • linkmetadata

    hash<string, scalar>

    Hash containing user metadata.

  • linkcreated

    timestampread only

    When the user was created.

  • linkupdated

    timestampread only

    When the user was last updated.

linkRelationships

  • linkaccount

    individual

    The account that the user belongs to.

  • linkproducts

    collection

    The products that the user is associated with.

  • linklicenses

    collection

    The licenses that the user owns.

  • linkmachines

    collection

    The machines that the user owns.

  • linktokens

    collection

    The authentication tokens of the user.

Example object

{
  "data": {
    "id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298",
    "type": "users",
    "attributes": {
      "fullName": "John Doe",
      "firstName": "John",
      "lastName": "Doe",
      "email": "[email protected]",
      "role": "user",
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "products": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/products"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/licenses"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/machines"
        }
      },
      "tokens": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/tokens"
        }
      }
    }
  }
}

linkCreate a user

Creates a new user resource.

Please note that user resources are shared between products—meaning, when your account has multiple products, your users are signing up for a user account for all of your products, not just a single product. Your registration verbiage should reflect that. They will be able to login across all of your products with a single user account, but are licensed per-product.

For example, a user signs up for a "Blizzard" account, not for a "World of Warcraft" account. And with their "Blizzard" account, they will be able to login and buy licenses for "World of Warcraft", "Overwatch", "Starcraft", and for other products which "Blizzard" provides.

linkAuthentication

  • linkNone

    When the account is unprotected, no authentication is required and anybody may create new a user.

  • linkBearer

    required

    When the account is protected, an authentication token with admin privileges or a product token is required.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkAttributes

  • linkfirstName

    string, required

    The first name of the user.

  • linklastName

    string, required

    The last name of the user.

  • linkemail

    string, required

    The unique email of the user.

  • linkpassword

    string, required

    The password for the user.

  • linkrole

    string, default isuserprotectedProtected attributes are only available for bearers with an admin or product role.

    The role of the user. Can be either user or admin.

  • linkmetadata

    hash<string, scalar>, optional

    Hash containing user metadata.

linkReturns

A 201 Created response will be returned along with the new user object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/users

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json"
  },
  body: JSON.stringify({
    "data": {
      "type": "users",
      "attributes": {
        "firstName": "John",
        "lastName": "Doe",
        "email": "[email protected]",
        "password": "secret"
      }
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/users",
  method: .post,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json"
  ],
  parameters: [
    "data": [
      "type": "users",
      "attributes": [
        "firstName": "John",
        "lastName": "Doe",
        "email": "[email protected]",
        "password": "secret"
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("users", Method.POST);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");

request.AddJsonBody(new {
  data = new {
    type = "users",
    attributes = new {
      firstName = "John",
      lastName = "Doe",
      email = "[email protected]",
      password = "secret"
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "users",
    "attributes" to mapOf(
      "firstName" to "John",
      "lastName" to "Doe",
      "email" to "[email protected]",
      "password" to "secret"
    )
  )
))

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/users")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("data", ofEntries(
    entry("type", "users"),
    entry("attributes", ofEntries(
      entry("firstName", "John"),
      entry("lastName", "Doe"),
      entry("email", "[email protected]"),
      entry("password", "secret")
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/users")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value attrs;
attrs["firstName"] = value::string("John");
attrs["lastName"] = value::string("Doe");
attrs["email"] = value::string("[email protected]");
attrs["password"] = value::string("secret");

value data;
data["type"] = value::string("users");
data["attributes"] = attrs;

value body;
body["data"] = data;

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

req.set_request_uri("/users");
req.set_method(methods::POST);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/users \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -d '{
        "data": {
          "type": "users",
          "attributes": {
            "firstName": "John",
            "lastName": "Doe",
            "email": "[email protected]",
            "password": "secret"
          }
        }
      }'

Example response / 201 Created

{
  "data": {
    "id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298",
    "type": "users",
    "attributes": {
      "fullName": "John Doe",
      "firstName": "John",
      "lastName": "Doe",
      "email": "[email protected]",
      "role": "user",
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "products": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/products"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/licenses"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/machines"
        }
      },
      "tokens": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/tokens"
        }
      }
    }
  }
}

linkRetrieve a user

Retrieves the details of an existing user.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin, the user, or a product.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) or email of the user to be retrieved.

linkReturns

A 200 OK response will be returned along with a user object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/users/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "users/a5a154d2-f026-40fa-bc8d-a7e3ca415298",
  Method.GET
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298");
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();

curl https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298 \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298",
    "type": "users",
    "attributes": {
      "fullName": "John Doe",
      "firstName": "John",
      "lastName": "Doe",
      "email": "[email protected]",
      "role": "user",
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "products": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/products"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/licenses"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/machines"
        }
      },
      "tokens": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/tokens"
        }
      }
    }
  }
}

linkUpdate a user

Updates the specified user resource by setting the values of the parameters passed. Any parameters not provided will be left unchanged.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin, the user, or a product.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the user to be updated.

linkAttributes

  • linkfirstName

    string, optional

    The first name of the user.

  • linklastName

    string, optional

    The last name of the user.

  • linkemail

    string, optional

    The unique email of the user.

  • linkrole

    stringprotectedProtected attributes are only available for bearers with an admin or product role.

    The role of the user. Can be either user or admin.

  • linkmetadata

    hash<string, scalar>, optionalprotectedProtected attributes are only available for bearers with an admin or product role.

    Hash containing user metadata.

linkReturns

A 200 OK response will be returned along with the updated user object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/users/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298", {
  method: "PATCH",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "data": {
      "type": "users",
      "attributes": {
        "metadata": {
          "nickname": "Jack"
        }
      }
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298",
  method: .patch,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "data": [
      "type": "users",
      "attributes": [
        "metadata": [
          "nickname": "Jack"
        ]
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "users/a5a154d2-f026-40fa-bc8d-a7e3ca415298",
  Method.PATCH
);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  data = new {
    type = "users",
    attributes = new {
      metadata = new {
        nickname = "Jack"
      }
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "users",
    "attributes" to mapOf(
      "metadata" to mapOf(
        "nickname" to "Jack"
      )
    )
  )
))

val res = Unirest.patch("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("data", ofEntries(
    entry("type", "users"),
    entry("attributes", ofEntries(
      entry("metadata", ofEntries(
        entry("nickname", "Jack")
      ))
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.patch("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value metadata;
metadata["nickname"] = value::string("Jack");

value attrs;
attrs["metadata"] = metadata;

value data;
data["type"] = value::string("users");
data["attributes"] = attrs;

value body;
body["data"] = data;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298");
req.set_method(methods::PATCH);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X PATCH https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298 \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "data": {
          "type": "users",
          "attributes": {
            "metadata": {
              "nickname": "Jack"
            }
          }
        }
      }'

Example response / 200 OK

{
  "data": {
    "id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298",
    "type": "users",
    "attributes": {
      "fullName": "John Doe",
      "firstName": "John",
      "lastName": "Doe",
      "email": "[email protected]",
      "role": "user",
      "metadata": {
        "nickname": "Jack"
      },
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "products": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/products"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/licenses"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/machines"
        }
      },
      "tokens": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/tokens"
        }
      }
    }
  }
}

linkDelete a user

Permanently deletes a user. It cannot be undone. This action also immediately deletes any licenses and machines that the user is associated with.

linkAuthentication

  • linkBearer

    required

    An authentication token with admin privileges.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the user to be deleted.

linkReturns

A 204 No Content response will be returned.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/users/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298", {
  method: "DELETE",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298",
  method: .delete,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let status = response.response?.statusCode
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "users/a5a154d2-f026-40fa-bc8d-a7e3ca415298",
  Method.DELETE
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298");
req.set_method(methods::DELETE);

client.request(req)
  .then([](http_response res) {
    auto status = res.status_code();
  })
  .wait();
curl -X DELETE https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298 \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 204 No Content

No content

linkList all users

Returns a list of users. The users are returned sorted by creation date, with the most recent users appearing first. Resources are automatically scoped to the authenticated bearer e.g. when authenticated as a product, only users of that specific product will be listed.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resources: either an admin or a product.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkFilters

  • linklimit

    integer, default is10

    A limit on the number of users to be returned. Limit must be a number between 1 and 100.

    https://api.keygen.sh/v1/accounts/<%= account %>/users?limit=25
  • linkpage

    hash<string, integer>

    Hash containing page size and page number. Page size must be a number between 1 and 100

    https://api.keygen.sh/v1/accounts/<%= account %>/users?page[size]=15&page[number]=2
  • linkproduct

    string

    The identifier (UUID) of the product to filter by.

    https://api.keygen.sh/v1/accounts/<%= account %>/users?product=c6772cd4-c89c-45fa-ab19-395087d79a2d
  • linkroles

    array, default isuser

    Array containing role names to filter by. The following roles are available: admin, user.

    https://api.keygen.sh/v1/accounts/<%= account %>/users?roles[]=admin&roles[]=user

linkReturns

A 200 OK response will be returned along with a list of user objects.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/users{FILTERS}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/users?limit=15", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/users?limit=15",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("users", Method.GET);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddParameter("list", 15);

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/users")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/users")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

uri_builder uri("/users");
uri.append_query("limit", 15);

req.set_request_uri(uri.to_uri());
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/users?limit=15 -g \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": [
    {
      "id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298",
      "type": "users",
      "attributes": {
        "fullName": "John Doe",
        "firstName": "John",
        "lastName": "Doe",
        "email": "[email protected]",
        "role": "user",
        "metadata": {},
        "created": "<%= created %>",
        "updated": "<%= created %>"
      },
      "relationships": {
        "account": {
          "links": {
            "related": "/v1/accounts/<%= account %>"
          },
          "data": {
            "type": "accounts",
            "id": "<%= account %>"
          }
        },
        "products": {
          "links": {
            "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/products"
          }
        },
        "licenses": {
          "links": {
            "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/licenses"
          }
        },
        "machines": {
          "links": {
            "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/machines"
          }
        },
        "tokens": {
          "links": {
            "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/tokens"
          }
        }
      }
    },
    …
  ]
}

linkUser actions

Actions for the user resource.

linkUpdate password

Action to update the user's password. A user's password can only be updated when authenticated as the given user.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: the user.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) or email of the user to be retrieved.

linkMeta

  • linkoldPassword

    string, required

    The current password for the user.

  • linknewPassword

    string, required

    The new password for the user.

linkReturns

A 200 OK response will be returned along with the updated user object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/users/{ID}/actions/update-password

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/actions/update-password", {
  method: "POST",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "meta": {
      "oldPassword": "password123",
      "newPassword": "Ep66YCGTD*kc=4AFotPf;[email protected]"
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/actions/update-password",
  method: .post,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "meta": [
      "oldPassword": "password123",
      "newPassword": "Ep66YCGTD*kc=4AFotPf;[email protected]"
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/actions/update-password",
  Method.POST
);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  meta = new {
    oldPassword = "password123",
    newPassword = "Ep66YCGTD*kc=4AFotPf;[email protected]"
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "meta" to mapOf(
    "oldPassword" to "password123",
    "newPassword" to "Ep66YCGTD*kc=4AFotPf;[email protected]"
  )
))

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/actions/update-password")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("oldPassword", "password123"),
    entry("newPassword", "Ep66YCGTD*kc=4AFotPf;[email protected]")
  ))
));

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/actions/update-password")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value meta;
meta["oldPassword"] = value::string("password123");
meta["newPassword"] = value::string("Ep66YCGTD*kc=4AFotPf;[email protected]");

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

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/actions/update-password");
req.set_method(methods::POST);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res) {
    auto status = res.status_code();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/actions/update-password \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "meta": {
          "oldPassword": "password123",
          "newPassword": "Ep66YCGTD*kc=4AFotPf;[email protected]"
        }
      }'

Example response / 200 OK

{
  "data": {
    "id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298",
    "type": "users",
    "attributes": {
      "fullName": "John Doe",
      "firstName": "John",
      "lastName": "Doe",
      "email": "[email protected]",
      "role": "user",
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "products": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/products"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/licenses"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/machines"
        }
      },
      "tokens": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/tokens"
        }
      }
    }
  }
}

linkReset password

Fulfill a user's password reset request. Password reset tokens expire 24 hours after requesting the reset.

linkAuthentication

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) or email of the user to be retrieved.

linkMeta

  • linkpasswordResetToken

    string, required

    The password reset token emailed to the user.

  • linknewPassword

    string, required

    The new password for the user.

linkReturns

A 200 OK response will be returned along with the updated user object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/users/{ID}/actions/reset-password

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/actions/reset-password", {
  method: "POST",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json"
  },
  body: JSON.stringify({
    "meta": {
      "passwordResetToken": "a9f93c31b41642248db99fc04f4e8482.a5a154d2f02640fabc8da7e3ca415298.96d846eb5cfa38e7282b8eb406926c23cb38edf73c9e15847ac8760427003f5612c6efb5a9005f162462079af2303b79b84d0e78b1aba4c72a7cef7c984d5fv1",
      "newPassword": "Ep66YCGTD*kc=4AFotPf;[email protected]"
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/actions/reset-password",
  method: .post,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json"
  ],
  parameters: [
    "meta": [
      "passwordResetToken": "a9f93c31b41642248db99fc04f4e8482.a5a154d2f02640fabc8da7e3ca415298.96d846eb5cfa38e7282b8eb406926c23cb38edf73c9e15847ac8760427003f5612c6efb5a9005f162462079af2303b79b84d0e78b1aba4c72a7cef7c984d5fv1",
      "newPassword": "Ep66YCGTD*kc=4AFotPf;[email protected]"
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/actions/reset-password",
  Method.POST
);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");

request.AddJsonBody(new {
  meta = new {
    passwordResetToken = "a9f93c31b41642248db99fc04f4e8482.a5a154d2f02640fabc8da7e3ca415298.96d846eb5cfa38e7282b8eb406926c23cb38edf73c9e15847ac8760427003f5612c6efb5a9005f162462079af2303b79b84d0e78b1aba4c72a7cef7c984d5fv1",
    newPassword = "Ep66YCGTD*kc=4AFotPf;[email protected]"
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "meta" to mapOf(
    "passwordResetToken" to "a9f93c31b41642248db99fc04f4e8482.a5a154d2f02640fabc8da7e3ca415298.96d846eb5cfa38e7282b8eb406926c23cb38edf73c9e15847ac8760427003f5612c6efb5a9005f162462079af2303b79b84d0e78b1aba4c72a7cef7c984d5fv1",
    "newPassword" to "Ep66YCGTD*kc=4AFotPf;[email protected]"
  )
))

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/actions/reset-password")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("passwordResetToken", "a9f93c31b41642248db99fc04f4e8482.a5a154d2f02640fabc8da7e3ca415298.96d846eb5cfa38e7282b8eb406926c23cb38edf73c9e15847ac8760427003f5612c6efb5a9005f162462079af2303b79b84d0e78b1aba4c72a7cef7c984d5fv1"),
    entry("newPassword", "Ep66YCGTD*kc=4AFotPf;[email protected]")
  ))
));

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/actions/reset-password")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value meta;
meta["passwordResetToken"] = value::string("a9f93c31b41642248db99fc04f4e8482.a5a154d2f02640fabc8da7e3ca415298.96d846eb5cfa38e7282b8eb406926c23cb38edf73c9e15847ac8760427003f5612c6efb5a9005f162462079af2303b79b84d0e78b1aba4c72a7cef7c984d5fv1");
meta["newPassword"] = value::string("Ep66YCGTD*kc=4AFotPf;[email protected]");

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

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/actions/reset-password");
req.set_method(methods::POST);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res) {
    auto status = res.status_code();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/actions/reset-password \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -d '{
        "meta": {
          "passwordResetToken": "a9f93c31b41642248db99fc04f4e8482.a5a154d2f02640fabc8da7e3ca415298.96d846eb5cfa38e7282b8eb406926c23cb38edf73c9e15847ac8760427003f5612c6efb5a9005f162462079af2303b79b84d0e78b1aba4c72a7cef7c984d5fv1",
          "newPassword": "Ep66YCGTD*kc=4AFotPf;[email protected]"
        }
      }'

Example response / 200 OK

{
  "data": {
    "id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298",
    "type": "users",
    "attributes": {
      "fullName": "John Doe",
      "firstName": "John",
      "lastName": "Doe",
      "email": "[email protected]",
      "role": "user",
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "products": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/products"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/licenses"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/machines"
        }
      },
      "tokens": {
        "links": {
          "related": "/v1/accounts/<%= account %>/users/a5a154d2-f026-40fa-bc8d-a7e3ca415298/tokens"
        }
      }
    }
  }
}

linkLicenses

linkThe license object

Below you will find the various attributes for the license resource, as well as the license resource's relationships. A license is an implementation of a product's policy.

linkAttributes

  • linkkey

    string, default isauto-generated

    A unique pre-determined key for the license. Cannot be used on encrypted licenses. This attribute will be automatically generated or popped from the remaining pool if left blank. For offline license key validation, you could manually specify a key generated from a public/private keypair.

  • linkexpiry

    timestamp

    When the license will expire.

  • linkuses

    integer, default is0

    The license's current usage count. This can be incremented, decremented, or reset using the license's usage-related actions.

  • linksuspended

    boolean

    Whether or not the license is suspended. A suspended license will always fail validation.

  • linkfloating

    booleanread only

    Whether or not the license is floating. This is inherited from the policy.

  • linkconcurrent

    booleanread only

    Whether or not the license is concurrent. This is inherited from the policy.

  • linkstrict

    booleanread only

    Whether or not the policy is strict. This is inherited from the policy.

  • linkmaxMachines

    integerread only

    The maximum number of machines the license can have associated with it. This is inherited from the policy.

  • linkmaxUses

    integerread only

    The maximum number of uses the license is allowed to have. This is inherited from the policy.

  • linkrequireCheckIn

    booleanread only

    Whether or not the license will require check-in at a predefined interval to continue to pass validation i.e. if a license misses a check-in, it will be invalidated. This is inherited from the policy.

  • linklastCheckIn

    timestampread only

    When the license was last checked-in. This is null if the policy does not require check-ins.

  • linknextCheckIn

    timestampread only

    The time at which the license is required to check-in by. This is null if the policy does not require check-ins.

  • linkmetadata

    hash<string, scalar>

    Hash containing license metadata.

  • linkcreated

    timestampread only

    When the license was created.

  • linkupdated

    timestampread only

    When the license was last updated.

linkRelationships

  • linkaccount

    individual

    The account that the license belongs to.

  • linkproduct

    individual

    The product that the license is associated with.

  • linkpolicy

    individual

    The policy that the license implements.

  • linkuser

    individual

    The user that owns the license.

  • linkmachines

    collection

    The machines that the license is associated with.

Example object

{
  "data": {
    "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
    },
    "attributes": {
      "key": "9581b92724204b63bb00d7652ef4b95b-b4fdedeb77a5dc2b57154ac881771867-1b6653b4a9f0ba7c7ce5f4d38430101a-84d547067f848e5ca6cdce667ccaf9v1",
      "expiry": "<%= expiry %>",
      "uses": 0,
      "suspended": false,
      "encrypted": false,
      "floating": false,
      "concurrent": true,
      "strict": false,
      "maxMachines": 5,
      "maxUses": null,
      "requireCheckIn": false,
      "lastCheckIn": null,
      "nextCheckIn": null,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "e8bf27c0-5f9c-4135-a65c-f52706c5fd4c"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/machines"
        }
      }
    }
  }
}

linkCreate a license

Creates a new license resource.

When creating a license for a pooled policy, the key will be taken from the remaining keys in the pool. If the pool is empty, an error will be returned until more keys are added to the pool.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin, the product it belongs to, or if the license's policy is unprotected, the user it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkAttributes

  • linkkey

    string, optional, default isauto-generated

    A unique pre-determined key for the license. Cannot be used on encrypted licenses. This attribute will be automatically generated or popped from the remaining pool if left blank. For offline license key validation, you could manually specify a key generated from a public/private keypair.

  • linksuspended

    boolean, optional, default isfalse

    Whether or not the license is suspended.

  • linkmetadata

    hash<string, scalar>, optional

    Hash containing license metadata.

linkRelationships

  • linkpolicy

    linkage, required

    The policy to implement for the license.

  • linkuser

    linkage, optional

    The user the license is for. If ommitted, the license will be user-less. This is useful if you're managing users within your own database. If authenticated as a user, this relationship is required and must be the authenticated user.

linkReturns

A 201 Created response will be returned along with the new license object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses", {
  method: "POST",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "data": {
      "type": "licenses",
      "relationships": {
        "policy": {
          "data": { "type": "policies", "id": "37b632f4-8e1e-4af9-8717-634765364628" }
        },
        "user": {
          "data": { "type": "users", "id": "015a33dd-3aca-43a9-8786-328042cce30a" }
        }
      }
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses",
  method: .post,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "data": [
      "type": "licenses",
      "relationships": [
        "policy": [
          "data": [ "type": "policies", "id": "37b632f4-8e1e-4af9-8717-634765364628" ]
        ],
        "user": [
          "data": [ "type": "users", "id": "015a33dd-3aca-43a9-8786-328042cce30a" ]
        ]
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("licenses", Method.POST);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  data = new {
    type = "licenses",
    relationships = new {
      policy = new {
        data = new { type = "policies", id = "37b632f4-8e1e-4af9-8717-634765364628" }
      },
      user = new {
        data = new { type = "users", id = "015a33dd-3aca-43a9-8786-328042cce30a" }
      }
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "licenses",
    "relationships" to mapOf(
      "policy" to mapOf(
        "data" to mapOf("type" to "policies", "id" to "37b632f4-8e1e-4af9-8717-634765364628")
      ),
      "user" to mapOf(
        "data" to mapOf("type" to "users", "id" to "015a33dd-3aca-43a9-8786-328042cce30a")
      )
    )
  )
))

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("data", ofEntries(
    entry("type", "licenses"),
    entry("relationships", ofEntries(
      entry("policy", ofEntries(
        entry("data", ofEntries(entry("type", "policies"), entry("id", "37b632f4-8e1e-4af9-8717-634765364628")))
      )),
      entry("user", ofEntries(
        entry("data", ofEntries(entry("type", "users"), entry("id", "015a33dd-3aca-43a9-8786-328042cce30a")))
      ))
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value policy_;
policy_["type"] = value::string("policies");
policy_["id"] = value::string("37b632f4-8e1e-4af9-8717-634765364628");

value policy;
policy["data"] = policy_;

value user_;
user_["type"] = value::string("users");
user_["id"] = value::string("015a33dd-3aca-43a9-8786-328042cce30a");

value user;
user["data"] = user_;

value rels;
rels["policy"] = policy;
rels["user"] = user;

value data;
data["type"] = value::string("licenses");
data["relationships"] = rels;

value body;
body["data"] = data;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

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

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/licenses \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "data": {
          "type": "licenses",
          "relationships": {
            "policy": {
              "data": { "type": "policies", "id": "37b632f4-8e1e-4af9-8717-634765364628" }
            },
            "user": {
              "data": { "type": "users", "id": "015a33dd-3aca-43a9-8786-328042cce30a" }
            }
          }
        }
      }'

Example response / 201 Created

{
  "data": {
    "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
    },
    "attributes": {
      "key": "024e1ec7440f43b0b1ecc51c40897931-9fc2bb9d3cbd3d207fb713227737b637-1788b9572a82ce14166227a8d4db5b6d-904064d3432be2ab0088d60d09fca7v1",
      "expiry": "<%= expiry %>",
      "uses": 0,
      "suspended": false,
      "encrypted": false,
      "floating": true,
      "concurrent": true,
      "strict": false,
      "maxMachines": 5,
      "maxUses": null,
      "requireCheckIn": false,
      "lastCheckIn": null,
      "nextCheckIn": null,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "37b632f4-8e1e-4af9-8717-634765364628"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "015a33dd-3aca-43a9-8786-328042cce30a"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines?license=b18e3f3a-330c-4d8d-ae2e-014db21fa827"
        }
      }
    }
  }
}

linkRetrieve a license

Retrieves the details of an existing license.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resource: either an admin, the product it belongs to, or the user it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) or key of the license to be retrieved. Cannot be an encrypted license key.

linkReturns

A 200 OK response will be returned along with a license object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/eef41cf5-f32e-4dab-a867-b9738d87285b", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/eef41cf5-f32e-4dab-a867-b9738d87285b",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "licenses/eef41cf5-f32e-4dab-a867-b9738d87285b",
  Method.GET
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/eef41cf5-f32e-4dab-a867-b9738d87285b")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/eef41cf5-f32e-4dab-a867-b9738d87285b")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/eef41cf5-f32e-4dab-a867-b9738d87285b");
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/licenses/eef41cf5-f32e-4dab-a867-b9738d87285b \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "eef41cf5-f32e-4dab-a867-b9738d87285b",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/eef41cf5-f32e-4dab-a867-b9738d87285b"
    },
    "attributes": {
      "key": "9581b92724204b63bb00d7652ef4b95b-b4fdedeb77a5dc2b57154ac881771867-1b6653b4a9f0ba7c7ce5f4d38430101a-84d547067f848e5ca6cdce667ccaf9v1",
      "expiry": "<%= expiry %>",
      "uses": 0,
      "suspended": false,
      "encrypted": false,
      "floating": false,
      "concurrent": true,
      "strict": false,
      "maxMachines": 5,
      "maxUses": null,
      "requireCheckIn": false,
      "lastCheckIn": null,
      "nextCheckIn": null,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "e8bf27c0-5f9c-4135-a65c-f52706c5fd4c"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines?license=eef41cf5-f32e-4dab-a867-b9738d87285b"
        }
      }
    }
  }
}

linkUpdate a license

Updates the specified license resource by setting the values of the parameters passed. Any parameters not provided will be left unchanged.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the license to be updated.

linkAttributes

  • linkexpiry

    timestamp, optionalprotectedProtected attributes are only available for bearers with an admin or product role.

    When the license will expire. Note: updating this attribute to an expiry in the past will not emit a license.expired webhook event.

  • linksuspended

    boolean, optionalprotectedProtected attributes are only available for bearers with an admin or product role.

    Whether or not the license is suspended. Note: updating this attribute directly will not emit a license.suspended webhook event.

  • linkmetadata

    hash<string, scalar>, optionalprotectedProtected attributes are only available for bearers with an admin or product role.

    Hash containing license metadata.

linkReturns

A 200 OK response will be returned along with the updated license object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827", {
  method: "PATCH",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "data": {
      "type": "licenses",
      "attributes": {
        "expiry": "2020-01-01T00:00:00.000Z"
      }
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827",
  method: .patch,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "data": [
      "type": "licenses",
      "attributes": [
        "expiry": "2020-01-01T00:00:00.000Z"
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827",
  Method.PATCH
);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  data = new {
    type = "licenses",
    attributes = new {
      expiry = "2020-01-01T00:00:00.000Z"
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "licenses",
    "attributes" to mapOf(
      "expiry" to "2020-01-01T00:00:00.000Z"
    )
  )
))

val res = Unirest.patch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("data", ofEntries(
    entry("type", "licenses"),
    entry("attributes", ofEntries(
      entry("expiry", "2020-01-01T00:00:00.000Z")
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.patch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value attrs;
attrs["expiry"] = value::string("2020-01-01T00:00:00.000Z");

value data;
data["type"] = value::string("licenses");
data["attributes"] = attrs;

value body;
body["data"] = data;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827");
req.set_method(methods::PATCH);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X PATCH https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827 \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "data": {
          "type": "licenses",
          "attributes": {
            "expiry": "2020-01-01T00:00:00.000Z"
          }
        }
      }'

Example response / 200 OK

{
  "data": {
    "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
    },
    "attributes": {
      "key": "024e1ec7440f43b0b1ecc51c40897931-9fc2bb9d3cbd3d207fb713227737b637-1788b9572a82ce14166227a8d4db5b6d-904064d3432be2ab0088d60d09fca7v1",
      "expiry": "2020-01-01T00:00:00.000Z",
      "uses": 0,
      "suspended": false,
      "encrypted": false,
      "floating": false,
      "concurrent": true,
      "strict": false,
      "maxMachines": 1,
      "maxUses": null,
      "requireCheckIn": false,
      "lastCheckIn": null,
      "nextCheckIn": null,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "e8bf27c0-5f9c-4135-a65c-f52706c5fd4c"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines?license=b18e3f3a-330c-4d8d-ae2e-014db21fa827"
        }
      }
    }
  }
}

linkDelete a license

Permanently deletes a license. It cannot be undone. This action also immediately deletes any machines that the license is associated with.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin, the product it belongs to, or if the license's policy is unprotected, the user it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the license to be deleted.

linkReturns

A 204 No Content response will be returned.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065", {
  method: "DELETE",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
  method: .delete,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
    let status = response.response?.statusCode
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "licenses/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
  Method.DELETE
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065");
req.set_method(methods::DELETE);

client.request(req)
  .then([](http_response res) {
    auto status = res.status_code();
  })
  .wait();
curl -X DELETE https://api.keygen.sh/v1/accounts/<%= account %>/licenses/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065 \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 204 No Content

No content

linkList all licenses

Returns a list of licenses. The licenses are returned sorted by creation date, with the most recent licenses appearing first. Resources are automatically scoped to the authenticated bearer e.g. when authenticated as a user, only licenses of that specific user will be listed.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resources.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkFilters

  • linklimit

    integer, default is10

    A limit on the number of licenses to be returned. Limit must be a number between 1 and 100.

    https://api.keygen.sh/v1/accounts/<%= account %>/licenses?limit=25
  • linkpage

    hash<string, integer>

    Hash containing page size and page number. Page size must be a number between 1 and 100

    https://api.keygen.sh/v1/accounts/<%= account %>/licenses?page[size]=15&page[number]=2
  • linksuspended

    boolean

    The suspended status of the license to filter by.

    https://api.keygen.sh/v1/accounts/<%= account %>/licenses?suspended=true
  • linkproduct

    string

    The identifier (UUID) of the product to filter by.

    https://api.keygen.sh/v1/accounts/<%= account %>/licenses?product=3ab38aae-bbf7-4846-9c32-af9d94bf5ad4
  • linkpolicy

    string

    The identifier (UUID) of the policy to filter by.

    https://api.keygen.sh/v1/accounts/<%= account %>/licenses?policy=0b4b1a9a-e25a-4f14-a95e-d9dd378d6065
  • linkuser

    string

    The identifier (UUID) of the user to filter by.

    https://api.keygen.sh/v1/accounts/<%= account %>/licenses?user=a5a154d2-f026-40fa-bc8d-a7e3ca415298
  • linkmachine

    string

    The identifier (UUID) of the machine to filter by.

    https://api.keygen.sh/v1/accounts/<%= account %>/licenses?machine=e4ab4f90-3203-48b3-bb33-a7377beb1d46

linkReturns

A 200 OK response will be returned along with a list of license objects.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses{FILTERS}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses?limit=15", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses?limit=15",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("licenses", Method.GET);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddParameter("limit", 15);

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/licenses")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/licenses")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

uri_builder uri("/licenses");
uri.append_query("limit", 15);

req.set_request_uri(uri.to_uri());
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/licenses?limit=15 -g \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": [
    {
      "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
      "type": "licenses",
      "links": {
        "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
      },
      "attributes": {
        "key": "024e1ec7440f43b0b1ecc51c40897931-9fc2bb9d3cbd3d207fb713227737b637-1788b9572a82ce14166227a8d4db5b6d-904064d3432be2ab0088d60d09fca7v1",
        "expiry": "<%= expiry %>",
        "uses": 0,
        "suspended": false,
        "encrypted": false,
        "floating": false,
        "concurrent": true,
        "strict": false,
        "maxMachines": 1,
        "maxUses": null,
        "requireCheckIn": false,
        "lastCheckIn": null,
        "nextCheckIn": null,
        "metadata": {},
        "created": "<%= created %>",
        "updated": "<%= created %>"
      },
      "relationships": {
        "account": {
          "links": {
            "related": "/v1/accounts/<%= account %>"
          },
          "data": {
            "type": "accounts",
            "id": "<%= account %>"
          }
        },
        "product": {
          "links": {
            "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
          },
          "data": {
            "type": "products",
            "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
          }
        },
        "policy": {
          "links": {
            "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
          },
          "data": {
            "type": "policies",
            "id": "37b632f4-8e1e-4af9-8717-634765364628"
          }
        },
        "user": {
          "links": {
            "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
          },
          "data": {
            "type": "users",
            "id": "015a33dd-3aca-43a9-8786-328042cce30a"
          }
        },
        "machines": {
          "links": {
            "related": "/v1/accounts/<%= account %>/machines?license=b18e3f3a-330c-4d8d-ae2e-014db21fa827"
          }
        }
      }
    },
    …
  ]
}

linkLicense actions

Actions for the license resource.

linkQuick validate license

Action to quickly validate a license. This will check the following: if the license is suspended, if the license is expired, if the license is overdue for check-in, and if the license meets its machine requirements (if strict).

This endpoint does not allow scopes to be provided, and does not take required scopes into account during validation. If your policy requires any particular scopes to be specified, e.g. requireFingerprintScope, etc., you should use the POST version of this endpoint.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to validate the resource: either an admin, the product it belongs to, or the user it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) or key of the license to be validated. Cannot be an encrypted license key.

linkReturns

A 200 OK response will be returned along with the validation result and the validated license object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/{ID}/actions/validate

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/validate", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { meta, data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/validate",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/validate",
  Method.GET
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/validate")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/validate")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/validate");
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/validate \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "meta": {
    "valid": true,
    "detail": "is valid",
    "constant": "VALID"
  },
  "data": {
    "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
    },
    "attributes": {
      "key": "024e1ec7440f43b0b1ecc51c40897931-9fc2bb9d3cbd3d207fb713227737b637-1788b9572a82ce14166227a8d4db5b6d-904064d3432be2ab0088d60d09fca7v1",
      "expiry": "2020-01-01T00:00:00.000Z",
      "uses": 0,
      "suspended": false,
      "encrypted": false,
      "floating": true,
      "concurrent": true,
      "strict": false,
      "maxMachines": 5,
      "maxUses": null,
      "requireCheckIn": false,
      "lastCheckIn": null,
      "nextCheckIn": null,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "e8bf27c0-5f9c-4135-a65c-f52706c5fd4c"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines?license=b18e3f3a-330c-4d8d-ae2e-014db21fa827"
        }
      }
    }
  }
}

linkValidation Constants

Below are the possible values for the meta.constant key within the validation response. This can be used to better communicate failures to your users.

Constant Meaning
VALID The validated license resource or license key is valid.
NOT_FOUND The validated license resource or license key does not exist.
OVERDUE The validated license is overdue for check-in.
SUSPENDED The validated license has been suspended.
EXPIRED The validated license is expired.
NO_MACHINE The validated license does not meet its node-locked policy's requirement of exactly 1 associated machine.
NO_MACHINES The validated license does not meet its floating policy's requirement of at least 1 associated machine.
TOO_MANY_MACHINES The validated license has exceeded its policy's machine limit.

linkValidate license

Action to validate a license. This will check the following: if the license is suspended, if the license is expired, if the license is overdue for check-in, and if the license meets its machine requirements (if strict).

Additional scopes can also be applied, and may be required by the license's policy, e.g. a policy may set requireFingerprintScope=true, which will require that you specify a scope.fingerprint with the validation request in order to pass validation.

The scoping feature allows you to easily set up a node-locked or floating licensing model without additional logic on your end.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to validate the resource: either an admin, the product it belongs to, or the user it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) or key of the license to be validated. Cannot be an encrypted license key.

linkMeta

  • linkscope

    hash<string, string>, optional

    Scope to validate the license against i.e. if a license's key is associated with product X, but the validation request is scoped to product Y, it will fail validation because a matching license doesn't exist for that product.

  • linkscope.product

    string, optional

    The identifier (UUID) of the product to validate against.

  • linkscope.policy

    string, optional

    The identifier (UUID) of the policy to validate against.

  • linkscope.machine

    string, optional

    The identifier (UUID) of the machine to validate against.

  • linkscope.fingerprint

    string, optional

    The fingerprint of a machine to validate against.

linkReturns

A 200 OK response will be returned along with the validation result and the validated license object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/{ID}/actions/validate

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/validate", {
  method: "POST",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "meta": {
      "scope": {
        "fingerprint": "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC"
      }
    }
  })
})

const { meta, data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/validate",
  method: .post,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "meta": [
      "scope": [
        "fingerprint": "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC"
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/validate",
  Method.POST
);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  meta = new {
    scope = new {
      fingerprint = "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC"
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "meta" to mapOf(
    "scope" to mapOf(
      "fingerprint" to "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC"
    )
  )
))

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/validate")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("scope", ofEntries(
      entry("fingerprint", "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC")
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/validate")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value scope;
scope["fingerprint"] = value::string("4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC");

value meta;
meta["scope"] = scope;

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

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/validate");
req.set_method(methods::POST);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/validate \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "meta": {
          "scope": {
            "fingerprint": "9a:Eq:Uv:p3:yZ:tL:lC:Bz:mA:Eg:E6:Mk:YX:dK:NC"
          }
        }
      }'

Example response / 200 OK

{
  "meta": {
    "valid": false,
    "detail": "fingerprint scope does not match",
    "constant": "FINGERPRINT_SCOPE_MISMATCH"
  },
  "data": {
    "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
    },
    "attributes": {
      "key": "024e1ec7440f43b0b1ecc51c40897931-9fc2bb9d3cbd3d207fb713227737b637-1788b9572a82ce14166227a8d4db5b6d-904064d3432be2ab0088d60d09fca7v1",
      "expiry": "<%= expired %>",
      "uses": 0,
      "suspended": false,
      "encrypted": false,
      "floating": true,
      "concurrent": true,
      "strict": false,
      "maxMachines": 5,
      "maxUses": null,
      "requireCheckIn": false,
      "lastCheckIn": null,
      "nextCheckIn": null,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "e8bf27c0-5f9c-4135-a65c-f52706c5fd4c"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines?license=b18e3f3a-330c-4d8d-ae2e-014db21fa827"
        }
      }
    }
  }
}

linkValidation Constants

Below are the possible values for the meta.constant key within the validation response. This can be used to better communicate failures to your users.

Constant Meaning
VALID The validated license resource or license key is valid.
NOT_FOUND The validated license resource or license key does not exist.
OVERDUE The validated license is overdue for check-in.
SUSPENDED The validated license has been suspended.
EXPIRED The validated license is expired.
NO_MACHINE The validated license does not meet its node-locked policy's requirement of exactly 1 associated machine.
NO_MACHINES The validated license does not meet its floating policy's requirement of at least 1 associated machine.
TOO_MANY_MACHINES The validated license has exceeded its policy's machine limit.
PRODUCT_SCOPE_REQUIRED The validated license requires a product scope to be provided during validation.
PRODUCT_SCOPE_MISMATCH The validated license's product scope does not match the provided scope.
POLICY_SCOPE_REQUIRED The validated license requires a policy scope to be provided during validation.
POLICY_SCOPE_MISMATCH The validated license's policy scope does not match the provided scope.
MACHINE_SCOPE_REQUIRED The validated license requires a machine scope to be provided during validation.
MACHINE_SCOPE_MISMATCH The validated license's machine scope does not match the provided scope.
FINGERPRINT_SCOPE_REQUIRED The validated license requires a fingerprint scope to be provided during validation.
FINGERPRINT_SCOPE_MISMATCH The validated license's fingerprint scope does not match the provided scope.

linkValidate key

Action to validate a license key. This will look up the license by its key and check the following: if the license is suspended, if the license is expired, if the license is overdue for check-in, and if the license meets its machine requirements (if strict).

Additional scopes can also be applied, and may be required by the license's policy, e.g. a policy may set requireFingerprintScope=true, which will require that you specify a scope.fingerprint with the validation request in order to pass validation.

The scoping feature allows you to easily set up a node-locked or floating licensing model without additional logic on your end.

linkAuthentication

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkMeta

  • linkkey

    string, required

    The license key to validate.

  • linkscope

    hash<string, string>, optional

    Scope to validate the license against i.e. if a license's key is associated with product X, but the validation request is scoped to product Y, it will fail validation because a matching license doesn't exist for that product.

  • linkscope.product

    string, optional

    The identifier (UUID) of the product to validate against.

  • linkscope.policy

    string, optional

    The identifier (UUID) of the policy to validate against.

  • linkscope.machine

    string, optional

    The identifier (UUID) of the machine to validate against.

  • linkscope.fingerprint

    string, optional

    The fingerprint of a machine to validate against.

linkReturns

A 200 OK response will be returned along with the validation result and the validated license object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/actions/validate-key

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/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, data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/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!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
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(request);
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/<%= account %>/licenses/actions/validate-key")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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/<%= account %>/licenses/actions/validate-key")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
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();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/licenses/actions/validate-key \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -d '{
        "meta": {
          "key": "B8A5-91D7-CB9A-DAE4-4F6E-1128"
        }
      }'

Example response / 200 OK

{
  "meta": {
    "valid": false,
    "detail": "is expired",
    "constant": "EXPIRED"
  },
  "data": {
    "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
    },
    "attributes": {
      "key": "024e1ec7440f43b0b1ecc51c40897931-9fc2bb9d3cbd3d207fb713227737b637-1788b9572a82ce14166227a8d4db5b6d-904064d3432be2ab0088d60d09fca7v1",
      "expiry": "<%= expired %>",
      "uses": 0,
      "suspended": false,
      "encrypted": false,
      "floating": true,
      "concurrent": true,
      "strict": false,
      "maxMachines": 5,
      "maxUses": null,
      "requireCheckIn": false,
      "lastCheckIn": null,
      "nextCheckIn": null,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "e8bf27c0-5f9c-4135-a65c-f52706c5fd4c"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines?license=b18e3f3a-330c-4d8d-ae2e-014db21fa827"
        }
      }
    }
  }
}

linkValidation Constants

Below are the possible values for the meta.constant key within the validation response. This can be used to better communicate failures to your users.

Constant Meaning
VALID The validated license resource or license key is valid.
NOT_FOUND The validated license resource or license key does not exist.
OVERDUE The validated license is overdue for check-in.
SUSPENDED The validated license has been suspended.
EXPIRED The validated license is expired.
NO_MACHINE The validated license does not meet its node-locked policy's requirement of exactly 1 associated machine.
NO_MACHINES The validated license does not meet its floating policy's requirement of at least 1 associated machine.
TOO_MANY_MACHINES The validated license has exceeded its policy's machine limit.
PRODUCT_SCOPE_REQUIRED The validated license requires a product scope to be provided during validation.
PRODUCT_SCOPE_MISMATCH The validated license's product scope does not match the provided scope.
POLICY_SCOPE_REQUIRED The validated license requires a policy scope to be provided during validation.
POLICY_SCOPE_MISMATCH The validated license's policy scope does not match the provided scope.
MACHINE_SCOPE_REQUIRED The validated license requires a machine scope to be provided during validation.
MACHINE_SCOPE_MISMATCH The validated license's machine scope does not match the provided scope.
FINGERPRINT_SCOPE_REQUIRED The validated license requires a fingerprint scope to be provided during validation.
FINGERPRINT_SCOPE_MISMATCH The validated license's fingerprint scope does not match the provided scope.

linkSuspend license

Action to temporarily suspend (ban) a license. This will cause the license to fail validation until reinistated. To permanently revoke a license, see the revoke action.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to suspend the resource: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the license to suspend.

linkReturns

A 200 OK response will be returned along with the suspended license object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/{ID}/actions/suspend

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/suspend", {
  method: "POST",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/suspend",
  method: .post,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/suspend",
  Method.POST
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/suspend")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/suspend")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/suspend");
req.set_method(methods::POST);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/suspend \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
    },
    "attributes": {
      "key": "024e1ec7440f43b0b1ecc51c40897931-9fc2bb9d3cbd3d207fb713227737b637-1788b9572a82ce14166227a8d4db5b6d-904064d3432be2ab0088d60d09fca7v1",
      "expiry": "2020-01-01T00:00:00.000Z",
      "uses": 0,
      "suspended": true,
      "encrypted": false,
      "floating": true,
      "concurrent": true,
      "strict": false,
      "maxMachines": 5,
      "maxUses": null,
      "requireCheckIn": false,
      "lastCheckIn": null,
      "nextCheckIn": null,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "e8bf27c0-5f9c-4135-a65c-f52706c5fd4c"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines?license=b18e3f3a-330c-4d8d-ae2e-014db21fa827"
        }
      }
    }
  }
}

linkReinstate license

Action to reinstate a suspended license.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to reinstate the resource: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the license to reinstate.

linkReturns

A 200 OK response will be returned along with the reinstated license object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/{ID}/actions/reinstate

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/reinstate", {
  method: "POST",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/reinstate",
  method: .post,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/reinstate",
  Method.POST
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/reinstate")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/reinstate")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/reinstate");
req.set_method(methods::POST);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/reinstate \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
    },
    "attributes": {
      "key": "024e1ec7440f43b0b1ecc51c40897931-9fc2bb9d3cbd3d207fb713227737b637-1788b9572a82ce14166227a8d4db5b6d-904064d3432be2ab0088d60d09fca7v1",
      "expiry": "2020-01-01T00:00:00.000Z",
      "uses": 0,
      "suspended": false,
      "encrypted": false,
      "floating": true,
      "strict": false,
      "maxMachines": 5,
      "maxUses": null,
      "requireCheckIn": false,
      "lastCheckIn": null,
      "nextCheckIn": null,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "e8bf27c0-5f9c-4135-a65c-f52706c5fd4c"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines?license=b18e3f3a-330c-4d8d-ae2e-014db21fa827"
        }
      }
    }
  }
}

linkRenew license

Action to renew a license. Extends license expiry by the policy's duration.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to renew the resource: either an admin, the product it belongs to, or if the license's policy is unprotected, the user it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the license to renew.

linkReturns

A 200 OK response will be returned along with the renewed license object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/{ID}/actions/renew

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/renew", {
  method: "POST",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/renew",
  method: .post,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/renew",
  Method.POST
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/renew")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/renew")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/renew");
req.set_method(methods::POST);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/renew \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
    },
    "attributes": {
      "key": "024e1ec7440f43b0b1ecc51c40897931-9fc2bb9d3cbd3d207fb713227737b637-1788b9572a82ce14166227a8d4db5b6d-904064d3432be2ab0088d60d09fca7v1",
      "expiry": "2020-01-01T00:00:00.000Z",
      "uses": 0,
      "suspended": false,
      "encrypted": false,
      "floating": false,
      "concurrent": true,
      "strict": false,
      "maxMachines": 5,
      "maxUses": null,
      "requireCheckIn": false,
      "lastCheckIn": null,
      "nextCheckIn": null,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "e8bf27c0-5f9c-4135-a65c-f52706c5fd4c"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines?license=b18e3f3a-330c-4d8d-ae2e-014db21fa827"
        }
      }
    }
  }
}

linkRevoke license

Action to revoke (delete) a license. This cannot be undone. This action also immediately deletes any machines that the license is associated with.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to revoke the resource: either an admin, the product it belongs to, or if the license's policy is unprotected, the user it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the license to revoke.

linkReturns

A 204 No Content response will be returned.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/{ID}/actions/revoke

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/revoke", {
  method: "DELETE",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/revoke",
  method: .delete,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let status = response.response?.statusCode
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/revoke",
  Method.DELETE
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/revoke")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/revoke")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/revoke");
req.set_method(methods::DELETE);

client.request(req)
  .then([](http_response res) {
    auto status = res.status_code();
  })
  .wait();
curl -X DELETE https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/revoke \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 204 No Content

No content

linkCheck-In license

Action to check-in a license. Sets the license's lastCheckIn to the current time, and the license's nextCheckIn according to the policy's check-in interval.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to check-in the resource: either an admin, the product it belongs to, or if the license's policy is unprotected, the user it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the license to check-in.

linkReturns

A 200 OK response will be returned along with the checked in license object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/{ID}/actions/check-in

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/check-in", {
  method: "POST",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/check-in",
  method: .post,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/check-in",
  Method.POST
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/check-in")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/check-in")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/check-in");
req.set_method(methods::POST);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/check-in \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
    },
    "attributes": {
      "key": "024e1ec7440f43b0b1ecc51c40897931-9fc2bb9d3cbd3d207fb713227737b637-1788b9572a82ce14166227a8d4db5b6d-904064d3432be2ab0088d60d09fca7v1",
      "expiry": "2020-01-01T00:00:00.000Z",
      "uses": 0,
      "suspended": false,
      "encrypted": false,
      "floating": true,
      "concurrent": true,
      "strict": false,
      "maxMachines": 5,
      "maxUses": null,
      "requireCheckIn": true,
      "lastCheckIn": "<%= lastCheckIn %>",
      "nextCheckIn": "<%= nextCheckIn %>",
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "e8bf27c0-5f9c-4135-a65c-f52706c5fd4c"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines?license=b18e3f3a-330c-4d8d-ae2e-014db21fa827"
        }
      }
    }
  }
}

linkIncrement license usage

Action to increment a license's uses attribute in accordance with its policy's maxUses attribute. When the policy's maxUses limit is exceeded, the increment attempt will fail. When the policy's maxUses is set to null, there is no limit on usage.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to increment the resource's usage: either an admin, the product it belongs to, or if the license's policy is unprotected, the user it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the license to increment usage for.

linkMeta

  • linkincrement

    integer, optional, default is1

    The amount to increment the license's usage by.

linkReturns

A 200 OK response will be returned along with the incremented uses count within the license object. A 422 Unprocessable Entity will be returned in the case where the policy's maxUses count has been exceeded.

Though rare, a 409 Conflict will be returned in the case where a previous increment operation has not yet completed. This is likely due to you firing off too many increment requests in parallel. Increase the time between requests or increment in larger batches by utilizing the meta.increment parameter.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/{ID}/actions/increment-usage

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/increment-usage", {
  method: "POST",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "meta": {
      "increment": 25
    }
  })
})

const { meta, data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/increment-usage",
  method: .post,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "meta": [
      "increment": 25
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/increment-usage",
  Method.POST
);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  meta = new {
    increment = 25
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "meta" to mapOf(
    "increment" to 25
  )
))

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/increment-usage")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("increment", 25)
  ))
));

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/increment-usage")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value meta;
meta["increment"] = value::int(25);

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

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/increment-usage");
req.set_method(methods::POST);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/increment-usage \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "meta": {
          "increment": 25
        }
      }'

Example response / 200 OK

{
  "data": {
    "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
    },
    "attributes": {
      "key": "024e1ec7440f43b0b1ecc51c40897931-9fc2bb9d3cbd3d207fb713227737b637-1788b9572a82ce14166227a8d4db5b6d-904064d3432be2ab0088d60d09fca7v1",
      "expiry": "2020-01-01T00:00:00.000Z",
      "uses": 25,
      "suspended": false,
      "encrypted": false,
      "floating": true,
      "concurrent": true,
      "strict": false,
      "maxMachines": 5,
      "maxUses": 100,
      "requireCheckIn": true,
      "lastCheckIn": "<%= lastCheckIn %>",
      "nextCheckIn": "<%= nextCheckIn %>",
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "e8bf27c0-5f9c-4135-a65c-f52706c5fd4c"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines?license=b18e3f3a-330c-4d8d-ae2e-014db21fa827"
        }
      }
    }
  }
}

linkDecrement license usage

Action to decrement a license's uses attribute in accordance with its policy's maxUses attribute.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to decrement the resource's usage: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the license to decrement usage for.

linkMeta

  • linkdecrement

    integer, optional, default is1

    The amount to decrement the license's usage by.

linkReturns

A 200 OK response will be returned along with the decremented uses count within the license object.

Though rare, a 409 Conflict will be returned in the case where a previous decrement operation has not yet completed. This is likely due to you firing off too many decrement requests in parallel. Increase the time between requests or decrement in larger batches by utilizing the meta.decrement parameter.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/{ID}/actions/decrement-usage

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/decrement-usage", {
  method: "POST",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/decrement-usage",
  method: .post,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/decrement-usage",
  Method.POST
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/decrement-usage")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/decrement-usage")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/decrement-usage");
req.set_method(methods::POST);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/decrement-usage \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
    },
    "attributes": {
      "key": "024e1ec7440f43b0b1ecc51c40897931-9fc2bb9d3cbd3d207fb713227737b637-1788b9572a82ce14166227a8d4db5b6d-904064d3432be2ab0088d60d09fca7v1",
      "expiry": "2020-01-01T00:00:00.000Z",
      "uses": 0,
      "suspended": false,
      "encrypted": false,
      "floating": true,
      "concurrent": true,
      "strict": false,
      "maxMachines": 5,
      "maxUses": 5,
      "requireCheckIn": true,
      "lastCheckIn": "<%= lastCheckIn %>",
      "nextCheckIn": "<%= nextCheckIn %>",
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "e8bf27c0-5f9c-4135-a65c-f52706c5fd4c"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines?license=b18e3f3a-330c-4d8d-ae2e-014db21fa827"
        }
      }
    }
  }
}

linkReset license usage

Action to reset a license's uses attribute to 0.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to reset the resource's usage: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the license to reset usage for.

linkReturns

A 200 OK response will be returned along with the reset uses count within the license object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/{ID}/actions/reset-usage

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/reset-usage", {
  method: "POST",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/reset-usage",
  method: .post,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/reset-usage",
  Method.POST
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/reset-usage")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/reset-usage")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/reset-usage");
req.set_method(methods::POST);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/actions/reset-usage \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
    },
    "attributes": {
      "key": "024e1ec7440f43b0b1ecc51c40897931-9fc2bb9d3cbd3d207fb713227737b637-1788b9572a82ce14166227a8d4db5b6d-904064d3432be2ab0088d60d09fca7v1",
      "expiry": "2020-01-01T00:00:00.000Z",
      "uses": 0,
      "suspended": false,
      "encrypted": false,
      "floating": true,
      "concurrent": true,
      "strict": false,
      "maxMachines": 5,
      "maxUses": 5,
      "requireCheckIn": true,
      "lastCheckIn": "<%= lastCheckIn %>",
      "nextCheckIn": "<%= nextCheckIn %>",
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "e8bf27c0-5f9c-4135-a65c-f52706c5fd4c"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines?license=b18e3f3a-330c-4d8d-ae2e-014db21fa827"
        }
      }
    }
  }
}

linkLicense relationships

Relationship endpoints for the license resource.

linkChange policy

Change a license's policy relationship. This will immediately be taken into effect for all future validations.

Below are the limitations to changing a license's policy:

  • You cannot change from an encrypted policy to an unencrypted policy (or vice-versa).
  • You cannot change from a pooled policy to an unpooled policy (or vice-versa).
  • You cannot change to a policy for another product.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin, the product it belongs to, or if the license's policy is unprotected, the user it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) or key of the license to be updated. Cannot be an encrypted license key.

linkReturns

A 200 OK response will be returned along with the updated license object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/licenses/{ID}/policy

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy", {
  method: "PUT",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "data": {
      "type": "policies",
      "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy",
  method: .put,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "data": [
      "type": "policies",
      "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy",
  Method.PUT
);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  data = new {
    type = "policies",
    id = "70af414d-6152-4ff1-892b-15a40ada6b4e"
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "policies",
    "id" to "37b632f4-8e1e-4af9-8717-634765364628"
  )
))

val res = Unirest.put("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("data", ofEntries(
    entry("type", "policies"),
    entry("id", "37b632f4-8e1e-4af9-8717-634765364628")
  ))
));

HttpResponse<JsonNode> res = Unirest.put("https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value data;
data["type"] = value::string("policies");
data["id"] = value::string("37b632f4-8e1e-4af9-8717-634765364628");

value body;
body["data"] = data;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy");
req.set_method(methods::PUT);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X PUT https://api.keygen.sh/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      }'

Example response / 200 OK

{
  "data": {
    "id": "b18e3f3a-330c-4d8d-ae2e-014db21fa827",
    "type": "licenses",
    "links": {
      "self": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827"
    },
    "attributes": {
      "key": "024e1ec7440f43b0b1ecc51c40897931-9fc2bb9d3cbd3d207fb713227737b637-1788b9572a82ce14166227a8d4db5b6d-904064d3432be2ab0088d60d09fca7v1",
      "expiry": "2020-01-01T00:00:00.000Z",
      "uses": 0,
      "suspended": false,
      "encrypted": false,
      "floating": false,
      "concurrent": true,
      "strict": false,
      "maxMachines": 1,
      "maxUses": null,
      "requireCheckIn": false,
      "lastCheckIn": null,
      "nextCheckIn": null,
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/product"
        },
        "data": {
          "type": "products",
          "id": "eb4e14a7-ea41-4ede-b3fe-5e835c17156b"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/policy"
        },
        "data": {
          "type": "policies",
          "id": "70af414d-6152-4ff1-892b-15a40ada6b4e"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/licenses/b18e3f3a-330c-4d8d-ae2e-014db21fa827/user"
        },
        "data": {
          "type": "users",
          "id": "e8bf27c0-5f9c-4135-a65c-f52706c5fd4c"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines?license=b18e3f3a-330c-4d8d-ae2e-014db21fa827"
        }
      }
    }
  }
}

linkMachines

linkThe machine object

Below you will find the various attributes for the machine resource, as well as the machine resource's relationships. Machines can be used to track and manage where your users are allowed to use your product.

linkAttributes

  • linkfingerprint

    string

    The fingerprint of the machine. This can be an arbitrary string, but must be unique within the scope of the license it belongs to.

  • linkname

    string

    The human-readable name of the machine.

  • linkip

    string

    The IP of the machine.

  • linkhostname

    string

    The hostname of the machine.

  • linkplatform

    string

    The platform of the machine.

  • linkmetadata

    hash<string, scalar>

    Hash containing machine metadata.

  • linkcreated

    timestampread only

    When the machine was created.

  • linkupdated

    timestampread only

    When the machine was last updated.

linkRelationships

  • linkaccount

    individual

    The account that the machine belongs to.

  • linkproduct

    individual

    The product that the machine is associated with.

  • linklicense

    individual

    The license that the machine is associated with.

  • linkuser

    individual

    The user that owns the machine.

Example object

{
  "data": {
    "id": "9c4c90c8-d4d3-4571-9363-4c7b0332a6a4",
    "type": "machines",
    "links": {
      "self": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4"
    },
    "attributes": {
      "fingerprint": "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC",
      "ip": null,
      "hostname": null,
      "platform": "macOS",
      "name": "Office MacBook Pro",
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/product"
        },
        "data": {
          "type": "products",
          "id": "22b78db6-6a2e-4a7f-9369-157976148c4c"
        }
      },
      "license": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/license"
        },
        "data": {
          "type": "licenses",
          "id": "4097d726-6cc5-4156-8575-3a96387e19b4"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/user"
        },
        "data": {
          "type": "users",
          "id": "15ad7012-b570-48b7-88c1-fbab68be9d05"
        }
      }
    }
  }
}

linkActivate a machine

Creates, or activates, a new machine resource.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to create the resource: either an admin, the product it belongs to, or the user it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkAttributes

  • linkfingerprint

    string, required

    The fingerprint of the machine. This can be an arbitrary string, but must be unique within the scope of the license it belongs to.

  • linkname

    string, optional

    The human-readable name of the machine.

  • linkip

    string, optional

    The IP of the machine.

  • linkhostname

    string, optional

    The hostname of the machine.

  • linkplatform

    string, optional

    The platform of the machine.

  • linkmetadata

    hash<string, scalar>, optional

    Hash containing machine metadata.

linkRelationships

  • linklicense

    linkage, required

    The license the machine is for.

linkReturns

A 201 Created response will be returned along with the new machine object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines

Example request

const fetch = require("node-fetch")
const sha1 = require("sha1")
const { promisify } = require("bluebird")
const { getMac } = require("getmac")

const getMacAddress = promisify(getMac)
const getFingerprint = async () => {
  return sha1(await getMacAddress() /* + anything else you want to use */)
          .split(/(.{2})/)
          .filter(Boolean)
          .join(":")
}

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/machines", {
  method: "POST",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "data": {
      "type": "machines",
      "attributes": {
        "fingerprint": await getFingerprint(),
        "platform": "macOS",
        "name": "Office MacBook Pro"
      },
      "relationships": {
        "license": {
          "data": {
            "type": "licenses",
            "id": "4097d726-6cc5-4156-8575-3a96387e19b4"
          }
        }
      }
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/machines",
  method: .post,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "data": [
      "type": "machines",
      "attributes": [
        "fingerprint": "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC",
        "platform": "macOS",
        "name": "Office MacBook Pro"
      ],
      "relationships": [
        "license": [
          "data": [
            "type": "licenses",
            "id": "4097d726-6cc5-4156-8575-3a96387e19b4"
          ]
        ]
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("machines", Method.POST);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  data = new {
    type = "machines",
    attributes = new {
      fingerprint = "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC",
      platform = "macOS",
      name = "Office MacBook Pro"
    },
    relationships = new {
      license = new {
        data = new {
          type = "licenses",
          id = "4097d726-6cc5-4156-8575-3a96387e19b4"
        }
      }
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "machines",
    "attributes" to mapOf(
      "fingerprint" to "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC",
      "platform" to "macOS",
      "name" to "Office MacBook Pro"
    ),
    "relationships" to mapOf(
      "license" to mapOf(
        "data" to mapOf(
          "type" to "licenses",
          "id" to "4097d726-6cc5-4156-8575-3a96387e19b4"
        )
      )
    )
  )
))

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/machines")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("data", ofEntries(
    entry("type", "machines"),
    entry("attributes", ofEntries(
      entry("fingerprint", "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC"),
      entry("platform", "macOS"),
      entry("name", "Office MacBook Pro")
    )),
    entry("relationships", ofEntries(
      entry("license", ofEntries(
        entry("data", ofEntries(
          entry("type", "licenses"),
          entry("id", "4097d726-6cc5-4156-8575-3a96387e19b4")
        ))
      ))
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/machines")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value attrs;
attrs["fingerprint"] = value::string("4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC");
attrs["platform"] = value::string("macOS");
attrs["name"] = value::string("Office MacBook Pro");

value license_;
license_["type"] = value::string("licenses");
license_["id"] = value::string("4097d726-6cc5-4156-8575-3a96387e19b4");

value license;
license["data"] = license_;

value rels;
rels["license"] = license;

value data;
data["type"] = value::string("machines");
data["attributes"] = attrs;
data["relationships"] = rels;

value body;
body["data"] = data;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/machines");
req.set_method(methods::POST);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/machines \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "data": {
          "type": "machines",
          "attributes": {
            "fingerprint": "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC",
            "platform": "macOS",
            "name": "Office MacBook Pro"
          },
          "relationships": {
            "license": {
              "data": {
                "type": "licenses",
                "id": "4097d726-6cc5-4156-8575-3a96387e19b4"
              }
            }
          }
        }
      }'

Example response / 201 Created

{
  "data": {
    "id": "9c4c90c8-d4d3-4571-9363-4c7b0332a6a4",
    "type": "machines",
    "links": {
      "self": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4"
    },
    "attributes": {
      "fingerprint": "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC",
      "ip": null,
      "hostname": null,
      "platform": "macOS",
      "name": "Office MacBook Pro",
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/product"
        },
        "data": {
          "type": "products",
          "id": "22b78db6-6a2e-4a7f-9369-157976148c4c"
        }
      },
      "license": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/license"
        },
        "data": {
          "type": "licenses",
          "id": "4097d726-6cc5-4156-8575-3a96387e19b4"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/user"
        },
        "data": {
          "type": "users",
          "id": "15ad7012-b570-48b7-88c1-fbab68be9d05"
        }
      }
    }
  }
}

linkRetrieve a machine

Retrieves the details of an existing machine.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resource: either an admin, the product it belongs to, or the user it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the machine to be retrieved.

linkReturns

A 200 OK response will be returned along with a machine object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/machines/eef41cf5-f32e-4dab-a867-b9738d87285b", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/machines/eef41cf5-f32e-4dab-a867-b9738d87285b",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "machines/eef41cf5-f32e-4dab-a867-b9738d87285b",
  Method.GET
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/machines/eef41cf5-f32e-4dab-a867-b9738d87285b")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/machines/eef41cf5-f32e-4dab-a867-b9738d87285b")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/machines/eef41cf5-f32e-4dab-a867-b9738d87285b");
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/machines/eef41cf5-f32e-4dab-a867-b9738d87285b \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "9c4c90c8-d4d3-4571-9363-4c7b0332a6a4",
    "type": "machines",
    "links": {
      "self": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4"
    },
    "attributes": {
      "fingerprint": "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC",
      "ip": null,
      "hostname": null,
      "platform": "macOS",
      "name": "Office MacBook Pro",
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/product"
        },
        "data": {
          "type": "products",
          "id": "22b78db6-6a2e-4a7f-9369-157976148c4c"
        }
      },
      "license": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/license"
        },
        "data": {
          "type": "licenses",
          "id": "4097d726-6cc5-4156-8575-3a96387e19b4"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/user"
        },
        "data": {
          "type": "users",
          "id": "15ad7012-b570-48b7-88c1-fbab68be9d05"
        }
      }
    }
  }
}

linkUpdate a machine

Updates the specified machine resource by setting the values of the parameters passed. Any parameters not provided will be left unchanged.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin, the product it belongs to, or the user it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the machine to be updated.

linkAttributes

  • linkname

    string, optional

    The human-readable name of the machine.

  • linkip

    string, optional

    The IP of the machine.

  • linkhostname

    string, optional

    The hostname of the machine.

  • linkplatform

    string, optional

    The platform of the machine.

  • linkmetadata

    hash<string, scalar>, optionalprotectedProtected attributes are only available for bearers with an admin or product role.

    Hash containing machine metadata.

linkReturns

A 200 OK response will be returned along with the updated machine object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/machines/b18e3f3a-330c-4d8d-ae2e-014db21fa827", {
  method: "PATCH",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "data": {
      "type": "machines",
      "attributes": {
        "ip": "192.168.1.1"
      }
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/machines/b18e3f3a-330c-4d8d-ae2e-014db21fa827",
  method: .patch,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "data": [
      "type": "machines",
      "attributes": [
        "ip": "192.168.1.1"
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "machines/b18e3f3a-330c-4d8d-ae2e-014db21fa827",
  Method.PATCH
);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  data = new {
    type = "machines",
    attributes = new {
      ip = "192.168.1.1"
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "machines",
    "attributes" to mapOf(
      "ip" to "192.168.1.1"
    )
  )
))

val res = Unirest.patch("https://api.keygen.sh/v1/accounts/<%= account %>/machines/b18e3f3a-330c-4d8d-ae2e-014db21fa827")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("data", ofEntries(
    entry("type", "machines"),
    entry("attributes", ofEntries(
      entry("ip", "192.168.1.1")
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.patch("https://api.keygen.sh/v1/accounts/<%= account %>/machines/b18e3f3a-330c-4d8d-ae2e-014db21fa827")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value attrs;
attrs["ip"] = value::string("192.168.1.1");

value data;
data["type"] = value::string("machines");
data["attributes"] = attrs;

value body;
body["data"] = data;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/machines/b18e3f3a-330c-4d8d-ae2e-014db21fa827");
req.set_method(methods::PATCH);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X PATCH https://api.keygen.sh/v1/accounts/<%= account %>/machines/b18e3f3a-330c-4d8d-ae2e-014db21fa827 \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "data": {
          "type": "machines",
          "attributes": {
            "ip": "192.168.1.1"
          }
        }
      }'

Example response / 200 OK

{
  "data": {
    "id": "9c4c90c8-d4d3-4571-9363-4c7b0332a6a4",
    "type": "machines",
    "links": {
      "self": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4"
    },
    "attributes": {
      "fingerprint": "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC",
      "ip": "192.168.1.1",
      "hostname": null,
      "platform": "macOS",
      "name": "Office MacBook Pro",
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/product"
        },
        "data": {
          "type": "products",
          "id": "22b78db6-6a2e-4a7f-9369-157976148c4c"
        }
      },
      "license": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/license"
        },
        "data": {
          "type": "licenses",
          "id": "4097d726-6cc5-4156-8575-3a96387e19b4"
        }
      },
      "user": {
        "links": {
          "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/user"
        },
        "data": {
          "type": "users",
          "id": "15ad7012-b570-48b7-88c1-fbab68be9d05"
        }
      }
    }
  }
}

linkDeactivate a machine

Permanently deletes, or deactivates, a machine. It cannot be undone.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin, the product it belongs to, or the user it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the machine to be deleted.

linkReturns

A 204 No Content response will be returned.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4", {
  method: "DELETE",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4",
  method: .delete,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let status = response.response?.statusCode
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4",
  Method.DELETE
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4");
req.set_method(methods::DELETE);

client.request(req)
  .then([](http_response res) {
    auto status = res.status_code();
  })
  .wait();
curl -X DELETE https://api.keygen.sh/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4 \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 204 No Content

No content

linkList all machines

Returns a list of machines. The machines are returned sorted by creation date, with the most recent machines appearing first. Resources are automatically scoped to the authenticated bearer e.g. when authenticated as a user, only machines of that specific user will be listed.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resources.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkFilters

  • linklimit

    integer, default is10

    A limit on the number of machines to be returned. Limit must be a number between 1 and 100.

    https://api.keygen.sh/v1/accounts/<%= account %>/machines?limit=25
  • linkpage

    hash<string, integer>

    Hash containing page size and page number. Page size must be a number between 1 and 100

    https://api.keygen.sh/v1/accounts/<%= account %>/machines?page[size]=15&page[number]=2
  • linkfingerprint

    string

    The machine fingerprint to filter by.

    https://api.keygen.sh/v1/accounts/<%= account %>/machines?fingerprint=4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC
  • linkproduct

    string

    The identifier (UUID) of the product to filter by.

    https://api.keygen.sh/v1/accounts/<%= account %>/machines?product=3ab38aae-bbf7-4846-9c32-af9d94bf5ad4
  • linklicense

    string

    The identifier (UUID) of the license to filter by.

    https://api.keygen.sh/v1/accounts/<%= account %>/machines?license=3fd7ff1c-e778-4030-a81c-d2242d909258
  • linkkey

    string

    The license key to filter by. Cannot be an encrypted key.

    https://api.keygen.sh/v1/accounts/<%= account %>/machines?key=B8A5-91D7-CB9A-DAE4-4F6E-1128
  • linkuser

    string

    The identifier (UUID) of the user to filter by.

    https://api.keygen.sh/v1/accounts/<%= account %>/machines?user=a5a154d2-f026-40fa-bc8d-a7e3ca415298

linkReturns

A 200 OK response will be returned along with a list of machine objects.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines{FILTERS}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/machines?limit=15", {
  method: "GET",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/machines?limit=15",
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("machines", Method.GET);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddParameter("limit", 15);

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/machines")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/machines")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

uri_builder uri("/machines");
uri.append_query("limit", 15);

req.set_request_uri(uri.to_uri());
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/machines?limit=15 -g \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": [
    {
      "id": "9c4c90c8-d4d3-4571-9363-4c7b0332a6a4",
      "type": "machines",
      "links": {
        "self": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4"
      },
      "attributes": {
        "fingerprint": "4d:Eq:UV:D3:XZ:tL:WN:Bz:mA:Eg:E6:Mk:YX:dK:NC",
        "ip": null,
        "hostname": null,
        "platform": "macOS",
        "name": "Office MacBook Pro",
        "metadata": {},
        "created": "<%= created %>",
        "updated": "<%= created %>"
      },
      "relationships": {
        "account": {
          "links": {
            "related": "/v1/accounts/<%= account %>"
          },
          "data": {
            "type": "accounts",
            "id": "<%= account %>"
          }
        },
        "product": {
          "links": {
            "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/product"
          },
          "data": {
            "type": "products",
            "id": "22b78db6-6a2e-4a7f-9369-157976148c4c"
          }
        },
        "license": {
          "links": {
            "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/license"
          },
          "data": {
            "type": "licenses",
            "id": "4097d726-6cc5-4156-8575-3a96387e19b4"
          }
        },
        "user": {
          "links": {
            "related": "/v1/accounts/<%= account %>/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/user"
          },
          "data": {
            "type": "users",
            "id": "15ad7012-b570-48b7-88c1-fbab68be9d05"
          }
        }
      }
    },
    …
  ]
}

linkKeys

linkThe key object

Below you will find the various attributes for the key resource, as well as the key resource's relationships. Keys cannot be validated, are not actual "licenses", and are only used for pooled policies.

When creating a pooled policy, you create a limited set of "keys" to fill the pool. Each time a license is created that implements the pooled policy, a "key" is taken from the pool and used for the new license, until the pool is depleted. After a pool has been depleted, new licenses cannot be created from the pooled policy until new keys are added. Pooled policies are usually used for limited betas or promotion deals for the first x users.

These are unused keys within a policy's pool – they are not valid licenses. These are used when creating new licenses for a pooled policy or when using a pool's pop action.

linkAttributes

  • linkkey

    string

    The unique key string for the key.

  • linkcreated

    timestampread only

    When the key was created.

  • linkupdated

    timestampread only

    When the key was last updated.

linkRelationships

  • linkaccount

    individual

    The account that the key belongs to.

  • linkproduct

    individual

    The product that the key is associated with.

  • linkpolicy

    individual

    The pooled policy that the key belongs to.

Example object

{
  "data": {
    "id": "6e936a61-94ad-44d1-88ac-88da9f10eca7",
    "type": "keys",
    "links": {
      "self": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7"
    },
    "attributes": {
      "key": "B8A5-91D7-CB9A-DAE4-4F6E-1128",
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7/product"
        },
        "data": {
          "type": "products",
          "id": "1f286fb6-c9bb-498b-a4e7-6c67748b1f4f"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7/policy"
        },
        "data": {
          "type": "policies",
          "id": "95981290-518b-4109-a611-c0001214b3c5"
        }
      }
    }
  }
}

linkCreate a key

Creates a new key resource.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to create the resource: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkAttributes

  • linkkey

    string, required

    The unique key string for the key. The key cannot collide with license keys that already exist.

linkRelationships

  • linkpolicy

    linkage, required

    The pooled policy the key belongs to.

linkReturns

A 201 Created response will be returned along with the new key object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/keys

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/keys", {
  method: "POST",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "data": {
      "type": "keys",
      "attributes": {
        "key": "B8A5-91D7-CB9A-DAE4-4F6E-1128"
      },
      "relationships": {
        "policy": {
          "data": {
            "type": "policies",
            "id": "4ba02145-d1e7-4443-8104-dd1e4236d869"
          }
        }
      }
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/keys",
  method: .post,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "data": [
      "type": "keys",
      "attributes": [
        "key": "B8A5-91D7-CB9A-DAE4-4F6E-1128"
      ],
      "relationships": [
        "policy": [
          "data": [
            "type": "policies",
            "id": "4ba02145-d1e7-4443-8104-dd1e4236d869"
          ]
        ]
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("keys", Method.POST);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  data = new {
    type = "keys",
    attributes = new {
      key = "B8A5-91D7-CB9A-DAE4-4F6E-1128"
    },
    relationships = new {
      policy = new {
        data = new {
          type = "policies",
          id = "4ba02145-d1e7-4443-8104-dd1e4236d869"
        }
      }
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "keys",
    "attributes" to mapOf(
      "key" to "B8A5-91D7-CB9A-DAE4-4F6E-1128"
    ),
    "relationships" to mapOf(
      "policy" to mapOf(
        "data" to mapOf(
          "type" to "policies",
          "id" to "4ba02145-d1e7-4443-8104-dd1e4236d869"
        )
      )
    )
  )
))

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/keys")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("data", ofEntries(
    entry("type", "keys"),
    entry("attributes", ofEntries(
      entry("key", "B8A5-91D7-CB9A-DAE4-4F6E-1128")
    )),
    entry("relationships", ofEntries(
      entry("policy", ofEntries(
        entry("data", ofEntries(
          entry("type", "policies"),
          entry("id", "4ba02145-d1e7-4443-8104-dd1e4236d869")
        ))
      ))
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/keys")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

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

value policy_;
policy_["type"] = value::string("policies");
policy_["id"] = value::string("4ba02145-d1e7-4443-8104-dd1e4236d869");

value policy;
policy["data"] = policy_;

value rels;
rels["policy"] = policy;

value data;
data["type"] = value::string("keys");
data["attributes"] = attrs;
data["relationships"] = rels;

value body;
body["data"] = data;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/keys");
req.set_method(methods::POST);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/keys \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "data": {
          "type": "keys",
          "attributes": {
            "key": "B8A5-91D7-CB9A-DAE4-4F6E-1128"
          },
          "relationships": {
            "policy": {
              "data": {
                "type": "policies",
                "id": "4ba02145-d1e7-4443-8104-dd1e4236d869"
              }
            }
          }
        }
      }'

Example response / 201 Created

{
  "data": {
    "id": "6e936a61-94ad-44d1-88ac-88da9f10eca7",
    "type": "keys",
    "links": {
      "self": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7"
    },
    "attributes": {
      "key": "B8A5-91D7-CB9A-DAE4-4F6E-1128",
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7/product"
        },
        "data": {
          "type": "products",
          "id": "1f286fb6-c9bb-498b-a4e7-6c67748b1f4f"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7/policy"
        },
        "data": {
          "type": "policies",
          "id": "4ba02145-d1e7-4443-8104-dd1e4236d869"
        }
      }
    }
  }
}

linkRetrieve a key

Retrieves the details of an existing key.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resource: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the key to be retrieved.

linkReturns

A 200 OK response will be returned along with a key object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/keys/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "keys/6e936a61-94ad-44d1-88ac-88da9f10eca7",
  Method.GET
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7");
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7 \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "6e936a61-94ad-44d1-88ac-88da9f10eca7",
    "type": "keys",
    "links": {
      "self": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7"
    },
    "attributes": {
      "key": "B8A5-91D7-CB9A-DAE4-4F6E-1128",
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7/product"
        },
        "data": {
          "type": "products",
          "id": "1f286fb6-c9bb-498b-a4e7-6c67748b1f4f"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7/policy"
        },
        "data": {
          "type": "policies",
          "id": "95981290-518b-4109-a611-c0001214b3c5"
        }
      }
    }
  }
}

linkUpdate a key

Updates the specified key resource by setting the values of the parameters passed. Any parameters not provided will be left unchanged.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the key to be updated.

linkAttributes

  • linkkey

    string, optional

    The unique key string for the key.

linkReturns

A 200 OK response will be returned along with the updated key object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/keys/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/keys/b18e3f3a-330c-4d8d-ae2e-014db21fa827", {
  method: "PATCH",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "data": {
      "type": "keys",
      "attributes": {
        "key": "9adce-26df1-9c487-nb293-d0279"
      }
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/keys/b18e3f3a-330c-4d8d-ae2e-014db21fa827",
  method: .patch,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "data": [
      "type": "keys",
      "attributes": [
        "key": "9adce-26df1-9c487-nb293-d0279"
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "keys/b18e3f3a-330c-4d8d-ae2e-014db21fa827",
  Method.PATCH
);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  data = new {
    type = "keys",
    attributes = new {
      key = "9adce-26df1-9c487-nb293-d0279"
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "keys",
    "attributes" to mapOf(
      "key" to "9adce-26df1-9c487-nb293-d0279"
    )
  )
))

val res = Unirest.patch("https://api.keygen.sh/v1/accounts/<%= account %>/keys/b18e3f3a-330c-4d8d-ae2e-014db21fa827")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("data", ofEntries(
    entry("type", "keys"),
    entry("attributes", ofEntries(
      entry("key", "9adce-26df1-9c487-nb293-d0279")
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.patch("https://api.keygen.sh/v1/accounts/<%= account %>/keys/b18e3f3a-330c-4d8d-ae2e-014db21fa827")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value attrs;
attrs["key"] = value::string("9adce-26df1-9c487-nb293-d0279");

value data;
data["type"] = value::string("keys");
data["attributes"] = attrs;

value body;
body["data"] = data;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/keys/b18e3f3a-330c-4d8d-ae2e-014db21fa827");
req.set_method(methods::PATCH);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X PATCH https://api.keygen.sh/v1/accounts/<%= account %>/keys/b18e3f3a-330c-4d8d-ae2e-014db21fa827 \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "data": {
          "type": "keys",
          "attributes": {
            "key": "9adce-26df1-9c487-nb293-d0279"
          }
        }
      }'

Example response / 200 OK

{
  "data": {
    "id": "6e936a61-94ad-44d1-88ac-88da9f10eca7",
    "type": "keys",
    "links": {
      "self": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7"
    },
    "attributes": {
      "key": "9adce-26df1-9c487-nb293-d0279",
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "product": {
        "links": {
          "related": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7/product"
        },
        "data": {
          "type": "products",
          "id": "1f286fb6-c9bb-498b-a4e7-6c67748b1f4f"
        }
      },
      "policy": {
        "links": {
          "related": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7/policy"
        },
        "data": {
          "type": "policies",
          "id": "95981290-518b-4109-a611-c0001214b3c5"
        }
      }
    }
  }
}

linkDelete a key

Permanently deletes a key. It cannot be undone.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the key to be deleted.

linkReturns

A 204 No Content response will be returned.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/keys/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7", {
  method: "DELETE",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7",
  method: .delete,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let status = response.response?.statusCode
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "keys/6e936a61-94ad-44d1-88ac-88da9f10eca7",
  Method.DELETE
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7");
req.set_method(methods::DELETE);

client.request(req)
  .then([](http_response res) {
    auto status = res.status_code();
  })
  .wait();
curl -X DELETE https://api.keygen.sh/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7 \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 204 No Content

No content

linkList all keys

Returns a list of keys. The keys are returned sorted by creation date, with the most recent keys appearing first. Resources are automatically scoped to the authenticated bearer e.g. when authenticated as a product, only keys of that specific product will be listed.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resources: either an admin or the product it belongs to.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkFilters

  • linklimit

    integer, default is10

    A limit on the number of keys to be returned. Limit must be a number between 1 and 100.

    https://api.keygen.sh/v1/accounts/<%= account %>/keys?limit=25
  • linkpage

    hash<string, integer>

    Hash containing page size and page number. Page size must be a number between 1 and 100

    https://api.keygen.sh/v1/accounts/<%= account %>/keys?page[size]=15&page[number]=2
  • linkproduct

    string

    The identifier (UUID) of the product to filter by.

    https://api.keygen.sh/v1/accounts/<%= account %>/keys?product=3ab38aae-bbf7-4846-9c32-af9d94bf5ad4
  • linkpolicy

    string

    The identifier (UUID) of the policy to filter by.

    https://api.keygen.sh/v1/accounts/<%= account %>/keys?policy=92ec8aa5-8f93-4e46-b356-4e54c16647be

linkReturns

A 200 OK response will be returned along with a list of key objects.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/keys{FILTERS}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/keys?limit=15", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/keys?limit=15",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("keys", Method.GET);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddParameter("list", 15);

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/keys")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/keys")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

uri_builder uri("/keys");
uri.append_query("limit", 15);

req.set_request_uri(uri.to_uri());
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/keys?limit=15 -g \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": [
    {
      "id": "6e936a61-94ad-44d1-88ac-88da9f10eca7",
      "type": "keys",
      "links": {
        "self": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7"
      },
      "attributes": {
        "key": "B8A5-91D7-CB9A-DAE4-4F6E-1128",
        "created": "<%= created %>",
        "updated": "<%= created %>"
      },
      "relationships": {
        "account": {
          "links": {
            "related": "/v1/accounts/<%= account %>"
          },
          "data": {
            "type": "accounts",
            "id": "<%= account %>"
          }
        },
        "product": {
          "links": {
            "related": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7/product"
          },
          "data": {
            "type": "products",
            "id": "1f286fb6-c9bb-498b-a4e7-6c67748b1f4f"
          }
        },
        "policy": {
          "links": {
            "related": "/v1/accounts/<%= account %>/keys/6e936a61-94ad-44d1-88ac-88da9f10eca7/policy"
          },
          "data": {
            "type": "policies",
            "id": "95981290-518b-4109-a611-c0001214b3c5"
          }
        }
      }
    },
    …
  ]
}

linkWebhooks

Webhook events are dispatched using POST requests to an account's webhook endpoints. Events usually get sent quickly, but sometimes there can be a small delay. If you experience a delay longer than 1 hour for the initial event, please contact us.

Webhooks are asynchronous events. We do our best to always send them in a timely manner, but we DO NOT recommend relying on webhooks for events that are time-sensitive e.g., waiting on a webhook to finish processing a web request.

To verify that a webhook event originated from us, you can retrieve the event directly via the API, or use signature verification.

linkEvent Types

The following events are dispatched to all endpoints with a POST request containing an event object.

NOTE: Events that occur on "sub" resources like account.plan do not trigger the parent's update event. In addition, resource deletion e.g. policy.deleted or user.deleted events will not trigger "cascading" deletion events on dependent associations.
Event Trigger Payload
account.updated When your account is updated The updated account object
account.subscription.paused When your account's subscription is paused The updated account object
account.subscription.resumed When your account's subscription is resumed The updated account object
account.subscription.canceled When your account's subscription is canceled The updated account object
account.subscription.renewed When your account's subscription is renewed The updated account object
account.plan.updated When your account's plan is updated The updated plan object
account.billing.updated When your account's billing is updated The updated billing object
user.created When a user is created The user object
user.updated When a user is updated The updated user object
user.deleted When a user is deleted The deleted user object
user.password-reset When a user requests a password reset The user object and reset token
product.created When a product is created The product object
product.updated When a product is updated The updated product object
product.deleted When a product is deleted The deleted product object
policy.created When a policy is created The policy object
policy.updated When a policy is updated The updated policy object
policy.deleted When a policy is deleted The deleted policy object
policy.pool.popped When a key is popped from a pool The popped key object
license.created When a license is created The license object
license.updated When a license is updated The updated license object
license.deleted When a license is deleted The deleted license object
license.expiring-soon When a license is expiring within the next 3 days
Note: Up to 1 event will be sent every day until expiration
The expiring license object
license.expired When a license has expired The expired license object
license.check-in-required-soon When a license requires a check-in within the next 3 days
Note: Up to 1 event will be sent every day until overdue
The license object
license.check-in-overdue When a license is overdue for check-in The overdue license object
license.validation.succeeded When a license validation succeeds The validated license object
license.validation.failed When a license validation fails The validated license object
license.usage.incremented When a license's usage is incremented The used license object
license.usage.decremented When a license's usage is decremented The used license object
license.usage.reset When a license's usage is reset The reset license object
license.renewed When a license is renewed The renewed license object
license.revoked When a license is revoked The revoked license object
license.suspended When a license is suspended The suspended license object
license.reinstated When a license is reinstated The reinstated license object
license.policy.updated When a license's policy relationship has been changed The license object
machine.created When a machine is created The machine object
machine.updated When a machine is updated The updated machine object
machine.deleted When a machine is deleted The deleted machine object
key.created When a key is created The key object
key.updated When a key is updated The updated key object
key.deleted When a key is deleted The deleted key object

Example webhook handler using Node and Express

const fetch = require("node-fetch")
const express = require("express")
const bodyParser = require("body-parser")
const app = express()

app.use(bodyParser.json({ type: "application/vnd.api+json" }))
app.use(bodyParser.json({ type: "application/json" }))

app.post("/my/webhook/url", async (req, res) => {
  const { data: { id } } = req.body

  // Fetch the webhook to validate it and get its most up-to-date state
  const event = await fetch(`https://api.keygen.sh/v1/accounts/{ACCOUNT}/webhook-events/${id}`, {
    method: "GET",
    headers: {
      "Accept": "application/vnd.api+json",
      "Authorization": "Bearer {PRODUCT_TOKEN}"
    }
  })

  const { data, errors } = await event.json()
  if (errors) {
    return res.sendStatus(200) // Webhook event does not exist
  }

  switch (data.attributes.event) {
    case "user.password-reset":
      const reset = JSON.parse(data.attributes.payload)
      const { passwordResetToken } = reset.meta

      // … email the password reset token to the user for fulfillment

      break
    case "user.created":
      const user = JSON.parse(data.attributes.payload)

      // … do something when a user is created e.g. create a Stripe customer

      break
    case "license.created":
      const license = JSON.parse(data.attributes.payload)

      // … do something when a license is created e.g. charge a user

      break
  }

  // Let Keygen know the event was received successfully
  res.sendStatus(200)
})

const server = app.listen(8080, 'localhost', () => {
  const { address, port } = server.address()

  console.log(`Listening at http://${address}:${port}`)
})

linkThe endpoint object

Below you will find the various attributes for the endpoint resource, as well as the endpoint resource's relationships.

When delivering webhook events to your endpoint, an event is considered failed if the endpoint responds with a non-2xx status code. It will automatically be retried with an exponential backoff. We will perform 15 retries over approximately 3 days.

linkAttributes

  • linkurl

    string

    The url that events are dispatched to. Must use the https protocol.

  • linkcreated

    timestampread only

    When the endpoint was created.

  • linkupdated

    timestampread only

    When the endpoint was last updated.

linkRelationships

  • linkaccount

    individual

    The account that the endpoint belongs to.

Example object

{
  "data": {
    "id": "0ed7330f-8d2c-405e-88b6-0a4a327e620c",
    "type": "webhook-endpoints",
    "links": {
      "self": "/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c"
    },
    "attributes": {
      "url": "https://api.example.com/v1/keygen",
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      }
    }
  }
}

linkCreate an endpoint

Creates a new endpoint for the account.

linkAuthentication

  • linkBearer

    required

    An authentication token with admin privileges.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkAttributes

  • linkurl

    string, required

    The url that events are dispatched to. Must use the https protocol. Must have a valid SSL certificate.

linkReturns

A 201 Created response will be returned along with the new webhook endpoint object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/webhook-endpoints

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints", {
  method: "POST",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "data": {
      "type": "webhook-endpoints",
      "attributes": {
        "url": "https://api.example.com/v1/keygen"
      }
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints",
  method: .post,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "data": [
      "type": "webhook-endpoints",
      "attributes": [
        "url": "https://api.example.com/v1/keygen"
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("webhook-endpoints", Method.POST);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  data = new {
    type = "webhook-endpoints",
    attributes = new {
      url = "https://api.example.com/v1/keygen"
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "webhook-endpoints",
    "attributes" to mapOf(
      "url" to "https://api.example.com/v1/keygen"
    )
  )
))

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("data", ofEntries(
    entry("type", "webhook-endpoints"),
    entry("attributes", ofEntries(
      entry("url", "https://api.example.com/v1/keygen")
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value attrs;
attrs["url"] = value::string("https://api.example.com/v1/keygen");

value data;
data["type"] = value::string("webhook-endpoints");
data["attributes"] = attrs;

value body;
body["data"] = data;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/webhook-endpoints");
req.set_method(methods::POST);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "data": {
          "type": "webhook-endpoints",
          "attributes": {
            "url": "https://api.example.com/v1/keygen"
          }
        }
      }'

Example response / 201 Created

{
  "data": {
    "id": "0ed7330f-8d2c-405e-88b6-0a4a327e620c",
    "type": "webhook-endpoints",
    "links": {
      "self": "/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c"
    },
    "attributes": {
      "url": "https://api.example.com/v1/keygen",
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      }
    }
  }
}

linkRetrieve an endpoint

Retrieves the details of an existing endpoint.

linkAuthentication

  • linkBearer

    required

    An authentication token with admin privileges.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the webhook-endpoint to be retrieved.

linkReturns

A 200 OK response will be returned along with a webhook endpoint object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/webhook-endpoints/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c",
  Method.GET
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c");
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "0ed7330f-8d2c-405e-88b6-0a4a327e620c",
    "type": "webhook-endpoints",
    "links": {
      "self": "/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c"
    },
    "attributes": {
      "url": "https://api.example.com/v1/keygen",
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      }
    }
  }
}

linkUpdate an endpoint

Updates the specified endpoint resource by setting the values of the parameters passed. Any parameters not provided will be left unchanged.

linkAuthentication

  • linkBearer

    required

    An authentication token with admin privileges.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the webhook endpoint to be updated.

linkAttributes

  • linkurl

    string, optional

    The url that events are dispatched to. Must use the https protocol.

linkReturns

A 200 OK response will be returned along with the updated webhook endpoint object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/webhook-endpoints/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c", {
  method: "PATCH",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  },
  body: JSON.stringify({
    "data": {
      "type": "webhook-endpoints",
      "attributes": {
        "url": "https://api.example.com/v2/keygen"
      }
    }
  })
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c",
  method: .patch,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ],
  parameters: [
    "data": [
      "type": "webhook-endpoints",
      "attributes": [
        "url": "https://api.example.com/v2/keygen"
      ]
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c",
  Method.PATCH
);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddJsonBody(new {
  data = new {
    type = "webhook-endpoints",
    attributes = new {
      url = "https://api.example.com/v2/keygen"
    }
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "data" to mapOf(
    "type" to "webhook-endpoints",
    "attributes" to mapOf(
      "url" to "https://api.example.com/v2/keygen"
    )
  )
))

val res = Unirest.patch("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("data", ofEntries(
    entry("type", "webhook-endpoints"),
    entry("attributes", ofEntries(
      entry("url", "https://api.example.com/v2/keygen")
    ))
  ))
));

HttpResponse<JsonNode> res = Unirest.patch("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c")
  .header("Authorization", "Bearer <%= token %>")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value attrs;
attrs["url"] = value::string("https://api.example.com/v2/keygen");

value data;
data["type"] = value::string("webhook-endpoints");
data["attributes"] = attrs;

value body;
body["data"] = data;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");

req.set_request_uri("/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c");
req.set_method(methods::PATCH);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res)
  {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X PATCH https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>' \
  -d '{
        "data": {
          "type": "webhook-endpoints",
          "attributes": {
            "url": "https://api.example.com/v2/keygen"
          }
        }
      }'

Example response / 200 OK

{
  "data": {
    "id": "0ed7330f-8d2c-405e-88b6-0a4a327e620c",
    "type": "webhook-endpoints",
    "links": {
      "self": "/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c"
    },
    "attributes": {
      "url": "https://api.example.com/v2/keygen",
      "created": "<%= created %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      }
    }
  }
}

linkDelete an endpoint

Permanently deletes an endpoint. It cannot be undone.

linkAuthentication

  • linkBearer

    required

    An authentication token with admin privileges.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the endpoint to be deleted.

linkReturns

A 204 No Content response will be returned.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/webhook-endpoints/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c", {
  method: "DELETE",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c",
  method: .delete,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let status = response.response?.statusCode
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c",
  Method.DELETE
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.delete("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c");
req.set_method(methods::DELETE);

client.request(req)
  .then([](http_response res) {
    auto status = res.status_code();
  })
  .wait();
curl -X DELETE https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 204 No Content

No content

linkList all endpoints

Returns a list of endpoints. The endpoints are returned sorted by creation date, with the most recent endpoints appearing first.

linkAuthentication

  • linkBearer

    required

    An authentication token with admin privileges.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkFilters

  • linklimit

    integer, default is10

    A limit on the number of endpoints to be returned. Limit must be a number between 1 and 100.

    https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints?limit=25
  • linkpage

    hash<string, integer>

    Hash containing page size and page number. Page size must be a number between 1 and 100

    https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints?page[size]=15&page[number]=2

linkReturns

A 200 OK response will be returned along with a list of webhook endpoint objects.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/webhook-endpoints{FILTERS}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints?limit=15", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints?limit=15",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("webhook-endpoints", Method.GET);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddParameter("list", 15);

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

uri_builder uri("/webhook-endpoints");
uri.append_query("limit", 15);

req.set_request_uri(uri.to_uri());
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/webhook-endpoints?limit=15 -g \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": [
    {
      "id": "0ed7330f-8d2c-405e-88b6-0a4a327e620c",
      "type": "webhook-endpoints",
      "links": {
        "self": "/v1/accounts/<%= account %>/webhook-endpoints/0ed7330f-8d2c-405e-88b6-0a4a327e620c"
      },
      "attributes": {
        "url": "https://api.example.com/v1/keygen",
        "created": "<%= created %>",
        "updated": "<%= created %>"
      },
      "relationships": {
        "account": {
          "links": {
            "related": "/v1/accounts/<%= account %>"
          },
          "data": {
            "type": "accounts",
            "id": "<%= account %>"
          }
        }
      }
    },
    …
  ]
}

linkThe event object

Below you will find the various attributes for the event resource, as well as the event resource's relationships.

If security is a concern, or if it's important to confirm that Keygen sent the webhook, you should use ONLY the event ID sent within the webhook to then retrieve the remaining details from Keygen. If the event doesn't exist, then it wasn't from us.

Also see signature verification for more advanced use-cases.

linkAttributes

  • linkendpoint

    stringread only

    The endpoint that the event will be sent to.

  • linkpayload

    stringread only

    The event payload in serialized JSON format.

  • linkevent

    stringread only

    The event type.

  • linkstatus

    stringread only

    The current status of the event. Possible statuses are: queued, working, complete, failed, interrupted or unavailable.

  • linkcreated

    timestampread only

    When the event was created.

  • linkupdated

    timestampread only

    When the event was last updated.

linkRelationships

  • linkaccount

    individual

    The account that the event belongs to.

Example object

{
  "data": {
    "id": "e438b26c-79ab-4088-9bbd-17dbb70c429a",
    "type": "webhook-events",
    "meta": {
      "idempotencyToken": "eeb719a7005359c2b1993c90cff455e2749142253c15227d3f7a93048868c5v1"
    },
    "links": {
      "self": "/v1/accounts/<%= account %>/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a"
    },
    "attributes": {
      "endpoint": "https://api.example.com/keygen",
      "payload": "{\"data\":{\"id\":\"438fc352-3fb5-4f0a-ae06-19d6f55ed5f8\",\"type\":\"licenses\",\"links\":{\"self\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8\"},\"attributes\":{\"key\":\"438fc3523fb54f0aae0619d6f55ed5f8-aeb27205c6f82479f888d83ff54b73e4-4cde9bc9cbac8f245220428cc1d0ab9c-119beb9ae7373524deb53cc20f7b14v1\",\"expiry\":\"2017-01-27T16:05:26.207Z\",\"encrypted\":true,\"metadata\":{},\"created\":\"2017-01-13T16:05:26.207Z\",\"updated\":\"2017-01-13T16:05:26.207Z\"},\"relationships\":{\"account\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502\"},\"data\":{\"type\":\"accounts\",\"id\":\"436430b4-de65-4b1d-a120-97b231395502\"}},\"product\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/product\"},\"data\":{\"type\":\"products\",\"id\":\"558c385c-ce9f-483a-8339-f8b71792426f\"}},\"policy\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/policy\"},\"data\":{\"type\":\"policies\",\"id\":\"d16e6c26-bfbd-47ae-94d5-d9b899e18cfa\"}},\"user\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/user\"},\"data\":{\"type\":\"users\",\"id\":\"7e401525-a2ae-4998-b4a3-84cc2e8dfa2f\"}},\"machines\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/machines\"}}}}}",
      "event": "license.created",
      "status": "queued",
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      }
    }
  }
}

linkRetrieve an event

Retrieves the details of an existing event.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resource: either an admin or a product.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the event to be retrieved.

linkReturns

A 200 OK response will be returned along with a webhook event object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/webhook-events/{ID}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a",
  Method.GET
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a");
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "e438b26c-79ab-4088-9bbd-17dbb70c429a",
    "type": "webhook-events",
    "meta": {
      "idempotencyToken": "eeb719a7005359c2b1993c90cff455e2749142253c15227d3f7a93048868c5v1"
    },
    "links": {
      "self": "/v1/accounts/<%= account %>/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a"
    },
    "attributes": {
      "endpoint": "https://api.example.com/keygen",
      "payload": "{\"data\":{\"id\":\"438fc352-3fb5-4f0a-ae06-19d6f55ed5f8\",\"type\":\"licenses\",\"links\":{\"self\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8\"},\"attributes\":{\"key\":\"438fc3523fb54f0aae0619d6f55ed5f8-aeb27205c6f82479f888d83ff54b73e4-4cde9bc9cbac8f245220428cc1d0ab9c-119beb9ae7373524deb53cc20f7b14v1\",\"expiry\":\"2017-01-27T16:05:26.207Z\",\"encrypted\":true,\"metadata\":{},\"created\":\"2017-01-13T16:05:26.207Z\",\"updated\":\"2017-01-13T16:05:26.207Z\"},\"relationships\":{\"account\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502\"},\"data\":{\"type\":\"accounts\",\"id\":\"436430b4-de65-4b1d-a120-97b231395502\"}},\"product\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/product\"},\"data\":{\"type\":\"products\",\"id\":\"558c385c-ce9f-483a-8339-f8b71792426f\"}},\"policy\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/policy\"},\"data\":{\"type\":\"policies\",\"id\":\"d16e6c26-bfbd-47ae-94d5-d9b899e18cfa\"}},\"user\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/user\"},\"data\":{\"type\":\"users\",\"id\":\"7e401525-a2ae-4998-b4a3-84cc2e8dfa2f\"}},\"machines\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/machines\"}}}}}",
      "event": "license.created",
      "status": "queued",
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      }
    }
  }
}

linkList all events

Returns a list of events. The events are returned sorted by creation date, with the most recent events appearing first.

linkAuthentication

  • linkBearer

    required

    An authentication token with admin privileges.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkFilters

  • linklimit

    integer, default is10

    A limit on the number of events to be returned. Limit must be a number between 1 and 100.

    https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events?limit=25
  • linkpage

    hash<string, integer>

    Hash containing page size and page number. Page size must be a number between 1 and 100

    https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events?page[size]=15&page[number]=2
  • linkevents

    array

    Array containing events to filter by.

    https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events?events[]=license.deleted&events[]=license.revoked

linkReturns

A 200 OK response will be returned along with a list of webhook event objects.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/webhook-events{FILTERS}

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events?limit=15", {
  method: "GET",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events?limit=15",
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("webhook-events", Method.GET);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

request.AddParameter("list", 15);

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .queryString("limit", 15)
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

uri_builder uri("/webhook-events");
uri.append_query("limit", 15);

req.set_request_uri(uri.to_uri());
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events?limit=15 -g \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": [
    {
      "id": "e438b26c-79ab-4088-9bbd-17dbb70c429a",
      "type": "webhook-events",
      "meta": {
        "idempotencyToken": "eeb719a7005359c2b1993c90cff455e2749142253c15227d3f7a93048868c5v1"
      },
      "links": {
        "self": "/v1/accounts/<%= account %>/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a"
      },
      "attributes": {
        "endpoint": "https://api.example.com/keygen",
        "payload": "{\"data\":{\"id\":\"438fc352-3fb5-4f0a-ae06-19d6f55ed5f8\",\"type\":\"licenses\",\"links\":{\"self\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8\"},\"attributes\":{\"key\":\"438fc3523fb54f0aae0619d6f55ed5f8-aeb27205c6f82479f888d83ff54b73e4-4cde9bc9cbac8f245220428cc1d0ab9c-119beb9ae7373524deb53cc20f7b14v1\",\"expiry\":\"2017-01-27T16:05:26.207Z\",\"encrypted\":true,\"metadata\":{},\"created\":\"2017-01-13T16:05:26.207Z\",\"updated\":\"2017-01-13T16:05:26.207Z\"},\"relationships\":{\"account\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502\"},\"data\":{\"type\":\"accounts\",\"id\":\"436430b4-de65-4b1d-a120-97b231395502\"}},\"product\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/product\"},\"data\":{\"type\":\"products\",\"id\":\"558c385c-ce9f-483a-8339-f8b71792426f\"}},\"policy\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/policy\"},\"data\":{\"type\":\"policies\",\"id\":\"d16e6c26-bfbd-47ae-94d5-d9b899e18cfa\"}},\"user\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/user\"},\"data\":{\"type\":\"users\",\"id\":\"7e401525-a2ae-4998-b4a3-84cc2e8dfa2f\"}},\"machines\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/machines\"}}}}}",
        "event": "license.created",
        "status": "queued",
        "created": "<%= created %>",
        "updated": "<%= created %>"
      },
      "relationships": {
        "account": {
          "links": {
            "related": "/v1/accounts/<%= account %>"
          },
          "data": {
            "type": "accounts",
            "id": "<%= account %>"
          }
        }
      }
    },
    …
  ]
}

linkEvent actions

Actions for the event resource.

linkManually retry event

Action to manually retry an event. This creates a new event resource with an identical idempotency token.

Be aware that failed events are automatically retried with an exponential backoff. We will perform 15 retries over approximately 3 days. If you're not watching idempotency tokens, manually retrying an event may result in stale or duplicate data being sent to your endpoints. An event is considered failed if the server responds with a non-2xx status code.

linkAuthentication

  • linkBearer

    required

    An authentication token with admin privileges.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

  • linkid

    string, required

    The identifier (UUID) of the event to retry.

linkReturns

A 201 Created response will be returned along with the retried webhook event object.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/webhook-events/{ID}/actions/retry

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a/actions/retry", {
  method: "POST",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a/actions/retry",
  method: .post,
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest(
  "webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a/actions/retry",
  Method.POST
);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a/actions/retry")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a/actions/retry")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a/actions/retry");
req.set_method(methods::POST);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/webhook-events/e438b26c-79ab-4088-9bbd-17dbb70c429a/actions/retry \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 201 Created

{
  "data": {
    "id": "3119ed21-2f9e-4aa9-8210-5ed0e73f9bef",
    "type": "webhook-events",
    "meta": {
      "idempotencyToken": "eeb719a7005359c2b1993c90cff455e2749142253c15227d3f7a93048868c5v1"
    },
    "links": {
      "self": "/v1/accounts/<%= account %>/webhook-events/3119ed21-2f9e-4aa9-8210-5ed0e73f9bef"
    },
    "attributes": {
      "endpoint": "https://api.example.com/keygen",
      "payload": "{\"data\":{\"id\":\"438fc352-3fb5-4f0a-ae06-19d6f55ed5f8\",\"type\":\"licenses\",\"links\":{\"self\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8\"},\"attributes\":{\"key\":\"438fc3523fb54f0aae0619d6f55ed5f8-aeb27205c6f82479f888d83ff54b73e4-4cde9bc9cbac8f245220428cc1d0ab9c-119beb9ae7373524deb53cc20f7b14v1\",\"expiry\":\"2017-01-27T16:05:26.207Z\",\"encrypted\":true,\"metadata\":{},\"created\":\"2017-01-13T16:05:26.207Z\",\"updated\":\"2017-01-13T16:05:26.207Z\"},\"relationships\":{\"account\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502\"},\"data\":{\"type\":\"accounts\",\"id\":\"436430b4-de65-4b1d-a120-97b231395502\"}},\"product\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/product\"},\"data\":{\"type\":\"products\",\"id\":\"558c385c-ce9f-483a-8339-f8b71792426f\"}},\"policy\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/policy\"},\"data\":{\"type\":\"policies\",\"id\":\"d16e6c26-bfbd-47ae-94d5-d9b899e18cfa\"}},\"user\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/user\"},\"data\":{\"type\":\"users\",\"id\":\"7e401525-a2ae-4998-b4a3-84cc2e8dfa2f\"}},\"machines\":{\"links\":{\"related\":\"/v1/accounts/436430b4-de65-4b1d-a120-97b231395502/licenses/438fc352-3fb5-4f0a-ae06-19d6f55ed5f8/machines\"}}}}}",
      "event": "license.created",
      "status": "queued",
      "created": "<%= updated %>",
      "updated": "<%= updated %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      }
    }
  }
}

linkProfiles

linkRetrieve profile

Retrieves the details of the currently authenticated bearer.

linkAuthentication

  • linkBearer

    required

    An authentication token.

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkReturns

A 200 OK response will be returned along with the token bearer.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/profile

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/profile", {
  method: "GET",
  headers: {
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  }
})

const { data, errors } = await response.json()
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/profile",
  headers: [
    "Accept": "application/vnd.api+json",
    "Authorization": "Bearer <%= token %>"
  ]
).responseJSON { response in
  let json = JSON(data: response.data!)
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("profile", Method.GET);

request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <%= token %>");

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*

val res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/profile")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;

HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<%= account %>/profile")
  .header("Authorization", "Bearer <%= token %>")
  .header("Accept", "application/vnd.api+json")
  .asJson();
#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 utility;

http_client client("https://api.keygen.sh/v1/accounts/<%= account %>");
http_request req;

req.headers().add("Authorization", "Bearer <%= token %>");
req.headers().add("Accept", "application/json");

req.set_request_uri("/profile");
req.set_method(methods::GET);

client.request(req)
  .then([](http_response res) {
    auto data = res.extract_json().get();
  })
  .wait();
curl https://api.keygen.sh/v1/accounts/<%= account %>/profile \
  -H 'Accept: application/vnd.api+json' \
  -H 'Authorization: Bearer <%= token %>'

Example response / 200 OK

{
  "data": {
    "id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298",
    "type": "users",
    "attributes": {
      "fullName": "John Doe",
      "firstName": "John",
      "lastName": "Doe",
      "email": "[email protected]",
      "role": "admin",
      "metadata": {},
      "created": "<%= created %>",
      "updated": "<%= created %>"
    },
    "relationships": {
      "account": {
        "links": {
          "related": "/v1/accounts/<%= account %>"
        },
        "data": {
          "type": "accounts",
          "id": "<%= account %>"
        }
      },
      "products": {
        "links": {
          "related": "/v1/accounts/<%= account %>/profiles/a5a154d2-f026-40fa-bc8d-a7e3ca415298/products"
        }
      },
      "licenses": {
        "links": {
          "related": "/v1/accounts/<%= account %>/profiles/a5a154d2-f026-40fa-bc8d-a7e3ca415298/licenses"
        }
      },
      "machines": {
        "links": {
          "related": "/v1/accounts/<%= account %>/profiles/a5a154d2-f026-40fa-bc8d-a7e3ca415298/machines"
        }
      },
      "tokens": {
        "links": {
          "related": "/v1/accounts/<%= account %>/profiles/a5a154d2-f026-40fa-bc8d-a7e3ca415298/tokens"
        }
      }
    }
  }
}

linkPasswords

linkForgot password

Request a password reset for a user. This will send an email to the user, if it is a valid email address. The email will contain a link leading to a password reset form securely hosted by Keygen.

If you would like to use custom branding or your own domain, you can set deliver = false and listen for the user.password-reset webhook which will contain the user data and meta containing the user's password reset token. You can use the password reset token to fulfill the reset through the password reset fulfillment endpoint.

linkAuthentication

linkParameters

  • linkaccount

    string, required

    The identifier (UUID) or slug of the account.

linkMeta

  • linkemail

    string, required

    The email of the user.

  • linkdeliver

    boolean, optional, default istrue

    Whether or not to email a password reset notification to the user. When false, you will need to listen for the user.password-reset webhook event and implement the fulfillment logic yourself.

linkReturns

A 202 Accepted response will be returned.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/passwords

Example request

const fetch = require("node-fetch")

const response = await fetch("https://api.keygen.sh/v1/accounts/<%= account %>/passwords", {
  method: "POST",
  headers: {
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json"
  },
  body: JSON.stringify({
    "meta": {
      "email": "[email protected]",
      "deliver": false
    }
  })
})
import SwiftyJSON
import Alamofire

Alamofire.request("https://api.keygen.sh/v1/accounts/<%= account %>/passwords",
  method: .post,
  headers: [
    "Content-Type": "application/vnd.api+json",
    "Accept": "application/vnd.api+json"
  ],
  parameters: [
    "meta": [
      "email": "[email protected]",
      "deliver": false
    ]
  ],
  encoding: JSONEncoding.default
).responseJSON { response in
  let status = response.response?.statusCode
}
using RestSharp;

var client = new RestClient("https://api.keygen.sh/v1/accounts/<%= account %>");
var request = new RestRequest("passwords", Method.POST);

request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");

request.AddJsonBody(new {
  meta = new {
    email = "[email protected]",
    deliver = false
  }
});

var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*

val body = JSONObject(mapOf(
  "meta" to mapOf(
    "email" to "[email protected]",
    "deliver" to false
  )
))

val res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/passwords")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson()
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("email", "[email protected]"),
    entry("deliver", false)
  ))
));

HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<%= account %>/passwords")
  .header("Content-Type", "application/vnd.api+json")
  .header("Accept", "application/vnd.api+json")
  .body(body)
  .asJson();
#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/<%= account %>");
http_request req;

value meta;
meta["email"] = value::string("[email protected]");
meta["deliver"] = value::boolean(false);

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

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

req.set_request_uri("/passwords");
req.set_method(methods::POST);
req.set_body(body.serialize());

client.request(req)
  .then([](http_response res) {
    auto status = res.status_code();
  })
  .wait();
curl -X POST https://api.keygen.sh/v1/accounts/<%= account %>/passwords \
  -H 'Content-Type: application/vnd.api+json' \
  -H 'Accept: application/vnd.api+json' \
  -d '{
        "meta": {
          "email": "[email protected]",
          "deliver": false
        }
      }'

Example response / 202 Accepted

No content