Fortinet black logo

Administration Guide

Appendix A: API guide

Appendix A: API guide

This section explains how to use the FortiNDR API.

FortiNDR REST API currently supports the following:

  • Files submission for scanning
  • Retrieve files verdict result
  • Get file STIX2 report
  • Starting network share scan
  • Events API support (detections based on source IP/Mac/hostname and anomaly type)

Get an administrator API key

You can submit files for analysis using API with an API key. You can generate an API key using the GUI or CLI. The API key has all access privileges of the admin user.

The token is only displayed once. If you lose the token, you must generate a new one.

Upload files using API

You can use API to upload files for Express Malware Analysis. The maximum upload file size is 200MB.

To use API to upload files, generate a token. The token is only displayed once. If you lose the token, generate a new one.

To generate a token using CLI:

execute api-key <user-name>

To generate a token using GUI:
  1. Go to System > Administrator and edit an administrator.
  2. In the API Key section, click Generate.

Use an API key

When making API calls, the API key is required in the request. You can include the API key in the API request header or URL parameter.

To pass the API token by request header, explicitly add the following field to the request header.

Authorization: Bearer <YOUR-API-TOKEN>

To pass the API token by URL parameter, explicitly include the following field in the request URL parameter.

access_token=<YOUR-API-TOKEN>

Submit files

/api/v1/files

You can submit files for analysis through the /api/v1/files endpoint with an administrator API key.

For a list of supported file types and formats, see FortiNDR traffic and files input types .

Submit a file using one of the following methods.

Method

Description

JSON data

The JSON data must be encoded in base64 format.

Encode the file directly into the HTTP body as JSON data using the file_content field.

Multi-part file

The multi-part file does not need to be encoded in base64 format.

Include the file in the HTTP body as a multi-part file.

In both methods, you can use the API key as a URI parameter or the Authorization field in the header. Passwords for zip files are optional. You can view the verdict of submitted files in Virtual Security Analyst > Express Malware Analysis.

Example 1 of submitting a file or zip file via JSON data using the Python Requests module:
self.session.post(url='/api/v1/files?access_token=***API-KEY HERE***',
     data={" file_name": " b64encode(FILENAME)",
     	"file_content": b64encode(open(PATH_TO_FILE, "rb").read())},
      	"password":" ***ZIP FILE PASSWORD HERE(OPTIONAL)***")
Example 2 of submitting a file or zip file via JSON data using the Python Requests module:
self.session.post(url='/api/v1/files',
     headers={'Authorization': 'Bearer ***API-KEY HERE***'}
     data={" file_name": " b64encode(FILENAME)",
     	"file_content": b64encode(open(PATH_TO_FILE, "rb").read())},
        "password":" ***ZIP FILE PASSWORD HERE(OPTIONAL)***")
Example 1 of submitting a file or zip file as a multi-part file using the Python Requests module:
self.session.post(url='/api/v1/files? access_token=***API-KEY HERE***'',
     data={"password":”***ZIP FILE PASSWORD HERE(OPTIONAL)***”},
     files={"file":( os.path.basename(PATH_TO_FILE),open(PATH_TO_FILE,"rb"))})
Example 2 of submitting a file or zip file as a multi-part file using the Python Requests module:
self.session.post(url='/api/v1/files',
     headers={'Authorization': 'Bearer ***API-KEY HERE***'},
     data={"password":”***ZIP FILE PASSWORD HERE(OPTIONAL)***”},
     files={"file":( os.path.basename(PATH_TO_FILE),open(PATH_TO_FILE,"rb"))})

Upload file by JSON data

Encode the file name into the HTTP body as JSON data using the file_name field.

Encode the file contents into the HTTP body as JSON data using the file_content field. The maximum file size is 200MB.

You have the option to include the password in the HTTP body as JSON data using the password field where a password is needed to extract an archived file.

The following is an example of Python request module by JSON data.

