Investigations APIs

The Investigations Application Programming Interfaces (APIs) let you build, delete, modify, or list the Investigation objects in USM Central. You can also use the APIs to download attachments, add evidence, or create notes for the Investigation object.

The Investigations APIs are based on the Representational State Transfer (REST) architecture standard. You must access the APIs using Hypertext Transfer Protocol Secure (HTTPS) on port 443. This document explains how to access the endpoints, how to construct your requests, and what errors you may receive.

Authentication

The Investigations APIs implements OAuth 2.0 for endpoint protection, which provides token-based authentication and authorization over HTTPS. To generate the token, you must first obtain the following items:

  • URL of your USM Central instance

    This URL is in the form of https://{usm-central-subdomain}.alienvault.cloud. The {usm-central-subdomain} portion identifies your USM Central instance.

  • Email and password of an active user on the USM Central instance

    Important: This user must have the Manager role. You can use an existing user or create a new user dedicated to accessing the Investigations APIs.

With both information at hand, you can construct an authentication request like this:

curl --request POST \
'https://{usm-central-subdomain}.alienvault.cloud/mssp/idp/login/false' \
--header 'Content-Type: application/json' \	
--data-raw '{ 
	"username": "{email of a USM Central user}", 
	"password": "{password of this user}" 
}'

Replace {usm-central-subdomain}, {email of a USM Central user}, and {password of this user} with the information you've collected for authentication.

If you use a development tool such as Postman, your request may look like this:

auth request in Postman

A successful response to this request contains two tokens, access_token and id-token:

{
  "access_token": "access token",
  "id-token": "ID token",	
  "scope": "",
  "expires_in": 3600,
  "token_type": "Bearer"	
}

The id-token identifies the user whereas the access_token provides authorization information of the user, such us the user role assigned in USM Central. You must use the id-token in making requests to the other Investigations API endpoints.

Note: Each token is valid for 60 minutes. After they expire, you can re-authenticate to get new tokens. Alternatively, you can generate a new token automatically every time a request is sent.

Requests and Responses

All connections to the Invesigations APIs use the HTTPS protocol. The base URL is: https://investigations.us-east-1.prod.alienvault.cloud/investigations/v3.

To save space, this URL is represented by {Base URL} for the remainder of this document.

The following examples use the /investigations endpoint to demonstrate how to formulate your requests and what their corresponding responses are. See Investigations API Reference for the full list of endpoints and more examples.

Example 1: Create an Investigation

To create an investigations in the system, enter this command:

curl --request POST '{Base URL}/investigations' \
--header 'Authorization: Bearer {id-token}' \
--data-raw '{ 
  "title": "Test", 
  "description": "This is a test.",
  "deployment": "{usm-anywhere-subdomain}",					
  "severity": "Medium",					
  "status": "Open",					
  "intent": "Environmental Awareness"					  
}'

Replace {id-token} with the token you obtain through authentication. {usm-anywhere-subdomain} represents the Uniform Resource Identifier (URI) of the USM Anywhere instance connected to USM Central. For example, the "abc123" in https://abc123.alienvault.cloud.

The API responses are JSON objects with a structure that allows pagination using Hypermedia as the Engine of Application State (HATEOAS)-style links. You will receive this response for the previous request:

{
  "title": "Test",
  "description": "This is a test.",
  "deployment": "{usm-anywhere-subdomain}",
  "status": "Open",
  "severity": "Medium",
  "intent": "Environmental Awareness",
  "assignedTo": "userA <1a378571-cfe6-414c-9cd7-1b2b0435632c>",
  "id": "61398658-b171-4f44-a804-4fdb34101505",
  "tenant": "695a1bff-5973-41ee-8b97-9c738f6b9ab8",
  "lastModified": {
    "by": "userA <1a378571-cfe6-414c-9cd7-1b2b0435632c>",
    "on": "2021-06-01T22:22:32.101097Z"
  },
  "created": {
    "by": "userA <1a378571-cfe6-414c-9cd7-1b2b0435632c>",
    "on": "2021-06-01T22:22:32.101097Z"
  },
  "private": false,
  "_embedded": {
    "notes": {
      "elements": 0
    },
    "evidence": {
      "elements": 0
    },
    "attachments": {
      "elements": 0
    },
    "history": {
      "elements": 0
    }					
  },
  "_links": {
    "self": {
      "href": "{Base URL}/investigations/61398658-b171-4f44-a804-4fdb34101505"
    },
    "notes": {
      "href": "{Base URL}/investigations/61398658-b171-4f44-a804-4fdb34101505/notes"
    },
    "evidence": {
      "href": "{Base URL}/investigations/61398658-b171-4f44-a804-4fdb34101505/evidence"
    },
    "attachments": {
      "href": "{Base URL}/investigations/61398658-b171-4f44-a804-4fdb34101505/attachments"
    },
    "history": {
      "href": "{Base URL}/investigations/61398658-b171-4f44-a804-4fdb34101505/history"
    }
  }				
}

