Select programming language for code examples

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

  • linkdata.attributes.fingerprint

    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.

  • linkdata.attributes.cores

    integer

    The number of CPU cores for the machine.

  • linkdata.attributes.name

    string

    The human-readable name of the machine.

  • linkdata.attributes.ip

    string

    The IP of the machine.

  • linkdata.attributes.hostname

    string

    The hostname of the machine.

  • linkdata.attributes.platform

    string

    The platform of the machine.

  • linkdata.attributes.requireHeartbeat

    booleanread only

    Whether or not the machine has an active heartbeat monitor and requires pings.

  • linkdata.attributes.heartbeatStatus

    stringread only

    The status of the machine's heartbeat. One of: NOT_STARTED, ALIVE or DEAD.

  • linkdata.attributes.heartbeatDuration

    integerread only

    The policy's heartbeat duration. When a heartbeat monitor is active, the machine must send a heartbeat ping within this timeframe to remain activated.

  • linkdata.attributes.lastHeartbeat

    timestamp (ISO8601 format)read only

    When the machine last sent a heartbeat ping. This is null if the machine does not require a heartbeat.

  • linkdata.attributes.nextHeartbeat

    timestamp (ISO8601 format)read only

    The time at which the machine is required to send a heartbeat ping by. This is null if the machine does not require a heartbeat.

  • linkdata.attributes.metadata

    object<string, scalar>

    Object containing machine metadata.

  • linkdata.attributes.created

    timestamp (ISO8601 format)read only

    When the machine was created.

  • linkdata.attributes.updated

    timestamp (ISO8601 format)read only

    When the machine was last updated.

linkRelationships

  • linkdata.relationships.account

    individual

    The account that the machine belongs to.

  • linkdata.relationships.product

    individual

    The product that the machine is associated with.

  • linkdata.relationships.license

    individual

    The license that the machine is associated with.

  • linkdata.relationships.user

    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",
"cores": null,
"ip": null,
"hostname": null,
"platform": "macOS",
"name": "Office MacBook Pro",
"requireHeartbeat": false,
"heartbeatStatus": "NOT_STARTED",
"heartbeatDuration": 600,
"lastHeartbeat": null,
"nextHeartbeat": null,
"metadata": {},
"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}"
}
},
"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 for a license.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to create the resource: either an admin, the product it belongs to, the license it belongs to (via an activation token), or the user it belongs to (unless the license is protected).

linkURL Parameters

  • link:account

    string, required

    The identifier (UUID) or slug of your Keygen account.

linkAttributes

  • linkdata.attributes.fingerprint

    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.

  • linkdata.attributes.cores

    integer, optional

    The number of CPU cores for the machine.

  • linkdata.attributes.name

    string, optional

    The human-readable name of the machine.

  • linkdata.attributes.ip

    string, optional

    The IP of the machine.

  • linkdata.attributes.hostname

    string, optional

    The hostname of the machine.

  • linkdata.attributes.platform

    string, optional

    The platform of the machine.

  • linkdata.attributes.metadata

    object<string, scalar>, optional

    Object containing machine metadata.

linkRelationships

linkReturns

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

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

Definition

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

Example request

const fetch = require("node-fetch")
 
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": "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"
}
}
}
}
})
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.post(
"https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines",
headers={
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"Authorization": "Bearer {TOKEN}"
},
data=json.dumps({
"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"
}
}
}
}
})
).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",
"cores": null,
"ip": null,
"hostname": null,
"platform": "macOS",
"name": "Office MacBook Pro",
"requireHeartbeat": false,
"heartbeatStatus": "NOT_STARTED",
"heartbeatDuration": 600,
"lastHeartbeat": null,
"nextHeartbeat": null,
"metadata": {},
"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}"
}
},
"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, a product which the owning license belongs to, the license it belongs to (via an activation token), or the user it belongs to.

linkURL Parameters

  • link:account

    string, required

    The identifier (UUID) or slug of your Keygen account.

  • link:id

    string, required

    The identifier (UUID) or URL-safe fingerprint of the machine to be retrieved.

linkReturns

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

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

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 requests
import json
 