requests.post(url='/api/v1/files',

params={'access_token': 'u4VvEDpUATpJbFUfpbCzlSduTddCOIs'},

data={ 'file_name': b64encode('samples.zip'),

' file_content': b64encode(open('samples.zip', 'rb').read()),

' password': 'xxxxxxxx'})

Upload file by multi-part file

The following is an example of Python request module by multi-part file.

requests.post(url='/api/v1/files',

params={'access_token': 'u4VvEDpUATpJbFUfpbCzlSduTddCOIs'},

files={'samples.zip':open('samples.zip', 'rb')})

Retrieve file verdict results

/api/v1/verdict

Supported search query parameters

Description

sid

Get file IDs from a submission ID obtained after uploading a file.

fileid

Get verdict result from file ID.

md5

Get the latest verdict result from MD5 checksum of the file.

sha1

Get the latest verdict result from SHA1 checksum of the file.

Sha256

Get the latest verdict result from SHA256 checksum of the file.

The query string can only have one search query parameter.

Examples

GET /api/v1/verdict?sid= ***submission_id***

{
  "results": {
    "fileids": [
      7,8,9,10,11,12,13,14,15
    ],
    "total_fileids": 9
  } 
}

Field

Description

fileids

File IDs in one file submission. If the file is an archived or compressed file, only files supported by FortiNDR after extraction are accepted and only file IDs of supported files appear.

total_fileids

Total number of file IDs.

GET /api/v1/verdict?fileid= ***file_id***

{
  "results": {
    "file_id": 5742600,
    "virus_name": "W32/Miner.VI!tr",
    "md5": "bbd72472f8d729f4c262d6fe2d9f2c8c",
    "sha512": "cce8e67772f19bcfe5861e4c1b8eec87016bb7cf298735db633490243bc0391a017c7d6b805f225775405598614be48c5479cb7f1c54d957e6129effbf9cca37",
    "file_size": 1141544,
    "source": "http://172.16.77.46/api/sample_download/1106042791/",
    "severity": "High",
    "category": "Trojan",
    "family":"Emotet",
    "feature_composition": [
      {
        "feature_type": "Trojan",
        "appearance_in_sample": 986
      },
      {
        "feature_type": "Application",
        "appearance_in_sample": 95
      }
    ],
    "create_date": "2020-07-31",
    "confidence": "High",
    "file_type": "PE",
    "victim_ip": "172.19.235.225",
    "attacker_ip": "172.16.77.46",
    "victim_port": 35400,
    "attacker_port": 80,
    "engine_version": 1.013,
    "kdb_version": 1.037,
    "tmfc": 0,
    "pbit": 3
  }
}

Field

Description

file_id

ID of the file.

virus_name

FortiNDR virus name.

source

For file uploaded by API or GUI, source is manual upload, otherwise it is an URL.

severity

No Risk, Low, Medium, High, or Critical.

category

For clean file: Clean.

For malicious file, one of the following: Generic Attack, Downloader, Redirector, Dropper, Ransomware, Worm, PWS, Rootkit, Banking Trojan, Infostealer, Exploit, Virus, Application, Multi, CoinMiner, DoS, BackDoor, WebShell, SEP, Proxy, Trojan, Phishing, Fileless, Wiper, or Industroyer.

family

FortiNDR virus family name.

Feature_composition

JSON objects containing feature composition data for malicious file.

feature_type is the category which the detected feature belongs to.

appearance_in_sample is the number of appearances that the feature FortiNDR has detected.

confidence

For clean file: N/A.

For other file: Low, Medium, or High.

file_type

PE, PDF, MSOFFICE, HTML, ELF, VBS, VBA, JS.

tmfc

Reserved.

pbit

Debug only.

parent_fname

The archive file name if the current file was extracted from an archive/zip file.

Example of problems retrieving results
{
  "http_code": 400,
  "message": "INVALID_PARAM"
}

Field

Description

http_code

