Select programming language for code examples

linkEngines

Engines are automatically populated by the current packages and their releases. The below endpoints are read-only. To activate an engine, create a package implementing the desired engine e.g. pypi.

linkThe engine object

Below you will find the various attributes for the engine resource.

linkAttributes

  • linkdata.attributes.name

    stringread only

    The human-readable name of the engine. This can be used as an optional label.

  • linkdata.attributes.key

    stringread only

    The machine-readable key of the engine.

  • linkdata.attributes.created

    timestamp (iso8601)read only

    When the engine was created.

  • linkdata.attributes.updated

    timestamp (iso8601)read only

    When the engine was last updated.

linkRelationships

  • linkdata.relationships.account

    individual

    The account that the engine belongs to.

Example object

{
"data": {
"id": "606e5384-6beb-446c-90ab-38b147ecae1f",
"type": "engines",
"attributes": {
"name": "PyPI",
"key": "pypi",
"created": "2023-07-26T15:16:43.455Z",
"updated": "2023-07-26T15:16:43.455Z"
},
"relationships": {
"account": {
"links": {
"related": "/v1/accounts/<account>"
},
"data": {
"type": "accounts",
"id": "<account>"
}
}
},
"links": {
"related": "/v1/accounts/<account>/engines/606e5384-6beb-446c-90ab-38b147ecae1f"
}
}
}

linkRetrieve an engine

Retrieves the details of an existing engine.

linkAuthentication

  • linkBearer

    optional

    An authentication token with privileges to read the release engine: either an admin, the product it belongs to, an entitled license (via license key or a license token), or a user with an entitled license. If there are products with an OPEN distribution strategy, no authentication is required to read their associated engines.

linkURL Parameters

  • link<account>

    stringrequired

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

  • link<engine>

    stringrequired

    The identifier (UUID) or key of the engine to be retrieved.

linkReturns

A 200 OK response will be returned along with an engine 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>/engines/<engine>

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/<account>/engines/pypi", {
method: "GET",
headers: {
"Authorization": "Bearer <token>",
"Accept": "application/vnd.api+json"
}
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.get(
"https://api.keygen.sh/v1/accounts/<account>/engines/pypi",
headers={
"Authorization": "Bearer <token>",
"Accept": "application/vnd.api+json"
}
).json()
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/<account>/engines/pypi",
headers: [
"Authorization": "Bearer <token>",
"Accept": "application/vnd.api+json"
]
).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(
"engines/pypi",
Method.GET
);
 
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Accept", "application/vnd.api+json");
 
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>/engines/pypi")
.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>/engines/pypi")
.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("/engines/pypi");
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>/engines/pypi \
-H 'Authorization: Bearer <token>' \
-H 'Accept: application/vnd.api+json'

Example response / 200 OK

{
"data": {
"id": "606e5384-6beb-446c-90ab-38b147ecae1f",
"type": "engines",
"attributes": {
"name": "PyPI",
"key": "pypi",
"created": "2023-07-26T15:16:43.455Z",
"updated": "2023-07-26T15:16:43.455Z"
},
"relationships": {
"account": {
"links": {
"related": "/v1/accounts/<account>"
},
"data": {
"type": "accounts",
"id": "<account>"
}
}
},
"links": {
"related": "/v1/accounts/<account>/engines/606e5384-6beb-446c-90ab-38b147ecae1f"
}
}
}

linkList all engines

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

linkAuthentication

  • linkBearer

    optional

    An authentication token with privileges to read the engines: either an admin, the product the releases belong to, an entitled license (via license key or a license token), or a user with an entitled license. If there are products with an OPEN distribution strategy, no authentication is required to read their associated engines.

linkURL Parameters

  • link<account>

    stringrequired

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

linkQuery Parameters

  • linklimit

    integerdefault=10

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

    /v1/accounts/<account>/engines?limit=25
  • linkpage

    object<string, integer>

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

    /v1/accounts/<account>/engines?page[size]=15&page[number]=2

linkReturns

A 200 OK response will be returned along with a list of engine 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>/engines

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/<account>/engines?limit=15", {
method: "GET",
headers: {
"Authorization": "Bearer <token>",
"Accept": "application/vnd.api+json"
}
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.get(
"https://api.keygen.sh/v1/accounts/<account>/engines?limit=15",
headers={
"Authorization": "Bearer <token>",
"Accept": "application/vnd.api+json"
}
).json()
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/<account>/engines?limit=15",
headers: [
"Authorization": "Bearer <token>",
"Accept": "application/vnd.api+json"
]
).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("engines", Method.GET);
 
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Accept", "application/vnd.api+json");
 
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>/engines")
.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>/engines")
.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("/engines");
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>/engines?limit=15 -g \
-H 'Authorization: Bearer <token>' \
-H 'Accept: application/vnd.api+json'