res = requests.get(
"https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/eef41cf5-f32e-4dab-a867-b9738d87285b",
headers={
"Accept": "application/vnd.api+json",
"Authorization": "Bearer {TOKEN}"
}
).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",
"cores": null,
"ip": null,
"hostname": null,
"platform": "macOS",
"name": "Office MacBook Pro",
"requireHeartbeat": false,
"heartbeatStatus": "NOT_STARTED",
"heartbeatDuration": 600,
"lastHeartbeat": null,
"nextHeartbeat": null,
"metadata": {},
"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}"
}
},
"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 (unless the license is protected).

linkURL Parameters

  • link:account

    string, required

    The identifier (UUID) or slug of your Keygen account.

  • link:id

    string, required

    The identifier (UUID) or URL-safe fingerprint of the machine to be updated.

linkAttributes

  • linkdata.attributes.cores

    integer, optional

    The number of CPU cores for the machine.

  • linkdata.attributes.name

    string, optional

    The human-readable name of the machine.

  • linkdata.attributes.ip

    string, optional

    The IP of the machine.

  • linkdata.attributes.hostname

    string, optional

    The hostname of the machine.

  • linkdata.attributes.platform

    string, optional

    The platform of the machine.

  • linkdata.attributes.metadata

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

    Object containing machine metadata.

linkReturns

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

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

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 requests
import json
 
res = requests.patch(
"https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/b18e3f3a-330c-4d8d-ae2e-014db21fa827",
headers={
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"Authorization": "Bearer {TOKEN}"
},
data=json.dumps({
"data": {
"type": "machines",
"attributes": {
"ip": "192.168.1.1"
}
}
})
).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",
"cores": 16
}
}
}'

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",
"cores": 16,
"ip": "192.168.1.1",
"hostname": null,
"platform": "macOS",
"name": "Office MacBook Pro",
"requireHeartbeat": false,
"heartbeatStatus": "NOT_STARTED",
"heartbeatDuration": 600,
"lastHeartbeat": null,
"nextHeartbeat": null,
"metadata": {},
"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}"
}
},
"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, the license it belongs to (via an activation token), or the user it belongs to (unless the license is protected).

linkURL Parameters

  • link:account

    string, required

    The identifier (UUID) or slug of your Keygen account.

  • link:id

    string, required

    The identifier (UUID) or URL-safe fingerprint of the machine to be deleted.

linkReturns

A 204 No Content response will be returned.

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

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 requests
 
res = requests.delete(
"https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4",
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: either an admin, a product which the owning license belongs to, the license which the machines belong to (via an activation token), or the user which the machines belong to.

linkURL Parameters

  • link:account

    string, required

    The identifier (UUID) or slug of your Keygen 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

    object<string, integer>

    Object 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
  • linkip

    string

    The machine IP address to filter by.

    https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines?ip=192.168.1.1
  • linkhostname

    string

    The machine hostname to filter by.

    https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines?hostname=CoolHostname
  • 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
  • linkpolicy

    string

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

    https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines?policy=f2a336e8-85c0-49bd-85f6-ffc15b4ac679
  • 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=C1B6DE-39A6E3-DE1529-8559A0-4AF593-V3
  • 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
  • linkmetadata

    object<string, scalar>

    The metadata object to filter by.

    https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines?metadata[nodeId]=68666bf8b

linkReturns

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

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

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 requests
import json
 
res = requests.get(
"https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines?limit=15",
headers={
"Accept": "application/vnd.api+json",
"Authorization": "Bearer {TOKEN}"
}
).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",
"cores": null,
"ip": null,
"hostname": null,
"platform": "macOS",
"name": "Office MacBook Pro",
"requireHeartbeat": false,
"heartbeatStatus": "NOT_STARTED",
"heartbeatDuration": 600,
"lastHeartbeat": null,
"nextHeartbeat": null,
"metadata": {},
"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}"
}
},
"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"
}
}
}
},
]
}

linkMachine actions

Actions for the machine resource.

linkOffline activation proofs

Action to generate a cryptographically signed offline activation proof. This can be used to implement an offline license activation system. You can think of these proofs as a 'certificate' or a 'license file.' See our sample client/server app on GitHub for an example of air-gapped license activation.