See HTTP status table.

message

Messages include:

DATA_NOT_EXIST when result data cannot be found given the search query parameter.

DATA_IN_PROCESS when result data is still under process, such as after one submission, the accepted files have not been assigned file IDs. This might happen when uploading a big archive or compressed file.

INVALID_PARAM_NUMBER when zero or more than one search query parameters exist.

INVALID_PARAM when search query value is not valid.

Submitted file errors explanation:

When using /ap1/v1/verdict?sid=xxx to retrieve the file verdict in the following two cases:

  • Oversized file
  • Oversized archive contents

You will get reply: {"http_code": 400, "message":"OVERSIZED_FILE"}

In the other following cases:

  • Unextractable archive
  • File is still in queue
  • File is still scanned

You will get successful reply with only supported file ids in the fileids list:

{

"results": {

    "fileids": [xx],

    "total_fileids": x

}

}

Once you get the fileid from submit id, using /ap1/v1/verdict?fileid=xxx

In the following two cases:

  • File is still in queue
  • File is still to be scanned

You will get reply: {"http_code": 200, "message":"DATA_IN_PROCESS"}

Get file stix2 report

/api/v1/report

Supported search query parameters

Description

fileid

Get report from file ID.

md5

Get report of the latest file with the MD5 checksum of the file.

sha1

Get report of the latest file with the SHA1 checksum of the file.

sha256

Get report of the latest file with the SHA256 checksum of the file.

The query string can only have one search query parameter.

Examples

GET /api/v1/report?fileid= ***file_id***

{
  "results": {
    *** STIX2 report content ***
  } 
}
HTTP status table

HTTP code

Description

200

OK: API request successful.

400

Bad Request.

403

Forbidden: Request is missing authentication token, invalid authentication token, or administrator is missing access profile permissions.

404

Resource Not Found: Unable to find the specified resource.

405

Method Not Allowed: Specified HTTP method is not allowed for this resource.

413

Request Entity Too Large.

424

Failed Dependency.

500

Internal Server Error.

Start Network Share scan

/api/v1/nfs/scan

Required query parameters

Description

sname

The Network Share profile name under which the scan task will be created.

Examples
GET /api/v1/nfs/scan?sname= ***network share profile name***
{
	"http_code": 200,
	"message": "OK"
}
Example of failed to start Network Share scan
{
	"http_code": 400,
	"message": "Scanning in Progress"
}

Events API support

/api/v1/events

Query parameters

Description

ip

Get anomaly events with device IPv4 or IPv6 address. User needs specify one of [ip, hostname, mac] in the request.

hostname

Get anomaly events with device hostname. User needs specify one of [ip, hostname, mac] in the request.

mac

Get anomaly events with device mac address. User needs specify one of [ip, hostname, mac] in the request.

type

Specify the anomaly type events, one of [ botnet, entrypted-attack, network-attack, fortiguard-ioc, week-communication, ml-discovery, malware ].

start_time

The start time of events, specified as a Unix timestamp in seconds.

End_time

The end time of events, specified as a Unix timestamp in seconds.

start

The starting point or offset from which the paginated events are returned. Default 0.

size

The number of events to be returned per page. Default 500.

Examples
GET /api/v1/events?ip= 192.168.1.114 &type=network-attack&start_time=1695020154&end_time=1698111999 &start=0&size=2
{
   "results":[
      {
         "event_time":"2023-10-23 16:15:53",
         "source_ip":"192.168.1.114",
         "source_port":38123,
         "destination_ip":"192.168.1.110",
         "destination_port":17185,
         "severity":"Low",
         "attack_name":"Nmap.Script.Scanner"
      },
      {
         "event_time":"2023-10-23 16:15:53",
         "source_ip":"192.168.1.114",
         "source_port":38124,
         "destination_ip":"192.168.1.110",
         "destination_port":17185,
         "severity":"Low",
         "attack_name":"Nmap.Script.Scanner"
      }
   ]
}

