API Developers Guide

Welcome to the API Developers Guide. This will cover most of the important concepts when using the API. Other details about the entities such as company, user, and notification filters can be found in the Portal user guide. https://ctci.atlassian.net/wiki/spaces/CTCIDOC/pages/340525116

This developer guide covers important points about using the API - Authentication, Error Handling, and such.


The server endpoint for requests is https://api.ctci.ai. There will be a dev sandbox version available soon.

Currently, all endpoints for requests use: /api/v1/<entity>.

The REST is our architectural standard for our API; it makes it easy to understand and easier to integrate into systems. In entity names, we are using the singular, not the plural. We use user and not users, as we think of an entity as being both singular and plural like a database table.






Is to retrieve one or more entries.


GET https://api.ctci.ai/api/v1/user retrieves all users.
GET https://api.ctci.ai/api/v1/user/<id> retrieves the specific users.


For the creation of an entity such as user, company, notification filter, notification group, notification delivery, processed, etc.


This is used to update entries.


PUT https://api.ctci.ai/api/v1/user/<id> would update the user with the <id>


This is used to delete an entry.


DELETE https://api.ctci.ai/api/v1/user/<id> would delete the user with the <id>

Specification - Swagger / OAS

To view the Swagger API, https://swagger.ctci.ai/

To use the Swagger/OAS specification in your tools, then use this URL. https://raw.githubusercontent.com/vmcommunity/swagger-api/main/cewl_download_swagger.yaml

If you want to generate client code for this then, go to https://editor.swagger.io/, and use the File menu and use open URL, then use the swagger URL above. Postman works well for testing this API as well - the code snippets in this document were generated from Postman.


For the API, you need to have credentials.

How to get your credentials:

  1. The preferred way: your company has been created by the CTCI team. If you want to start a trial, then send an email to sales@ctci.ai. Then register yourself as a user with an email address the same as the company email domain. You will then be able to log in and view the API tokens for your company. Depending on whether you have a CEWL subscription, is whether you see the full CEWL list or the restricted list.

  2. Register as a user, confirm your address and then perform a login API request with your user name and password. your username and password. This will give you restricted access to the CEWL list - only the NSA Chinese State Actors list. We call this the JWT tokens for API.

Sending API Request

Authentication Tokens must be sent in every request. The examples below are to download the CEWL list.

Using API Tokens - the preferred way

With API Tokens, you need to set a header “x-api-key” with your API Token from the . Examples are shown below. API Tokens cannot be used for interactive login using the CTCI Portal as they are only allowed for API.

Code Examples

Using Curl

curl --location --request GET 'https://api.ctci.ai/api/v1/cewl' \ --header 'x-api-key: <Put the API Token here>'


Using Python

# it needs requests import json import requests from os import environ import pandas as pd # grabs the CEWL API Token from environment variables, use whatever mechanism you want for secretes # TODO add your own exception handling around requests url = "https://api.ctci.ai/api/v1/cewl?q=" # empty filter will just download all of CEWL #query_filter = '' # put whatever you need in the query string query_filter = 'vendor="microsoft"' payload={} headers = { 'x-api-key': environ['CEWL_API_TOKEN'] } # TODO put in your exception handling with try_except around the requests call. response = requests.request("GET", f'{url}{query_filter}', headers=headers, data=payload) if response.status_code == 200: cve_data = json.loads(response.text) # to see what it returned # print(cve_data) if cve_data: # put it as a pandas dataframe cve_df = pd.DataFrame(cve_data["data"]) # now whatever ya need :) print(cve_df) else: print(f"Error status_code is:{response.status_code}") print("Error in retrieving CEWL entries, check API Token used") print("do your error handling")


Using JavaScript

var myHeaders = new Headers(); myHeaders.append("x-api-key", "<Put the API Token here>"); var requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; fetch("https://api.ctci.ai/api/v1/cewl", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error));

Using JWT Tokens - the other way

This is using the access_token from a login/password authenticated response.

Firstly do a login to get the access_token.


Getting Access Token using Curl


Getting Access Token using Python


Then the response will have an access token, use this in the next requests.

Code Examples using Access Token to call API

Using Curl

Using Python

Using JavaScript

Error Handling & Success Handling in the API

Where possible, we try to adhere to best practice standards for REST, and we try to adhere to good standards in error handling.

For HTTP Errors, we follow, where possible, the Problem Details for HTTP APIs: HTTP APIs (RFC 7807)

Basically, this standard has some common values on errors, and then you can add your own specific error values.

We support:

Problem Details Fields RFC 7807


Problem Details Fields RFC 7807



Used - it’s the HTTP return status


The summary of the response


More information about the response


Type of error


This is the request path


any specific value that is sent in the request that may help to diagnose the error


Used only on success, this is the JSON of the response for the successful request.

Error Response


Successful Response

The successful response uses a lot of fields as the error response, and it has an extra field, “data,” which carries the data about the request. Data is JSON.

A special note: if you try to update fields that you don’t have access to, it won’t update these fields, and if the request is properly formatted will return successfully. This was done as different fields that can be updated are dynamically determined by roles and such. This condition may change in the future and be an error.