Example 2: List the Investigations

To list all the investigations in the system, enter this command:

curl --request GET '{Base URL}/investigations' \
--header 'Authorization: Bearer {id-token}'

Replace {id-token} with the token you obtain through authentication.

The response contains a list of investigations followed by the pagination. For example:

{
  "investigations" : [
    {
      "title": "Test",
      "description": "This is a test.",
      "deployment": "{usm-anywhere-subdomain}",
      "status": "Open",
      "severity": "Medium",
      "intent": "Environmental Awareness",
      "assignedTo": "userA <1a378571-cfe6-414c-9cd7-1b2b0435632c>",
      "id": "61398658-b171-4f44-a804-4fdb34101505",
      "tenant": "695a1bff-5973-41ee-8b97-9c738f6b9ab8",
      "lastModified": {
        "by": "userA <1a378571-cfe6-414c-9cd7-1b2b0435632c>",
        "on": "2021-06-01T22:22:32.101097Z"
      },
      "created": {
        "by": "userA <1a378571-cfe6-414c-9cd7-1b2b0435632c>",
        "on": "2021-06-01T22:22:32.101097Z"
      },
      "private": false,
      "_embedded": {
        "notes": {
          "elements": 0
        },
          "evidence": {
          "elements": 0
        },
          "attachments": {
          "elements": 0
        },
          "history": {
          "elements": 0
        }								
      },
      "_links": {
        "self": {
          "href": "{Base URL}/investigations/61398658-b171-4f44-a804-4fdb34101505"
        },
        "notes": {
          "href": "{Base URL}/investigations/61398658-b171-4f44-a804-4fdb34101505/notes"
        },
        "evidence": {
          "href": "{Base URL}/investigations/61398658-b171-4f44-a804-4fdb34101505/evidence"
        },
        "attachments": {
          "href": "{Base URL}/investigations/61398658-b171-4f44-a804-4fdb34101505/attachments"
        },
        "history": {
          "href": "{Base URL}/investigations/61398658-b171-4f44-a804-4fdb34101505/history"
        }
      }
    }
  ],
  "page" : {
	"size" : 20,
	"totalElements" : 1,
	"totalPages" : 1,
	"number" : 1
  },
  "_links" : {
	"self" : {
	  "href" : "{Base URL}/investigations"
	}
  }
}

See Investigations API Reference for a sample response with multiple pages.

Example 3: List the Investigations with Limited Fields

If you are only interested in some of the fields in the investigation or want to save bandwidth, you can specify which fields of the investigation you want to see using the following syntax:

{Base URL}/investigations?fields={name of fields separated by comma}

For example, you can enter this command:

curl --request GET \
'{Base URL}/investigations?fields=title,description' \
--header 'Authorization: Bearer {id-token}'

Replace {id-token} with the token you obtain through authentication.

The response looks similar to Example 2 but each investigation only contains two fields, title and description:

{
  "investigations" : [
    {
      "title": "Test",
      "description": "This is a test.",
        "_embedded": {
          "notes": {
            "elements": 0
          },
          "evidence": {
            "elements": 0
          },
          "attachments": {
            "elements": 0
          },
          "history": {
            "elements": 0
          }	
	  },
      "_links": {
        "self": {
          "href": "{Base URL}/investigations/{id}"
          "templated": true
        },
        "notes": {
          "href": "{Base URL}/investigations/{investigationId}/notes"
          "templated": true
        },
        "evidence": {
          "href": "{Base URL}/investigations/{investigationId}evidence"
          "templated": true
        },
        "attachments": {
          "href": "{Base URL}/investigations/{investigationId}/attachments"
          "templated": true
        },
        "history": {
          "href": "{Base URL}/investigations/{id}/history"
          "templated": true
        }
      }
    }
  ],
  "page" : {
	"size" : 20,
	"totalElements" : 1,
	"totalPages" : 1,
	"number" : 1
  },
  "_links" : {
	"self" : {
	  "href" : "{Base URL}/investigations?fields=title,description"
	}
  }
}