Activation proofs are signed with your account's 2048-bit RSA private key, using RSA PKCS1 v1.5 padding, with a SHA256 digest. The proof dataset will be base64url encoded and then prefixed with proof/ before signing, and the signing data's signature will be base64url encoded and then appended onto the end of the signing data, delimited by the . character, e.g. proof/{URLBASE64_DATASET}.{URLBASE64_SIGNATURE}.

Here is an example of a cryptographically signed activation proof:

proof/eyJhY2NvdW50Ijp7ImlkIjoiMmUyOTE2N2ItZjc1NS00YjlkLTk1OWMtZTIzNmI1OTY5N2IzIn0sInByb2R1Y3QiOnsiaWQiOiI0MTdkODNjMy1jMjhkLTRhMDMtODQwYS00Y2ZmNmUzNTUyZTYifSwicG9saWN5Ijp7ImlkIjoiMTI2MzczY2QtYTA2Mi00MDYzLTgwODUtZDE3N2MyNTM0MTg3IiwiZHVyYXRpb24iOjEyMDk2MDB9LCJsaWNlbnNlIjp7ImlkIjoiMzg3ZjUxMmQtOTJjYy00Y2UzLWE3MTAtY2FjOGJkZGU3NzU1Iiwia2V5IjoiRUREMEIxLTAwQzhBNi04MzdGQzAtRDlGQTkyLUJGNjFBMS1WMyIsImV4cGlyeSI6IjIwMjEtMDQtMDVUMTc6MDQ6NTUuMjEzWiJ9LCJtYWNoaW5lIjp7ImlkIjoiN2ZhNzA3YzAtY2FhNi00NTI0LThlNTItNmEzNDQyMzUwNzVlIiwiZmluZ2VycHJpbnQiOiI4Qjo5Mjo1RDpERToxRDpFODozNjpEMjo4ODpFNzo2RTo0QSIsImNyZWF0ZWQiOiIyMDIxLTAzLTIyVDE3OjA0OjU1LjIyNFoifSwidHMiOiIyMDIxLTAzLTIyVDE3OjA0OjU2LjgzNFoifQ==.mJfXlfBbG8ekOph8SmDNiuRcL9sz_RSecwF4Q4hz1rd8gJOFN-fwhnt3Pd9rIGpr09_-4UPzqBeC0W_ak905F4iGVi57JK2b1qegjbe22R1XtqfFlvpHPvuez6lkhkRy8YOpe80PpWxyFuXCGwHJ65cSBFL6r6PvOqWG2IdacaolDdR76ek1z4bf5RWI-MEJFlJpQcJ_Cr8PjmssR4A270ZxhKlFGG-0wsut504l_XcmHH_IUmyvPTIAhoWV496pCSQSGGw6r4Y9BElKk1Vlm8tUMQ6JQMlbHjWkwWyd950r-0a1-AUw7kAMHKiR4SQTQGLumQhMe0v9Io6GLJeaQA==

Below is the decoded dataset from the above example proof:

{
"account": {
"id": "2e29167b-f755-4b9d-959c-e236b59697b3"
},
"product": {
"id": "417d83c3-c28d-4a03-840a-4cff6e3552e6"
},
"policy": {
"id": "126373cd-a062-4063-8085-d177c2534187",
"duration": 1209600
},
"license": {
"id": "387f512d-92cc-4ce3-a710-cac8bdde7755",
"key": "EDD0B1-00C8A6-837FC0-D9FA92-BF61A1-V3",
"expiry": "2021-04-05T17:04:55.213Z"
},
"machine": {
"id": "7fa707c0-caa6-4524-8e52-6a344235075e",
"fingerprint": "8B:92:5D:DE:1D:E8:36:D2:88:E7:6E:4A",
"created": "2021-03-22T17:04:55.224Z"
},
"ts": "2021-03-22T17:04:56.834Z"
}

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to generate an offline proof: either an admin, the product it belongs to, the license itself (via an activation token), or if the license's policy is unprotected, the user it belongs to.

linkURL Parameters

  • link:account

    string, required

    The identifier (UUID) or slug of your Keygen account.

  • link:id

    string, required

    The identifier (UUID) or URL-safe fingerprint of the machine to generate an offline activation proof for.

