API

Developers

API

Kolide’s REST-based API provides a simple way to programmatically read and interact with resources in your Kolide account.

Full Documentation

To explore all the functionality that our API offers, you can view the complete API reference on readme.io.

Creating an API Key

Note:
Only admins with “Full Access” can create or manage API Keys in Kolide.

The Kolide REST API uses token-based authentication. Kolide administrators can obtain a token by creating an API Key entry. To create a key, follow these steps:

  1. Click your user avatar in the upper-right corner of the Kolide UI.

  2. In the dropdown menu, click Settings.

  3. In the menu on the left, click Developers.

  4. In the sub-menu that appears, click API Keys.

  5. On the next screen, click Create New Key.

  6. In the modal that appears, provide a name for the Key and the name of a Kolide administrator who will be responsible for the API Key’s usage. Both of these values will appear in both the Audit Log and the Privacy Center.

  7. If available, select any special write permissions you’d like to grant to this specific key.

  8. Click Save.

  9. Once saved, the secret token is available in the table. Click on the duplicate button to copy the token to your clipboard.

Note:
The secret token can be accessed by any Kolide admins with “Full Access”. To do so, they must click the Reveal Secret button, and the action will be logged in the Kolide Audit Log.

Authentication

The Kolide REST API uses token-based authentication. To obtain a token, first create an API Key.

In addition to passing the token via the Authorization header (see the example below) on each request, you’ll also need to specify the API version using a specific HTTP header, X-Kolide-Api-Version. The current API version is 2023-05-26.

An example request using curl:

curl -H "Content-Type: application/json" \
     -H "X-Kolide-Api-Version: 2023-05-26" \
     -H "Authorization: Bearer $KOLIDE_API_TOKEN" \
     "https://api.kolide.com/audit_logs"

An example JSON response for the above request:

{
  "data": [...],
  "pagination": {
    "next": "https://api.kolide.com/audit_logs?per_page=2&cursor=DOscDOc=",
    "next_cursor": "DOscDOc=",
    "current_cursor": "",
    "count": 2
  }
}

Pagination

The Kolide API uses a cursor-based pagination strategy.

On any endpoint that returns a list or collection of entities, you may supply a cursor URL query parameter to fetch records beyond the first page of results:

curl -H "Content-Type: application/json" \
     -H "X-Kolide-Api-Version: 2023-05-26" \
     -H "Authorization: Bearer $KOLIDEAPIKEY" \
     "https://api.kolide.com/audit_logs?per_page=25"
{
  "pagination": {
    "next": "https://api.kolide.com/audit_logs?per_page=25&cursor=ABCDJ",
    "next_cursor": "ABCDJ",
    "current_cursor": "JDCBA",
    "count": 25,
  }
  "data": [...]
}

A request with a blank cursor parameter will return the first page of results. The response has a pagination section that includes the cursor for the next page of results. For your convenience, we also include a next attribute that is a pre-built URL with the next cursor already specified. See the example above.

The default page length is 25 records, but you can include a per_page query parameter to specify a different page length between 1 and 100.

If the values for cursor and next are blank, that indicates there are no more records to display and that you have reached the last page.

Code Examples

Here are a couple more simple examples of API clients iterating through a list of records:

Ruby

require "uri"
require "net/http"
require "openssl"
require "json"

# Find your API key at:
# https://app.kolide.com/x/settings/admin/developers/api_keys

key = ENV.fetch("APIKEY", "")
next_url = "https://api.kolide.com/audit_logs?per_page=25&cursor="
more_records = true
results = []

while more_records do
  url = URI(next_url)
  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true

  request = Net::HTTP::Get.new(url)
  request["accept"] = "application/json"
  request["Authorization"] = "Bearer #{key}"
  request["X-Kolide-API-Version"] = "2023-05-26"

  response = http.request(request)

  case response
  when Net::HTTPSuccess then
    resp = JSON.parse(response.read_body)
    next_url = resp["pagination"]["next"]
    results += resp["data"]
    more_records = next_url.to_s != ""
  else
    more_records = false
    puts "Unexpected response code: #{ response.code }"
  end
end

puts results

Javascript

const https = require("https");

// Find your API key at:
// https://app.kolide.com/x/settings/admin/developers/api_keys
const api_key = process.env.APIKEY;

function fetchRecords(url) {
  return new Promise((resolve, reject) => {
    let options = {
      method: "GET",
      headers: {
        accept: "application/json",
        authorization: "Bearer " + api_key,
        "x-kolide-api-version": "2023-05-26",
      },
    };

    const req = https.request(url, options, (res) => {
      let data = "";
      res.on("data", (chunk) => {
        data += chunk;
      });

      res.on("end", () => {
        if (res.statusCode !== 200) {
          reject("Error response: " + res.statusCode);
        } else {
          resolve(data);
        }
      });
    });
    req.on("error", (error) => {
      reject(error);
    });

    req.end();
  });
}