Appendix A: API guide

This section explains how to use the FortiNDR API.

FortiNDR REST API currently supports the following:

  • Files submission for scanning
  • Retrieve files verdict result
  • Get file STIX2 report
  • Starting network share scan
  • Events API support (detections based on source IP/Mac/hostname and anomaly type)

Get an administrator API key

You can submit files for analysis using API with an API key. You can generate an API key using the GUI or CLI. The API key has all access privileges of the admin user.

The token is only displayed once. If you lose the token, you must generate a new one.

Upload files using API

You can use API to upload files for Express Malware Analysis. The maximum upload file size is 200MB.

To use API to upload files, generate a token. The token is only displayed once. If you lose the token, generate a new one.

To generate a token using CLI:

execute api-key <user-name>

To generate a token using GUI:
  1. Go to System > Administrator and edit an administrator.
  2. In the API Key section, click Generate.

Use an API key

When making API calls, the API key is required in the request. You can include the API key in the API request header or URL parameter.

To pass the API token by request header, explicitly add the following field to the request header.

Authorization: Bearer <YOUR-API-TOKEN>

To pass the API token by URL parameter, explicitly include the following field in the request URL parameter.

access_token=<YOUR-API-TOKEN>

Submit files

/api/v1/files

You can submit files for analysis through the /api/v1/files endpoint with an administrator API key.

For a list of supported file types and formats, see FortiNDR traffic and files input types .

Submit a file using one of the following methods.

Method

Description

JSON data

The JSON data must be encoded in base64 format.

Encode the file directly into the HTTP body as JSON data using the file_content field.

Multi-part file

The multi-part file does not need to be encoded in base64 format.

Include the file in the HTTP body as a multi-part file.

In both methods, you can use the API key as a URI parameter or the Authorization field in the header. Passwords for zip files are optional. You can view the verdict of submitted files in Virtual Security Analyst > Express Malware Analysis.

Example 1 of submitting a file or zip file via JSON data using the Python Requests module:
self.session.post(url='/api/v1/files?access_token=***API-KEY HERE***',
     data={" file_name": " b64encode(FILENAME)",
     	"file_content": b64encode(open(PATH_TO_FILE, "rb").read())},
      	"password":" ***ZIP FILE PASSWORD HERE(OPTIONAL)***")
Example 2 of submitting a file or zip file via JSON data using the Python Requests module:
self.session.post(url='/api/v1/files',
     headers={'Authorization': 'Bearer ***API-KEY HERE***'}
     data={" file_name": " b64encode(FILENAME)",
     	"file_content": b64encode(open(PATH_TO_FILE, "rb").read())},
        "password":" ***ZIP FILE PASSWORD HERE(OPTIONAL)***")
Example 1 of submitting a file or zip file as a multi-part file using the Python Requests module:
self.session.post(url='/api/v1/files? access_token=***API-KEY HERE***'',
     data={"password":”***ZIP FILE PASSWORD HERE(OPTIONAL)***”},
     files={"file":( os.path.basename(PATH_TO_FILE),open(PATH_TO_FILE,"rb"))})
Example 2 of submitting a file or zip file as a multi-part file using the Python Requests module:
self.session.post(url='/api/v1/files',
     headers={'Authorization': 'Bearer ***API-KEY HERE***'},
     data={"password":”***ZIP FILE PASSWORD HERE(OPTIONAL)***”},
     files={"file":( os.path.basename(PATH_TO_FILE),open(PATH_TO_FILE,"rb"))})

Upload file by JSON data

Encode the file name into the HTTP body as JSON data using the file_name field.

Encode the file contents into the HTTP body as JSON data using the file_content field. The maximum file size is 200MB.

You have the option to include the password in the HTTP body as JSON data using the password field where a password is needed to extract an archived file.

The following is an example of Python request module by JSON data.