Example 4: Search for Investigations

If you only want to retrieve a subset of the investigations, you can limit what's included in the response using a search query:

{Base URL}/investigations?q={field name}{operator}{search string}

where

  • {field name} can be any field in the response except for deployment. The names are case sensitive.
  • {operator} can be ==, !=, <, <=, >, >=, =in=, or =out=.
  • {search string} is case sensitive. It must be enclosed in matching quotation marks (' or ") if it contains any white spaces or wild cards.
  • You can use wild cards (*) in the search string. For example, title=="Test*", which means all titles start with the word "Test".
  • The search string for =in= and =out= must be a list of values enclosed in parentheses. For example, title=in=("Test 1", "Test 2"), which means the title is "Test 1" or "Test 2". =in= means included in the list while =out= means NOT included in the list.
  • You can't use =in= or =out= on time fields such as created.on or lastModified.on.
  • You can combine different search criteria using logical operators, AND (;) and OR (,). For example, title=="Test 1",title=="Test 2", which means the title is "Test 1" or "Test 2".
  • The supported format for created.on and lastModified.on is YYYY-MM-DDThh:mm.

For example, you can enter this command:

curl --request GET \
'{Base URL}/investigations?q=title==%22Test*%22created.on%3E2021-06-22T13:10' \
--header 'Authorization: Bearer {id-token}'

Replace {id-token} with the token you obtain through authentication. %22 is the HTML encoding for a double quotation mark ("), %3E is the HTML encoding for greater than (>).

The response will contain all investigations whose title starts with the word "Test" and created after June 22, 2021 at 13:10.

Example 5: Sort the Investigations

When retrieving investigations, you can sort the results using this syntax:

{Base URL}/investigations?sort={name of the field to sort by},{sorting order}

where

  • {name of the field to sort by} can be id, title, created or lastModifed.

  • (sorting order} can be asc (ascending) or desc (descending).

  • There is no space after the comma (,).

  • You can combine the search query (q=) with sorting using the ampersand (&) as follows, ?q={query}&sort={name of the field to sort by},{sorting order}.

For example, you can enter this command:

curl --request GET \
'{Base URL}/investigations?q=title==%22Test*%22&sort=created.on,desc' \
--header 'Authorization: Bearer {id-token}'

Replace {id-token} with the token you obtain through authentication. %22 is the HTML encoding for a double quotation mark (").

The response will contain all investigations whose title starts with the word "Test" sorted by the created.on field in descending order.

Example 6: Display Investigations in the CSV Format

If desired, you can retrieve the investigations as comma-separated values (CSV). All you need is to add or change the Accept header to text/csv, like this:

curl --request GET '{Base URL}/investigations' \
--header 'Accept: text/csv' \					
--header 'Authorization: Bearer {id-token}'

Replace {id-token} with the token you obtain through authentication.

The response is the same as in Example 2 but displays as CSV:

id, i3, title, assignedTo, deployment, severity, intent, status, description, created.by, created.on, lastUpdated.on, notes.elements, evidence.elements, attachments.elements, changes.elements
61398658-b171-4f44-a804-4fdb34101505, , Test, userA <1a378571-cfe6-414c-9cd7-1b2b0435632c>, {usm-anywhere-subdomain}, Medium, Environmental Awareness, Open, This is a test., userA <1a378571-cfe6-414c-9cd7-1b2b0435632c>, 2021-06-01T22:22:32.101097Z, userA <1a378571-cfe6-414c-9cd7-1b2b0435632c>, 2021-06-01T22:22:32.101097Z, 0, 0, 0, 1

Note: In this sample output, a space is added after each comma to improve readability.

The first line in the response lists the case-sensitive fields of the investigation in order. This order remains the same for all requests unless you limit the fields using the fields parameter. For example:

curl --request GET \
'{Base URL}/investigations?fields=title,description' \
--header 'Accept: text/csv' \					
--header 'Authorization: Bearer {id-token}'

Then the response only contains the fields you've specified:

title,description
Test,This is a test.

Similarly, you can use the q parameter in the same way as in Example 4 but change the Accept header to text/csv:

curl --request GET \
'{Base URL}/investigations?q=title==%22Test*%22created.on%3E2021-06-22T13:10' \
--header 'Accept: text/csv' \					
--header 'Authorization: Bearer {id-token}'

USM-Specific Errors

If you receive an error for your request, there can be many possible reasons. Some may be general syntax errors while others are USM specific. The following table summarizes the errors relevant to the Investigations API schema and provides a solution when applicable.

Possible Error Codes and Messages
USM Error Code HTTP Status Code Error Message Solution
USM-1001 400 The request was missing one or more required fields. The response tells you which variable is missing. Add the variable to your request and resubmit.
USM-1002 406 The value specified for the Accept header in the request is not supported. The following values are supported by this endpoint: The response tells you what value is supported for the Accept header. Update the header in your request and resubmit.
USM-1003 400 Submitted filenames are only permitted to use letters a-z and A-Z; numbers 0-9; and special characters period, underscore, and hyphen.  
USM-1004 415 The value specified for the Accept header in the request is not supported. The following values are supported by this endpoint: The response tells you what value is supported for the Accept header. Update the header in your request and resubmit.
USM-1005 400 Validation on an argument failed.  
USM-1006 400 The provided search criteria has errors. Acceptable comparison operators are ==, !=, <, <=, >, >=, =in=, and =out=. Acceptable logical operators are ;(and) and ,(or). Search strings with whitespace must be surrounded by single quotes.

The response tells you which operator specified for the q parameter is wrong. Update the operator in your request and resubmit. See Example 4: Search for Investigations for more details.

USM-1007 400 The provided search criteria has errors. Invalid field name provided. You receive this error if any of the names specified for the q parameter is unsupported or misspelled. The response tells you which field name is invalid. Update the search query in your request and resubmit.
USM-1008 415 The Content-Type header was correct but the body does not appear to be a valid multiform type. The Content-Type header in your request is set to multipart/form-data, and you have specified the boundary parameter. However, the separator used in your file is different than the boundary parameter. Update the header in your request and resubmit.
USM-1009 415 The request was rejected because no multipart boundary was found in the Content-Type header. The Content-Type header in your request is set to multipart/form-data, but the boundary parameter is missing. Update the header in your request and resubmit. For example, --header 'Content-Type: multipart/form-data; boundary=???'.
USM-1010 400 The provided field name is invalid. You receive this error if any of the names specified for the fields parameter is invalid or misspelled. The response tells you which field name is invalid. Update the field name in your request and resubmit.

Generate the ID Token Automatically

Each ID token is only valid for 60 minutes. After they expire, you can re-authenticate to get new tokens, or you can generate an ID token automatically each time you send a request. The request will take more time because it combines two steps, fetching the token and sending the request, but the difference is minimal. This approach eliminates the need to get a new token every 60 minutes.

Command Line Example

To generate the ID token automatically from the command line

  1. Create an variable named $ID_TOKEN:

    export ID_TOKEN=$(curl --request POST \
    'https://{usm-central-subdomain}.alienvault.cloud/mssp/idp/login/false' \
    --header 'Content-Type: application/json' \	
    --data-raw '{ 
    	"username": "{email of a USM Central user}", 
    	"password": "{password of this user}" 
    }'|grep -o -E "\"id_token\":\"[^\"]+\"" | awk -F\: '{gsub(/"/, "", $2); \
    print $2}')

    Replace {usm-central-subdomain}, {email of a USM Central user}, and {password of this user} with the information you've collected for authentication.

  2. Use $ID_TOKEN in your request. For example:

    curl --request GET '{Base URL}/investigations' \
    --header 'Authorization: Bearer $ID_TOKEN'

Postman Example

In Postman, you can achieve the same by using the pre-request script.

To generate the ID token automatically in Postman

  1. Construct your request as usual.

  2. Under the Authorization tab, select Bearer Token and enter {{idToken}}.

    Generate ID token automatically in Postman

  3. Under the Pre-request Script tab, enter the following script:

    
    const tokenUrl = 'https://{usm-central-subdomain}.alienvault.cloud/mssp/idp/login/false';
    const username = '{email of a USM Central user}';
    const password = '{password of this user}';
    const getTokenRequest = {
      method: 'POST',
      url: tokenUrl,
      header: {
        'content-type': 'application/json',
      },
      body: {
        mode: 'raw',
        raw: JSON.stringify ({
          username: username,
          password: password
        })
      }
    };
    pm.sendRequest(getTokenRequest, (err, response) => {
      const jsonResponse = response.json();
      const idToken = jsonResponse.id-token;
      pm.variables.set('idToken', idToken);
    });
    

    Replace {usm-central-subdomain}, {email of a USM Central user}, and {password of this user} with the information you've collected for authentication.