async function getAllRecords() {
  let moreRecords = true;
  let url = "https://api.kolide.com/devices?cursor=";
  let records = [];

  while (moreRecords == true) {
    try {
      let response = await fetchRecords(url);
      let resp = JSON.parse(response);
      records = records.concat(resp["data"]);
      let nextUrl = resp["pagination"]["next"];
      if (nextUrl != "" && nextUrl != null) {
        moreRecords = true;
        url = nextUrl;
      } else {
        moreRecords = false;
      }
    } catch (error) {
      console.error("ERROR:");
      console.error(error);
      moreRecords = false;
    }
  }

  console.log(records);
}

getAllRecords();

Some list-style API endpoints support search. The endpoints that support search will have a query request parameter described in the API reference documentation for that endpoint. A search query is specified by adding a query parameter to the request URL.

The general syntax for specifying a search query is:

<field><operator><value>

  • <field> is the name of the attribute on the entity that you wish to search or filter by. The searchable fields are listed in the API reference documentation for each endpoint.

  • <operator> must be safely url-encoded, and may be one of the following:

    • : (exact match)
    • ~ (substring match)
    • > (greater than) only supported for datetime fields
    • < (less than) only supported for datetime fields
  • <value> is the value you wish to compare against. It must be quoted with double-quotes (") if it contains spaces.

For example, to search for people with an email containing the string @example.com, you would use the following query:

api.kolide.com/people?query=email~"@example.com"

To search for all issues that were detected before/after a certain datetime, you would use the following queries:

api.kolide.com/issues?query=detected_at%3C"2021-01-01T09:31:04Z"

and

api.kolide.com/issues?query=detected_at%3E"2021-01-01T09:31:04Z"

Note that timestamp values should be formatted using the ISO8601 format, and should quoted with double-quotes (").

Multiple search clauses can be combined with AND and OR. To expand on the examples above, if you wanted to find all the issues that were resolved within a certain time period, you could combine a resolved_at> search clause with a resolved_at< search clause:

api.kolide.com/issues?query=resolved_at>"2021-01-01T09:31:04Z" AND resolved_at<"2021-01-31T23:59:59"

url-encoded, this url would be:

api.kolide.com/issues?query=resolved_at%3E%222021-01-01T09:31:04Z%22%20AND%20resolved_at%3C%222021-01-31T23:59:59%22

Special Write Permissions

By default, all API Keys only have access to read-only endpoints. If you want a key to make changes to the Kolide system, you must first grant it individual write permissions.

Premium Feature:
Write API access is only available for customers who are subscribed to Kolide Max. For more information and how to upgrade, please see our pricing page.

When granting a key write permissions, you must also provide a rationale for why the permission is needed. This provides necessary information other administrators and end-users can use to understand why internal apps or processes are using a specific permission.

The following is a complete list of permissions:

Remove Devices

Added On: January 15th, 2024

Description: Allows an API Key to unregister and delete devices from Kolide

API Endpoints:

Manage User Requests

Added On: December 21st, 2023

Description: Allows an API Key to approve or deny end-user issue exemption requests and device registration requests

API Endpoints:

Manage Device Groups

Added On: August 31st, 2023

Description: Allows an API Key to add or remove devices from Device Groups.

API Endpoints:

Refresh Check

Added On: November 1st, 2023

Description: Allows an API Key to re-run a Kolide Check on devices enrolled in Kolide.

API Endpoints:

Update Devices

Added On: November 1st, 2023

Description: Allows an API Key to edit the configuration of devices.

API Endpoints:

Usage Limits

Kolide’s API supports a maximum of 270 requests per minute. When this limit is exceeded, Kolide will return a HTTP status code 429 (Too Many Requests). In this 429 request, Kolide will include headers that adhere to the RateLimit Header Fields for HTTP draft standard.

Here is the example of the headers Kolide will send when your client exceeds the usage limits.

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 20
RateLimit-Limit: 15
Ratelimit-Remaining: 0
Ratelimit-Reset: 1698610800

API Token Format

The format for Kolide API keys is as follows:

$PREFIX_$VERSION_$SECRET

This predictable format allows code-scanning tools like semgrep to detect when a secret has accidentally been committed to your version control system of choice and need to be rotated.

The value for $PREFIX is currently: k2sk

An example key will look something like: k2sk_v1_A2UYhW7OPt2jKKLqmFcaGNK7