linkMeta

  • linkmeta.dataset

    object<string, scalar>, optional

    A custom JSON dataset to embed within the activation proof. This dataset will be cryptographically signed, making it tamper-proof. Only authenticated admins and products may supply this value.

linkReturns

A 200 OK response will be returned along with an offline activation proof and the machine object.

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/{ID}/actions/generate-offline-proof

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/generate-offline-proof", {
method: "POST",
headers: {
"Accept": "application/vnd.api+json",
"Authorization": "Bearer {TOKEN}"
}
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.post(
"https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/generate-offline-proof",
headers={
"Accept": "application/vnd.api+json",
"Authorization": "Bearer {TOKEN}"
}
).json()
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/generate-offline-proof",
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(
"machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/ping-heartbeat",
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}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/generate-offline-proof")
.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}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/generate-offline-proof")
.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/actions/generate-offline-proof");
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}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/generate-offline-proof \
-H 'Accept: application/vnd.api+json' \
-H 'Authorization: Bearer {TOKEN}'

Example response / 200 OK

{
"meta": {
"proof": "proof/eyJhY2NvdW50Ijp7ImlkIjoiNjI0NzBkNjctNDgzNy00YjVhLWFjYzItN2FmYjgwZDBhM2JmIn0sInByb2R1Y3QiOnsiaWQiOiJhNzZiM2NhMi1hZGVlLTRiY2YtOTdhMS0xNzkyNDAzMWNlY2QifSwicG9saWN5Ijp7ImlkIjoiN2Y4OTlhMTUtNDU1My00YjkwLWI3MzAtNmUxZjgwMzEyYzcwIn0sImxpY2Vuc2UiOnsiaWQiOiIzMWZhMzU1MS1kYjJmLTRmN2UtYjEzMS0yZGZiNTViZmJmNzMiLCJrZXkiOiJERkU1NzktNzUzQzI1LUEzQjY2Ny0yNEUzRUMtMzI4QTU3LVYzIiwiZXhwaXJ5IjoiMjAyMS0wMy0yOVQyMjo0NzowOS4xMDhaIn0sIm1hY2hpbmUiOnsiaWQiOiJkZWMwNmE5YS1kZTVjLTQ1M2MtYTAyMy1jOTMwMjlkZjMzMjMiLCJmaW5nZXJwcmludCI6ImRjMTY0MmI5NjcyMTFlODVmMTRmNjRjZmE4NjdjODZjIiwiY3JlYXRlZCI6IjIwMjAtMTAtMDFUMTc6MTM6MTkuNzI1WiJ9LCJwcm9vZiI6eyJjcmVhdGVkIjoiMjAyMC0xMC0wNVQyMDo0MDozMi4xNDNaIn19.QpyUpB2PMXC4QmQfKvStoafV5F4WIvzaF3IJ8SEd2YVfhicbRxZp4EiJRkKt_la4TaBF7MzWeqaXfbMVDk_LAKAWlTFgeFNBF0B9pXyCWHgFc01AKeiz6l3Cwi-PsC-DP6yfMgQqZ2LKOruIbkuWHL8yrTBw9n5_LSRldR8OAxVY51o0bdWRiYHO1jtkq2MFbn8t3tS8p0bJacuHRrWJSl6WAYZYb3iLXLiuftSrX6cZuB_ZlVifWvXXl3Am_ebOBnZ7WQBsTfJ0xxHFKbIpn24s9LGlIf0kJOEk4zr8vc9mxxyIFh1HwbGKTQzpj9sW6rFiVY5a9zMQLKh3ciDjRQ=="
},
"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",
"cores": null,
"ip": null,
"hostname": null,
"platform": "macOS",
"name": "Office MacBook Pro",
"requireHeartbeat": true,
"heartbeatStatus": "ALIVE",
"heartbeatDuration": 600,
"lastHeartbeat": "2019-05-28T15:38:02.927Z",
"nextHeartbeat": "2019-05-28T15:48:02.927Z",
"metadata": {},
"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}"
}
},
"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"
}
}
}
}
}

linkPing heartbeat