requests.post(url='/api/v1/files',

params={'access_token': 'u4VvEDpUATpJbFUfpbCzlSduTddCOIs'},

data={ 'file_name': b64encode('samples.zip'),

' file_content': b64encode(open('samples.zip', 'rb').read()),

' password': 'xxxxxxxx'})

Upload file by multi-part file

The following is an example of Python request module by multi-part file.

requests.post(url='/api/v1/files',

params={'access_token': 'u4VvEDpUATpJbFUfpbCzlSduTddCOIs'},

files={'samples.zip':open('samples.zip', 'rb')})

Retrieve file verdict results

/api/v1/verdict

Supported search query parameters

Description

sid

Get file IDs from a submission ID obtained after uploading a file.

fileid

Get verdict result from file ID.

md5

Get the latest verdict result from MD5 checksum of the file.

sha1

Get the latest verdict result from SHA1 checksum of the file.

Sha256

Get the latest verdict result from SHA256 checksum of the file.

The query string can only have one search query parameter.

Examples

GET /api/v1/verdict?sid= ***submission_id***

{
  "results": {
    "fileids": [
      7,8,9,10,11,12,13,14,15
    ],
    "total_fileids": 9
  } 
}

Field

Description

fileids

File IDs in one file submission. If the file is an archived or compressed file, only files supported by FortiNDR after extraction are accepted and only file IDs of supported files appear.

total_fileids

Total number of file IDs.

GET /api/v1/verdict?fileid= ***file_id***

{
  "results": {
    "file_id": 5742600,
    "virus_name": "W32/Miner.VI!tr",
    "md5": "bbd72472f8d729f4c262d6fe2d9f2c8c",
    "sha512": "cce8e67772f19bcfe5861e4c1b8eec87016bb7cf298735db633490243bc0391a017c7d6b805f225775405598614be48c5479cb7f1c54d957e6129effbf9cca37",
    "file_size": 1141544,
    "source": "http://172.16.77.46/api/sample_download/1106042791/",
    "severity": "High",
    "category": "Trojan",
    "family":"Emotet",
    "feature_composition": [
      {
        "feature_type": "Trojan",
        "appearance_in_sample": 986
      },
      {
        "feature_type": "Application",
        "appearance_in_sample": 95
      }
    ],
    "create_date": "2020-07-31",
    "confidence": "High",
    "file_type": "PE",
    "victim_ip": "172.19.235.225",
    "attacker_ip": "172.16.77.46",
    "victim_port": 35400,
    "attacker_port": 80,
    "engine_version": 1.013,
    "kdb_version": 1.037,
    "tmfc": 0,
    "pbit": 3
  }
}

Field

Description

file_id

ID of the file.

virus_name

FortiNDR virus name.

source

For file uploaded by API or GUI, source is manual upload, otherwise it is an URL.

severity

No Risk, Low, Medium, High, or Critical.

category

For clean file: Clean.

For malicious file, one of the following: Generic Attack, Downloader, Redirector, Dropper, Ransomware, Worm, PWS, Rootkit, Banking Trojan, Infostealer, Exploit, Virus, Application, Multi, CoinMiner, DoS, BackDoor, WebShell, SEP, Proxy, Trojan, Phishing, Fileless, Wiper, or Industroyer.

family

FortiNDR virus family name.

Feature_composition

JSON objects containing feature composition data for malicious file.

feature_type is the category which the detected feature belongs to.

appearance_in_sample is the number of appearances that the feature FortiNDR has detected.

confidence

For clean file: N/A.

For other file: Low, Medium, or High.

file_type

PE, PDF, MSOFFICE, HTML, ELF, VBS, VBA, JS.

tmfc

Reserved.

pbit

Debug only.

parent_fname

The archive file name if the current file was extracted from an archive/zip file.

Example of problems retrieving results
{
  "http_code": 400,
  "message": "INVALID_PARAM"
}

Field

Description

http_code

See HTTP status table.

message

Messages include:

