Posted by:

David Greenwood

David Greenwood, Chief of Signal

If you are reading this blog post via a 3rd party source it is very likely that many parts of it will not render correctly. Please view the post on for the full interactive viewing experience.

In this post I will give you an introduction of TAXII 2.1 concepts to prepare you for the following posts in the tutorial series.

Note: this post is written for OASIS TAXII version 2.1. The concepts discussed are not always correct for earlier versions of OASIS TAXII. This post also talks about some specifics related to the Signal Corps implementation of a TAXII 2.1 Server, namely the exclusive use of STIX 2.1 content.

TAXII, or Trusted Automated Exchange of Intelligence Information, is a protocol designed specifically to share cyber threat intelligence.

TAXII enables organisations to share CTI by defining an API that allows for multiple sharing models; hub and spoke, peer to peer, source/subscriber.

Many often confuse STIX and TAXII, both created by OASIS.

STIX is a representation of threat intelligence – the content (covered in a previous tutorial).

TAXII is a standard way to share that content – the protocol.

A TAXII Server must be able to handle STIX content, but the two standards remain independent. It is possible to exchange STIX information without TAXII, and a TAXII server can also handle other intelligence formats. Similarly, a TAXII version 2.1 server can exchange STIX version 1.1 content.

One of the reasons that leads to confusion is this versioning of the standards. STIX is currently on version 2.1 (published 29th July 2019. TAXII, also currently on 2.1 (published 10th June 2021), tends to follow STIX version numbering, but again, is completely independent to STIX, as you can see from the publish dates of the specification.

At its core, TAXII has two main concepts,

  1. TAXII Servers: store created intelligence from and disseminate it to consumers (aka TAXII Clients)
  2. TAXII Clients: that create intelligence on and consume intelligence from TAXII Servers

The TAXII 2.1 specification defines two primary services to support a variety of common sharing models:

TAXII 2.1 Collections and Channels

  • Collections: An interface to a server-provided repository of objects that allows a producer to serve consumers in a request-response template.
  • Channels: Allows the exchange of information according to a publish-subscribe model.

In reality, the Channels service is not yet defined and I am not really sure why Oasis decided to include it in the published specification. As such, Channels will be touched on minimally in this tutorial.

Collections and Channels can be organized in different ways.

The search for information on a TAXII server depends on what you are looking for and how you want to receive it. Generally the design of Collections and Channels on a TAXII Server will look something like this

TAXII 2.1 Flow diagram

TAXII Clients contain the logic to consume data from and publish data to Collections (request/response) or Channels (streamed) via the TAXII Servers API. A TAXII Client might just be a script making API calls to the TAXII Server to retrieve data, though a few fully fledged productised TAXII Clients with more advanced logic to interact with TAXII APIs exist, some of which I will show you in this tutorial.

Before I get into those, I will demonstrate these concepts by going through the TAXII APIs.

Each request to a TAXII 2.1 API needs to include the Accept header application/taxii+json;version=2.1.

The TAXII 2.1 Specification recommends TAXII 2.1 Server APIs use HTTP Basic authorization which you will see used in the examples below.

In my examples I will also pass a custom user agent value in the request header too. As per the specification, TAXII Clients should use the User-Agent header in requests to a TAXII Server. I use a custom user agent to track requests on the TAXII Server.

Now I have shown the requirements of interacting with a TAXII API, let me show you some request to get you started.

Server Discovery

Typically a TAXII Client will first need to understand what is available to the user authenticating. This is done via the Server Discovery endpoint.

Think of discovery endpoint as the front door into a TAXII server. This endpoint helps clients navigate the content on the TAXII Server by showing all API Roots (where Collections are stored) available and information about the TAXII Server itself.

The GET request for the endpoint takes the form HOST/taxii2/.

curl -i https://MY_HOST/taxii2/ \
 -H "Accept: application/taxii+json;version=2.1" \
 -H "Authorization: Basic <BASE64 ENCODED CREDENTIALS>" \
 -A "Signals Corps Curl Demo Client/1.0"

Which returns a response that will look something like;

HTTP/1.1 200 OK
Content-Length: 387
Content-Type: application/taxii+json;version=2.1
Connection: close
  "title": "Signals Corps Demo TAXII Server",
  "description": "This TAXII Server is not real.",
  "contact": "[email protected]",
  "default": "https://MY_HOST/api/v1/group1",
  "api_roots": [

The api_roots property is typically the most important field for clients as it tells them the available API Roots available to the user (to discover).

API Root Information

In the previous example the server exposed the following API Roots to the user; /api/v1/group1, /api/v1/group2, and /api/v1/group3. There could be even more routes on this server, just not accessible to the authenticated user.

API Roots are logical groupings of TAXII Collections (and in the future, Channels). A TAXII server instance can support one or more API Roots.

API Roots offer a way for the owner of a TAXII Server to segment the data between groups of users. A user can have access to zero or more API Roots depending on the user permissions assigned to them on the TAXII server.

For example, a single TAXII Server could host multiple API Roots - one API Root for Collections and Channels used by Sharing Group A and another API Root for Collections and Channels used by Sharing Group B. Different consumers will have access to different groups (aka API Roots)/

To see what is inside an API Root you can use the Get API Root Information endpoint.

The GET request for the endpoint takes the form HOST/<API_ROOT>/.

Lets take a look at the /api/v1/group1 API Root;

curl -i https://MY_HOST/api/v1/group1 \
 -H "Accept: application/taxii+json;version=2.1" \
 -H "Authorization: Basic <base64 ENCODED CREDENTIALS>" \
 -A "Signals Corps Curl Demo Client/1.0"

Which returns;

HTTP/1.1 200 OK
Content-Length: 177
Content-Type: application/taxii+json;version=2.1
Connection: close
  "title": "Group 1 Sharing Group",
  "description": "An intelligence sharing group",
  "versions": ["application/taxii+json;version=2.1"],
  "max_content_length": 104857600

The response provides a general overview of the API Root, and in what protocol versions are used (in this case only TAXII 2.1 application/taxii+json;version=2.1) – this helps TAXII Clients understand if they can support the retrieval of content.

Next Up: Retrieving Objects

Now the available API Roots have been discovered, now the Collections within them can be queried.

Collections hold the actual cyber threat intelligence Object consumers are looking for. More on that in the next part of this tutorial.

Discuss this post

Signals Corps Slack

Never miss an update

Sign up to receive new articles in your inbox as they published.