Example response / 200 OK

{
"data": [
{
"id": "606e5384-6beb-446c-90ab-38b147ecae1f",
"type": "engines",
"attributes": {
"name": "PyPI",
"key": "pypi",
"created": "2023-07-26T15:16:43.455Z",
"updated": "2023-07-26T15:16:43.455Z"
},
"relationships": {
"account": {
"links": {
"related": "/v1/accounts/<account>"
},
"data": {
"type": "accounts",
"id": "<account>"
}
}
},
"links": {
"related": "/v1/accounts/<account>/engines/606e5384-6beb-446c-90ab-38b147ecae1f"
}
},
...
]
}

linkPyPI engine

Keygen implements PyPI's simple repository format for pip packages.

For more information on the format, see PEP 503.

You may also use the pypi.pkg.keygen.sh subdomain, e.g. https://pypi.pkg.keygen.sh/<account>/simple.

linkAuthentication

  • linkBearer

    optional

    An authentication token with privileges to read the releases: either an admin, the product it belongs to, an entitled license (via license key or a license token), or a user with an entitled license. If there are products with an OPEN distribution strategy, no authentication is required to read their associated releases.

linkURL Parameters

  • link<account>

    stringrequired

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

linkReturns

A 200 OK response will be returned along with an HTML document containing links to the package artifacts, in accordance with PEP 503.

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>/engines/pypi/simple

linkInstall with --index-url

Install a package that implements the pypi engine using pip. Only packages that implement the pypi engine will be available for install. Packages for other engines, or packages without an engine, will not be available.

In addition, only packages which are available to the current requestor will be included, e.g. if you don't authenticate then only OPEN packages will be included.

Please prefer --index-url over --extra-index-url, for security reasons. Because pip does not lock dependencies to specific repositories, and because pip provides no protection from package spoofing, we recommend using Keygen as the sole package index. All non-Keygen packages will be securely redirected to PyPI for fulfillment (also known as a "pass through" PyPI repository).

This prevents pip from installing a package with the same name from PyPI instead of Keygen, preventing a supply chain attack vector.

Alternatively, you can add the --index-url flag to your requirements.txt.

Example with license authentication

pip install <package> \
--index-url https://license:<key>@api.keygen.sh/v1/accounts/<account>/engines/pypi/simple

Example without authentication

pip install <package> \
--index-url https://api.keygen.sh/v1/accounts/<account>/engines/pypi/simple

linkInstall with pypi.conf

Alternatively, you can configure the engine globally via pypi.conf. This will make pip install all packages through Keygen. Keygen is a pass-through PyPI repository, meaning we will redirect all non-Keygen packages to PyPI.

Please see earlier security notice on --index-url vs --extra-index-url.

Example pypi.conf

[global]
index-url = https://license:<key>@api.keygen.sh/v1/accounts/<account>/engines/pypi/simple

linkInstall with .pypirc

Alternatively, you can configure the engine globally via .pypirc.

Notes on publishing

Please note that we DO NOT support uploading Python packages via twine. To upload a new version of a package, you can use the CLI or the UI to draft a new package release, then upload your whl and other distribution artifacts.

In addition, with the example .pypirc configuration, you may continue to upload to PyPI's public repository using twine like so:

twine upload dist/* --repository pypi

Example .pypirc

[distutils]
index-servers =
keygen # NB: see note above
 
[keygen]
repository = https://api.keygen.sh/v1/accounts/<account>/engines/pypi/simple
username = license
password = <key>
 
[pypi]
repository = https://upload.pypi.org/legacy/
 
[testpypi]
repository = https://test.pypi.org/legacy/

linkTauri engine

Keygen implements a dynamic update server for Tauri applications.

For a Tauri plugin, check out tauri-plugin-keygen-rs.

You may also use the tauri.pkg.keygen.sh subdomain, e.g. https://tauri.pkg.keygen.sh/<account>/<package>.

linkAuthentication

  • linkBearer

    optional

    An authentication token with privileges to read the releases: either an admin, the product it belongs to, an entitled license (via license key or a license token), or a user with an entitled license. If there are products with an OPEN distribution strategy, no authentication is required to read their associated releases.

linkURL Parameters

  • link<account>

    stringrequired

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

  • link<package>

    stringrequired

    The identifier (UUID) or key of the package.

linkQuery Parameters

  • linkplatform

    stringrequired

    The identifier (UUID) or key of the target platform.

    /v1/accounts/<account>/engines/tauri/<package>?platform=linux
  • linkarch

    stringrequired

    The identifier (UUID) or key of the target arch.

    /v1/accounts/<account>/engines/tauri/<package>?arch=x86_64
  • linkversion

    stringrequired

    The current application version.

    /v1/accounts/<account>/engines/tauri/<package>?version=1.0.0
  • linkconstraint

    stringoptional

    The version constraint for the upgrade. For example, constraint=1.0 will constrain all upgrades to version 1.x, while constraint=1.0.0 will constrain to version 1.0.x. This is useful if a given license is only entitled to a specific version range. Major version is required.

    You can also use constraints to constrain to a specific prerelease tag, such as constraint=1-beta, or to a specific build tag like constraint=1%2Bfoo (note the URL-encoded + symbol).
    /v1/accounts/<account>/engines/tauri/<package>?constraint=1.0
  • linkchannel

    stringoptional

    The release channel. One of: stable, rc, beta, alpha or dev. The rc channel will include stable releases. The beta channel will include rc and stable. Alpha will include beta, rc, and stable. Dev will only include releases on the dev channel (you can think of it as 'nightly' or 'edge', i.e. following a master branch).

    /v1/accounts/<account>/engines/tauri/<package>?channel=beta

linkReturns

A 200 OK response will be returned along with the update 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>/engines/tauri/<package>

linkUpdate with Tauri updater

You can use Keygen with Tauri's native updater to implement auto-updates for your Tauri app. Releases can be drafted and artifacts uploaded via the CLI or UI.

Please note that signatures MUST be explicitly set on uploaded artifacts. We do not automatically read accompanying .sig artifacts.

Using the CLI, this would look something like this:

tauri build # build app normally
 
# draft a new release
keygen new --channel 'stable' --version '1.0.0' --package 'myapp'
 
# upload artifacts
keygen upload target/release/bundle/appimage/myapp.AppImage.tar.gz \
+ --signature "$(cat target/release/bundle/appimage/myapp.AppImage.tar.gz.sig)" \
--release '1.0.0' \
--platform 'linux' \
--arch 'x86_64'
 
# upload others...
 
keygen publish --release '1.0.0'

Example tauri.conf.json

{
"tauri": {
"updater": {
"active": true,
"endpoints": [
"https://api.keygen.sh/v1/accounts/demo/engines/tauri/app?platform={{target}}&arch={{arch}}&version={{current_version}}"
],
"dialog": false,
"pubkey": "..."
}
}
}

Example updater with license authentication

tauri::Builder::default()
.setup(|app| {
let handle = app.handle();
tauri::async_runtime::spawn(async move {
match handle
.updater()
.header("Authorization", "License <key>")
.unwrap()
.check()
.await
{
Ok(update) => {
if update.is_update_available() {
update.download_and_install().await.unwrap();
}
}
Err(e) => {
println!("failed to update: {}", e);
}
}
});
Ok(())
});

linkRaw engine

The raw engine can be to create dynamic artifact download links that point to raw binaries, installers, etc.

These artifact download links are scoped to a product, optional package, and release.

You may also use the raw.pkg.keygen.sh subdomain, e.g. https://raw.pkg.keygen.sh/<account>/<product>[/@<package>]/<release>/<artifact>.

linkAuthentication

  • linkBearer

    optional

    An authentication token with privileges to read the artifacts: either an admin, the product it belongs to, an entitled license (via license key or a license token), or a user with an entitled license. If there are products with an OPEN distribution strategy, no authentication is required to read their associated releases.

linkURL Parameters

  • link<account>

    stringrequired

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

  • link<product>

    stringrequired

    The identifier (UUID) or code of the product.

  • link<package>

    string

    The identifier (UUID) or key of the package. If included, it must be prefixed with the @ symbol.

  • link<release>

    stringrequired

    The identifier (UUID), version, or tag of the release.

  • link<artifact>

    stringrequired

    The identifier (UUID) or filename of the artifact.

linkReturns

A 303 See Other redirect will be returned, pointing to the artifact's canonical URL.

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>/engines/raw/<product>[/@<package>]/<release>/<artifact>

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/<account>/engines/raw/relay/latest/install.sh, {
redirect: "manual",
method: "GET",
headers: {
"Authorization": "Bearer <token>"
}
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.get(
"https://api.keygen.sh/v1/accounts/<account>/engines/raw/relay/latest/install.sh,
allow_redirects=False,
headers={
"Authorization": "Bearer <token>"
}
).json()
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/<account>/engines/raw/relay/latest/install.sh,
headers: [
"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(
"engines/raw/relay/latest/install.sh",
Method.GET
);
 
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>/engines/raw/relay/latest/install.sh)
.header("Authorization", "Bearer <token>")
.asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;
 
HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<account>/engines/raw/relay/latest/install.sh)
.header("Authorization", "Bearer <token>")
.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.set_request_uri("/engines/raw/relay/latest/install.sh");
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>/engines/raw/relay/latest/install.sh \
-H 'Authorization: Bearer <token>'

Example response / 303 See Other

Location: https://api.keygen.sh/v1/accounts/<account>/artifacts/30c64dcd-a74d-4f0d-8479-8745172a4817/install.sh