DATA_NOT_EXIST when result data cannot be found given the search query parameter.

DATA_IN_PROCESS when result data is still under process, such as after one submission, the accepted files have not been assigned file IDs. This might happen when uploading a big archive or compressed file.

INVALID_PARAM_NUMBER when zero or more than one search query parameters exist.

INVALID_PARAM when search query value is not valid.

Submitted file errors explanation:

When using /ap1/v1/verdict?sid=xxx to retrieve the file verdict in the following two cases:

  • Oversized file
  • Oversized archive contents

You will get reply: {"http_code": 400, "message":"OVERSIZED_FILE"}

In the other following cases:

  • Unextractable archive
  • File is still in queue
  • File is still scanned

You will get successful reply with only supported file ids in the fileids list:

{

"results": {

    "fileids": [xx],

    "total_fileids": x

}

}

Once you get the fileid from submit id, using /ap1/v1/verdict?fileid=xxx

In the following two cases:

  • File is still in queue
  • File is still to be scanned

You will get reply: {"http_code": 200, "message":"DATA_IN_PROCESS"}

Get file stix2 report

/api/v1/report

Supported search query parameters

Description

fileid

Get report from file ID.

md5

Get report of the latest file with the MD5 checksum of the file.

sha1

Get report of the latest file with the SHA1 checksum of the file.

sha256

Get report of the latest file with the SHA256 checksum of the file.

The query string can only have one search query parameter.

Examples

GET /api/v1/report?fileid= ***file_id***

{
  "results": {
    *** STIX2 report content ***
  } 
}
HTTP status table

HTTP code

Description

200

OK: API request successful.

400

Bad Request.

403

Forbidden: Request is missing authentication token, invalid authentication token, or administrator is missing access profile permissions.

404

Resource Not Found: Unable to find the specified resource.

405

Method Not Allowed: Specified HTTP method is not allowed for this resource.

413

Request Entity Too Large.

424

Failed Dependency.

500

Internal Server Error.

Start Network Share scan

/api/v1/nfs/scan

Required query parameters

Description

sname

The Network Share profile name under which the scan task will be created.

Examples
GET /api/v1/nfs/scan?sname= ***network share profile name***
{
	"http_code": 200,
	"message": "OK"
}
Example of failed to start Network Share scan
{
	"http_code": 400,
	"message": "Scanning in Progress"
}

Events API support

/api/v1/events

Query parameters

Description

ip

Get anomaly events with device IPv4 or IPv6 address. User needs specify one of [ip, hostname, mac] in the request.

hostname

Get anomaly events with device hostname. User needs specify one of [ip, hostname, mac] in the request.

mac

Get anomaly events with device mac address. User needs specify one of [ip, hostname, mac] in the request.

type

Specify the anomaly type events, one of [ botnet, entrypted-attack, network-attack, fortiguard-ioc, week-communication, ml-discovery, malware ].

start_time

The start time of events, specified as a Unix timestamp in seconds.

End_time

The end time of events, specified as a Unix timestamp in seconds.

start

The starting point or offset from which the paginated events are returned. Default 0.

size

The number of events to be returned per page. Default 500.

Examples
GET /api/v1/events?ip= 192.168.1.114 &type=network-attack&start_time=1695020154&end_time=1698111999 &start=0&size=2
{
   "results":[
      {
         "event_time":"2023-10-23 16:15:53",
         "source_ip":"192.168.1.114",
         "source_port":38123,
         "destination_ip":"192.168.1.110",
         "destination_port":17185,
         "severity":"Low",
         "attack_name":"Nmap.Script.Scanner"
      },
      {
         "event_time":"2023-10-23 16:15:53",
         "source_ip":"192.168.1.114",
         "source_port":38124,
         "destination_ip":"192.168.1.110",
         "destination_port":17185,
         "severity":"Low",
         "attack_name":"Nmap.Script.Scanner"
      }
   ]
}