Action to begin and maintain a machine heartbeat monitor. When a machine has not performed a heartbeat ping within the monitor window, it will automatically be deactivated. This can be utilized for machine leasing, where a license has a limited number of machines allowed, and each machine must maintain heartbeat pings in order to remain active.

To illustrate further, consider a rather common scenario when dealing with leasing VMs:

  1. The machine is activated for a new device using a unique VM GUID as a "fingerprint."
  2. The machine sends their first heartbeat ping, starting the monitor.
  3. The machine sends further heartbeat pings, within the heartbeat monitor window, to indicate that it is still alive.
  4. The machine/software crashes. Normal machine deactivation fails to occur before the software program exits. This is now a "zombie" machine.
  5. The heartbeat monitor detects that the machine has not sent a ping within the window, and subsequently deactivates the machine.

The default heartbeat monitor window is 10 minutes from time of last ping. This can be configured via the license policy's heartbeatDuration attribute.

Once a machine heartbeat monitor has been started, it must be maintained. The machine will automatically be deactivated (i.e. deleted) if it does not maintain a ping frequency. Please see the reset heartbeat action, which can be used to reset and disable a heartbeat monitor for a given machine.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to ping the resource's heartbeat: either an admin, the product it belongs to, the machine's license (via an activation token), or the user it belongs to.

linkURL Parameters

  • link:account

    string, required

    The identifier (UUID) or slug of your Keygen account.

  • link:id

    string, required

    The identifier (UUID) or URL-safe fingerprint of the machine to ping.

linkReturns

A 200 OK response will be returned along with the pinged machine object.

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/{ID}/actions/ping-heartbeat

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/ping-heartbeat", {
method: "POST",
headers: {
"Accept": "application/vnd.api+json",
"Authorization": "Bearer {TOKEN}"
}
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.post(
"https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/ping-heartbeat",
headers={
"Accept": "application/vnd.api+json",
"Authorization": "Bearer {TOKEN}"
}
).json()
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/ping-heartbeat",
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(
"machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/ping-heartbeat",
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}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/ping-heartbeat")
.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}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/ping-heartbeat")
.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/actions/ping-heartbeat");
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}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/ping-heartbeat \
-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",
"cores": null,
"ip": null,
"hostname": null,
"platform": "macOS",
"name": "Office MacBook Pro",
"requireHeartbeat": true,
"heartbeatStatus": "ALIVE",
"heartbeatDuration": 600,
"lastHeartbeat": "2019-05-28T15:38:02.927Z",
"nextHeartbeat": "2019-05-28T15:48:02.927Z",
"metadata": {},
"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}"
}
},
"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"
}
}
}
}
}

linkReset heartbeat

Action to reset and stop the machine's heartbeat monitor. This will not deactivate the machine.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to reset the resource's heartbeat: either an admin or the product it belongs to.

linkURL Parameters

  • link:account

    string, required

    The identifier (UUID) or slug of your Keygen account.

  • link:id

    string, required

    The identifier (UUID) or URL-safe fingerprint of the machine to reset.

linkReturns

A 200 OK response will be returned along with the reset machine object.

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

Definition

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

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/reset-heartbeat", {
method: "POST",
headers: {
"Accept": "application/vnd.api+json",
"Authorization": "Bearer {TOKEN}"
}
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.post(
"https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/reset-heartbeat",
headers={
"Accept": "application/vnd.api+json",
"Authorization": "Bearer {TOKEN}"
}
).json()
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/{ACCOUNT}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/reset-heartbeat",
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(
"machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/reset-heartbeat",
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}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/reset-heartbeat")
.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}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/reset-heartbeat")
.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/actions/reset-heartbeat");
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}/machines/9c4c90c8-d4d3-4571-9363-4c7b0332a6a4/actions/reset-heartbeat \
-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",
"cores": null,
"ip": null,
"hostname": null,
"platform": "macOS",
"name": "Office MacBook Pro",
"requireHeartbeat": false,
"heartbeatStatus": "NOT_STARTED",
"heartbeatDuration": 600,
"lastHeartbeat": null,
"nextHeartbeat": null,
"metadata": {},
"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}"
}
},
"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"
}
}
}
}
}