Version:

Version:

Version:

Version:


Table of Contents

API Guide

Download PDF
Copy Link

API Methods

CRUD API

Authentication API

Authenticate

This API is used to generate a JWT authentication token for FortiSOAR authentication using username and password. It returns a JSON response containing the JWT token which you can then use to call other FortiSOAR APIs by passing it into the Authorization header. For example, Authorization: "Bearer {Token}".

Request

  METHOD: POST
  URL: https://{HOSTNAME}/auth/authenticate
  BODY:
  {
  	"credentials":
    {
      	"loginid": "{{username}}",
      	"password":"{{password}}"
    }
  }

Response

{
  	token:  “VALID JWT TOKEN"
}

FortiSOAR licensing

You can deploy the FortiSOAR enterprise license by running the csadm command as a root user: csadm license --deploy-enterprise-license <License File Path> . For more information on the FortiSOAR Admin CLI (csadm), see the FortiSOAR Admin CLI chapter in the "Administration Guide." For more information on licensing, see the Licensing FortiSOAR chapter in the "Deployment Guide." You can also deploy the FortiSOAR license using the API.

Deploying FortiSOAR license

You can deploy the FortiSOAR license using the API with or without an authorization token.

Deploying FortiSOAR license without an authorization token

From version 7.0.0 onwards, you can deploy the FortiSOAR license using the "Unauthenticate API", i.e, you can deploy the license without the need to generate the authorization token:

Request

POST /api/public/license HTTP/1.1
Host: fortisoar.fortinet.net
Content-Type: application/json
{
	"license_key": "<license_key>",
	"nodeId": "0961991714b6089a1d31983ea76f869e",
	"action": "deploy_license"
}

If the license is successfully deployed you will get the following response:

Response

STATUS: 200 OK

You can also retrieve the current status of license deployment using the following API:

Request

POST /api/public/license HTTP/1.1
Host: fortisoar.fortinet.net
Content-Type: application/json
{
   "nodeId": "0961991714b6089a1d31983ea76f869e",
   "action": "get_status"
}

Response

{

"depl_status": "finished",

"depl_info": {

"source": "192.168.56.1",

"user_id": null,

"ws_session_id": null,

"depl_start_time": "2020-12-23T12:23:30.771975"

}

}

Deploying FortiSOAR license with an authorization token

Before you can deploy the license file using the API, you require to generate the authorization token. Use the following curl call to get the token:

curl -X POST \
  https://<fortisoar_host>/auth/authenticate \
  -H 'Content-Type: application/json' \
  -d '{
	"credentials":
	{
		"loginid":"<loginid>",
		"password":"<password>"
	}
}

To deploy the license file using the API, make the following REST call:

curl -X POST 
  'https://<hostname>/api/auth/license 
  -H 'authorization: AUTH_TOKEN' 
  -H 'content-type: application/json'  
  -d '{
  		"license_key" : "LICENSE_KEY"
	}' 

The LICENSE_KEY value is the contents of the license file generated during the license generation step. As this API is an authenticated API, it can be used only when a valid license is already deployed. A successful deployment returns an HTTP 200 OK status.

Retrieving the license details

From version 7.0.0 onwards, you can retrieve the important license details for a given key, even before deploying the license, using the following API:

Request

POST /api/public/license HTTP/1.1
Host: fortisoar.fortinet.net
Content-Type: application/json
{
  "license_key": "<license_key>",
   "action": "get_info"
}

Response

{
 "serial_no": "FSRVMPTM20000065",
 "expiry_time": "2021-05-19 00:00:00",
 "hardware_key": "4a1782123dca6394b0d97879ca98bdf0",
 "max_users": 2, 
 "entitlements": {
     "branding": "advanced"
   },
 "type": "Evaluation",
 "edition": "Enterprise"
}

For licenses of type "Subscription", the values for max_users and expiry_time will be available only after the FortiSOAR license is deployed as the Subscription license details are fetched from the FortiGuard Distribution Network (FDN) server and therefore are available only after license deployment,

Once you have successfully deployed a FortiSOAR license, you can also retrieve the details of your license at any time using the following curl command:

curl -X GET 
  'https://<fortisoar_host>/auth/license/?param=license_details'  
  -H 'authorization: AUTH_TOKEN' 

The curl command displays a message similar to the following:

{
  "expired": false,
  "expired_nodes": [],
  "remaining_days": 180,
  "details": {
    "is_distributed": false,
    "role": [
      "master"
    ],
    "entitlements": {}
  },
  "nodes": {
    "6d1a908cc06887910ed3237e0c233fb1": {
      "message": "License Details: Max Users: 10, Expiring on: 2019-11-03, Issued for 180 days",
      "details": {
        "total_users": 10,
        "remaining_users": 9,
        "expiring_on": "2019-11-03",
        "issue_time": "2019-05-07 06:26:13.368238",
        "total_days": 180,
        "remaining_days": 180,
        "customer_name": "abc",
        "is_distributed": false,
        "entitlements": {},
        "role": [
          "master"
        ]
      },
      "node": {
        "nodeId": "6d1a908cc06887910ed3237e0c233fb1",
        "nodeName": "fortisoar.localhost",
        "status": "active",
        "role": "primary",
        "currentState": "primary server"
      }
    }
  }
}

From version 7.0.0 onwards you can also retrieve license details for a specific node using the 'node_id' parameter. When node_id value is "SELF", then license details are returned for the node on which the API call is received.

Request

GET /auth/license/?param=license_details&node_id=SELF HTTP/1.1
Host: dev.cyops.cyber
Authorization: <Bearer token>

Response

{
    "expired": false,
    "expired_nodes": [],
    "expired_nodes_details": [],
    "remaining_days": 90,
    "users": 2,
    "details": {
        "is_distributed": false,
        "role": null,
        "entitlements": {
            "branding": "advanced"
        }
    },
    "nodes": {
        "a840e36092f6edbcf9b6d97e918f81c6": {
            "details": {
                "issue_time": "2020-05-26 12:20:59.012831",
                "total_users": 2,
                "remaining_users": 1,
                "expiring_on": "2021-05-19",
                "remaining_days": 90,
                "customer_name": null,
                "is_distributed": false,
                "entitlements": {
                    "branding": "advanced"
                },
                "role": null,
                "type": "Evaluation",
                "serial_no": "FSRVMPTM20000061",
                "edition": "Enterprise"
            },
            "node": {
                "nodeId": "a840e36092f6edbcf9b6d97e918f81c6",
                "nodeName": "dev.cyops.cyber",
                "status": "active",
                "role": "primary",
                "comment": "primary server",
                "health": {}
            }
        }
    },
    "is_cloud_instance": false,
    "setup_type": "single-node"
}

API for administrators to forcefully log out users

This API can be used by an administrator to forcefully log out a user from FortiSOAR

POST /api/auth/token HTTP/1.1
Host: <host>
Content-Type: application/json
Accept: application/json
Authorization: <Bearer Token>
{
    "action": "logout",
    "users": [
        "d5d4e360-2725-40d1-9fe2-d9e9f3886a04"
    ]
}

Create users in bulk

Use the /api/3/insert/people API to create uses in bulk.

Request

METHOD: POST
URL: https://{HOSTNAME}/api/3/insert/people
BODY:
{"data":
 [
   {
     "username":"user4@gmail.com",
     "email":"user4@gmail.com",
     "firstname":"user4",
     "lastname":"4",
     "phoneMobile":"",
     "roles":[],
     "accessType":"Concurrent",
     "csActive":false,
     "loginType":6,
     "uuid":"482c47ad-edfd-42ec-b908-437cd5f86efb",
     "user":
       {
         "loginid":"user4@gmail.com",
         "user_type":6,
         "access_type":"Concurrent",
         "status":2
       }
   },
   {
     "username":"user5@gmail.com",
     "email":"user5@gmail.com",
     "firstname":"user5",
     "lastname":"5",
     "phoneMobile":"",
     "roles":[],
     "accessType":"Concurrent",
     "csActive":false,
     "loginType":6,
     "uuid":"3311f11e-2755-4076-8004-c028f17984a7",
     "user":
       {
         "loginid":"user5@gmail.com",
         "user_type":6,
         "access_type":"Concurrent",
         "status":2
       }
   }
 ]
} 

Note: user_type in the user key specifies the type of user to be created. For example "user_type":6 is used to creating SSO users.

High Availability Health Cluster API

This API is used to retrieve information for the nodes in a High Availability (HA) cluster from the database.

GET /api/auth/cluster/health/: Used to retrieve health information for all the nodes in an HA cluster from the database.

GET /api/auth/cluster/health?nodeId=<cluster-node-id>: Used to retrieve health information for a particular node in an HA cluster from the database.

GET /api/auth/cluster/health?latest=True&section=cpu,disk,ram,swap,all,services: Used to retrieve the latest health information for the node who is serving the API from the database.

Model Operations

Create Individual Model Records

Request

METHOD: POST
URL: /api/{version}/{collection}
BODY:
{
  "field1": "value1",
  "field2": "value2"
}

Example

Request

METHOD: POST
URL: /api/3/assets
BODY:
{
  "ip": "8.8.8.8",
  "hostname": "google-public-dns-a.google.com"
}

Response

STATUS: 201
BODY:
{
  "@id": "/api/3/assets/01199609-d60f-356b-a762-129a6e1b353b",
  "@type": "Asset",
  "ip": "8.8.8.8",
  "hostname": "google-public-dns-a.google.com"
}

Retrieve Collection of Model Records

The responses adhere to the Hydra Spec for pagination. Records that match the specified query are returned as objects within the "hydra:member" array.

Request

METHOD: GET
URL: /api/{version}/{collection}

Response

STATUS: 200
BODY:
{
  "@context": "/api/{version}/contexts/{collection type}",
  "@id": "/api/{version}/{collection}",
  "@type": "hydra:PagedCollection",
  /* Contains some Hydra pagination properties */
  "hydra:member": [
    { "@id": "/api/{version}/{collection}/{uuid}", ... },
    { "@id": "/api/{version}/{collection}/{uuid}", ... },
    { "@id": "/api/{version}/{collection}/{uuid}", ... }
  ]
}

From version 7.0.0 onwards, the 'Pagination' response has changed as follows:

  • The hydra 'next' attribute is not displayed in the API response, if there are no further results.
  • The Item per page key has been removed.
  • The new 'pagination' response has hydra: view with first page, next page, and last page information.

If you require the legacy view for records, though it is not recommended, you can add the $legacy_collection_view=true query parameter in the API request. If you set the $legacy_collection_view=true parameter, then the API request will also contain the following older keys:

  • 'hydra:itemsPerPage'
  • 'hydra:firstPage'
  • 'hydra:lastPage'

Example

Request

METHOD: GET
URL: /api/3/assets

Response

STATUS: 200
BODY:
{
  "@context": "/api/3/contexts/Asset",
  "@id": "/api/3/assets",
  "@type": "hydra:PagedCollection",
  "hydra:totalItems": 2,
  "hydra:itemsPerPage": 30,
  "hydra:firstPage": "/api/3/assets",
  "hydra:lastPage": "/api/3/assets",
  "hydra:member": [
    {
      "@id": "/api/3/assets/01199609-d60f-356b-a762-129a6e1b353b",
      "@type": "Asset",
      "ip": "8.8.8.8",
      "hostname": "google-public-dns-a.google.com"
    },
    {
      "@id": "/api/3/assets/017d3845-e204-367c-b74d-6bb37a8239b7",
      "@type": "Asset",
      "ip": "8.8.4.4",
      "hostname": "google-public-dns-b.google.com"
    }
  ]
}

Retrieve Single Model Records

Request

METHOD: GET
URL: /api/{version}/{collection}/{uuid}

Response

STATUS: 200
BODY:
{
  "@id": "/api/{version}/{collection}/{uuid}",
  "@type": "{collection type}",
  "field1": "value1",
  "field2": "value2"
}

Example

Request

METHOD: GET
URL: /api/3/assets/01199609-d60f-356b-a762-129a6e1b353b

Response

STATUS: 200
BODY:
{
  "@id": "/api/3/assets/01199609-d60f-356b-a762-129a6e1b353b",
  "@type": "Asset",
  "ip": "8.8.8.8",
  "hostname": "google-public-dns-a.google.com"
}

Update Single Model Records

Request

METHOD: PUT
URL: /api/{version}/{collection}/{uuid}
BODY:
{
  "field1": "value1",
  "field2": "value2"
}

Example

Request

METHOD: GET
URL: /api/3/assets/01199609-d60f-356b-a762-129a6e1b353b
BODY:
{
  "ip": "8.8.8.8"
}

Response

STATUS: 200
BODY:
{
  "@id": "/api/3/assets/01199609-d60f-356b-a762-129a6e1b353b",
  "@type": "Asset",
  "ip": "8.8.8.8",
  "hostname": "google-public-dns-a.google.com"
}

Delete Single Model Records

Caution

Deleting models can result in system instability and data model. We advise that you do not delete models after creation.

Request

METHOD: DELETE
URL: /api/{version}/{collection}/{uuid}

Example

Request

METHOD: DELETE
URL: /api/3/assets/01199609-d60f-356b-a762-129a6e1b353b

Response

STATUS: 204
REASON: No Content

Insert records in bulk

You can use the Bulk Insert API to insert records in bulk, in a module that you specify.

From version 7.0.0 onwards, the bulk API response has been changed to 'success' or 'failure', compared to earlier releases where multistage single, failed, and bad requests were passed.

Note

It is recommended that you insert up to 200 smaller records such as assets, indicators, etc. in single request and loop over your dataset. If you have larger records such as, alerts and incidents with large sourcedata, then the recommended batch size is 100.

Request

METHOD: POST
URL: {{YourFortiSOARHostname}}/api/{version}/insert/{moduleType}
BODY: {
		"data”: [{record 1}, {record 2}]
	  }		
}

Example

Request

METHOD: POST
URL: {{YourFortiSOARHostname}}/api/3/insert/alerts
BODY: {
		"data": [
        {
            "name": "bulk record 1",
            "description": "<p>bulk record 1 description</p>",
            "severity": "/api/3/picklists/58d0753f-f7e4-403b-953c-b0f521eab759"
        },{
            "name": "bulk record 2",
            "description": "<p>bulk record 2 description</p>",
            "severity": "/api/3/picklists/58d0753f-f7e4-403b-953c-b0f521eab759"
        },{
            "name": "bulk record 3",
            "description": "<p>bulk record 3 description</p>",
            "severity": "/api/3/picklists/58d0753f-f7e4-403b-953c-b0f521eab759"
        }
    ]	
}

Response: If all the records are inserted successfully, then you will get a 200 OK response. If not all the records can be inserted, then you will get a 207 (Partially Deleted) response.

Example of a complete response:

{
   “@context”: “/api/3/contexts/Alert”,
   “@id”: null,
   “@type”: “hydra:Collection”,
   “hydra:member”: [
       {
           inserted record data
       }
   ]
}

Delete records in bulk

You can use the Bulk Delete API to delete records in bulk, in a module that you specify.

Request

METHOD: DELETE
URL: {{YourFortiSOARHostname}}/api/{version}/delete/{moduleType}
BODY: {
		"ids": ["value1", "value2", "value3"]
	  }		
}

Example

Request

METHOD: DELETE
URL: {{YourFortiSOARHostname}}/api/3/delete/alerts
BODY: {
		"ids": ["13d7115a-2d4d-4bfb-bdb8-efabfce547f011", 
				"13d7115a-2d4d-4bfb-bdb8-efabfce547f012", 
				"13d7115a-2d4d-4bfb-bdb8-efabfce547f013"]
	  }		
}

Response: If all the records are deleted successfully, then you will get a 200 OK response. If not all the records can be deleted, if for example, you have provided an ID of an already deleted record, then you will get a 207 (Partially Deleted) response.

Update records in bulk

You can use the Bulk Update API to update records in bulk, in a module that you specify.

Request

METHOD: PUT
URL: {{YourFortiSOARHostname}}/api/{version}/update/{moduleType}
BODY: {
	“data” : [
		{
 			"field1": "value1",
  			"field2": "value2", 
  			"field3": "value3"
		},
		{
 			"field1": "value1",
  			"field2": "value2", 
  			"field3": "value3"
		}
	]
}

Example

Request

METHOD: PUT
URL: {{YourFortiSOARHostname}}/api/3/update/alerts
BODY: {
	“data” : [
		{
 			“@id”: “/api/3/alerts/a3abeb23-f323-45a9-856b-2bf9d10386cb”,
  			“source”: “1238765”, 
  			"description": "Test 1"
		},
		{
 			“@id”: “/api/3/alerts/8c086c21-2c79-4488-ae22-d0e116469fe2”,
  			“source”: “097353”,
  			“description”: “Test 2”,
		}
	]
}

Response: The response will contain all the fields specified in the metadata of the module. Following is a snippet extract of a successful response:

STATUS: 200
BODY: {
	“data” : [
		{
 			“@id”: “/api/3/alerts/a3abeb23-f323-45a9-856b-2bf9d10386cb”,
  			“source”: “1238765”, 
  			"description": "Test 1"
		},
		{
 			“@id”: “/api/3/alerts/8c086c21-2c79-4488-ae22-d0e116469fe2”,
  			“source”: “097353”,
  			“description”: “Test 2”,
		}
	]
}

Notes:

  • If you provide the body of the request appropriately, then all the records get successfully updated to the specified module, and you get a 200 OK response.
  • If you do not provide an id for an object (record), then the module is partially updated with the records that have an associated id. Records that do not have an id will not be updated in the specified module. In this case, you get a 207 response, which will list the records that are not updated.
  • If you specify a null value for any field, those records get successfully updated.

Upsert records

Note

Upsert works only if you have defined uniqueness for records in the module you want to upsert records. If you have not defined record uniqueness, the upsert operation will always insert records. Also, note that when you are upserting records, fields that are marked as non-editable also get updated and the upsert behavior for uniqueness will not work for fields that are marked as encrypted.

Single Upsert API

You can use the Upsert API to either update an existing record, if any record matches the unique list of fields you have specified for that module using the Module Editor, or insert a new record.

Request

Following is a sample request for a single upsert request:

METHOD: POST
URI: {{YourFortiSOARHostname}}/api/3/upsert/{moduleType}
BODY: 
      {
	   	"name": "value1",
  		"sourceId": null, 
  		"severity": "value2"
      }

Bulk Upsert API

You can use the Bulk Upsert API to either bulk update multiple records, if the records match the unique list of fields you have specified for that module, or bulk insert new records.

Request

Following is a sample request for a bulk upsert request:

METHOD: POST
URI: {{YourFortiSOARHostname}}/api/3/bulkupsert/{moduleType}
BODY:[ 
       {
	   	"name": "value1",
  		"sourceId": "null", 
  		"severity": "value2"
	   },
      {
	   	"name": "value1",
  		"sourceId": "null", 
  		"severity": "value2"
	   }
]

Response: If all the records are upserted successfully, then you will get a 200 OK response. If some records are upserted successfully and some records are not upserted, then you will get a 207 (Partial Upsert) response. If none of the records are upserted successfully, then you will get a 400 response.

Relationship Operations

For these examples, we will expect that an Incident has already been created in the system. All these operations will affect the assets field of an Incident.

Get Relationship

Request

METHOD: GET
URL: /api/3/incidents/bbdc13f8-015f-4615-8c63-4cebb6ec991b/assets

Response

{
  "@context": "/api/3/contexts/Asset",
  "@id": "/api/3/incidents/bbdc13f8-015f-4615-8c63-4cebb6ec991b/assets",
  "@type": "hydra:PagedCollection",
  "hydra:totalItems": 1,
  "hydra:itemsPerPage": 30,
  "hydra:firstPage": "/api/3/incidents/bbdc13f8-015f-4615-8c63-4cebb6ec991b/assets",
  "hydra:lastPage": "/api/3/incidents/bbdc13f8-015f-4615-8c63-4cebb6ec991b/assets",
  "hydra:member": [
    {
      "@id": "/api/3/assets/2ac5eafd-e7dd-465e-8ddd-6b9aeb7125c0",
      "@type": "Asset",
      "macAddress": "as:se:t2",
      "id": 639
    }
  ]
}

From version 7.0.0 onwards, the support for getting the count of related records by passing the $relationshipCount flag (api/3/<module>/uuid/<associateModule>?Countonly=true) on only queries has been removed. Now, to get relationships count, FortiSOAR has provided alternate route of aggregation support on /api/query/module, which is much faster.

Append Existing Object to Relationship

Request

METHOD: POST
URL: /api/3/incidents/bbdc13f8-015f-4615-8c63-4cebb6ec991b/assets
BODY:
{
  "@id": "/api/3/assets/e0a3521f-67de-473f-a9a0-7f2d44626567"
}

Response

{
  "@id": "/api/3/assets/e0a3521f-67de-473f-a9a0-7f2d44626567",
  "@type": "Asset",
  "macAddress": "as:se:t1",
  "id": 638
}

The behavior of linking records relationships has changed in version 7.0.0 because if there is a record that is linked to thousands of other records, an update to such records causes constant high CPU usage. An example of such a record would be indicators like org name that get extracted as part of every alert and get linked to thousands of alerts. Therefore, it is recommended that you link a maximum of 99 records in a single API call. This is because, if there are less than 99 records linked then the framework checks if the record being linked is already present in existing relations and if the same record is linked again and again, post-update triggers on relation "isChanged" is not triggered, also the linking is not audited again every time. However, from the 100th linked record, the framework only looks at the __link, __unlink keys, and hence, if the same record is linked again and again, post-update triggers on relation "isChanged" will get triggered, and also the linking gets audited again every time.

Append New Object to Relationship

Request

METHOD: POST
URL: /api/3/incidents/bbdc13f8-015f-4615-8c63-4cebb6ec991b/assets
BODY:
{
  "macAddress": "as:se:t3",
  "assetType": "laptop"
}

Response

{
  "@id": "/api/3/assets/5434a6e1-e9cd-4ecf-ba6b-f8ac82c3effc",
  "@type": "Asset",
  "macAddress": "as:se:t3",
  "id": 639
  "assetType": "laptop"
}

Delete Relationship

Request

METHOD: DELETE
URL: /api/3/incidents/bbdc13f8-015f-4615-8c63-4cebb6ec991b/assets/
e0a3521f-67de-473f-a9a0-7f2d44626567

Response

STATUS: 204
REASON: No Content

Audit Log Purge Operations

You can use the Audit Log Purge API to purge audit logs on an automated as well as on-demand basis.

Stop Automatic Purging of Audit Logs

To stop automatic purging of audit logs, run the following API:

Request

Method: DELETE 
URL:  /gateway/audit/activities/ttl
Content-Type: application/json
Authorization: <Bearer Token>

Example:

DELETE /gateway/audit/activities/ttl
Content-Type: application/json
Authorization: <Bearer Token>

Response: If the API is successfully run you will get a 200 OK response, which stops the automatic purging of audit logs.

Delete audit logs before a particular date

To delete audit logs before a particular date, run the following API:

Request

Method: DELETE 
URL:  /gateway/audit/activities
Authorization: <Bearer Token>
Cache-Control: no-cache

Example:

DELETE /gateway/audit/activities?uptoDate=1524477805
Authorization: <Bearer Token>
Cache-Control: no-cache

Response: If the API is successfully run you will get a 200 OK response and then audit logs that exist before the specified date will be purged.

Export and Import Configurations Operations

From version 6.4.3 onwards, to import and export configurations, you can use the respective APIs. You can also schedule API-based configuration export and imports. Alternatively, you can also use the FortiSOAR UI to run a wizard-based export and import of configuration information. For more information on the using the wizard-based export and import, see the Configuration Export and Import topic in the Application Editor chapter of the "Administration Guide."

Importing Configurations

To import a configuration using the API, the configuration must be in the JSON format. Follow these steps to import a configuration:

Step 1: Create an import job.

    POST /api/3/import_jobs 
    { 
    "status": "In Progress", 
    "file": "/api/3/files/<uuid of uploaded json file>" 
    } 

This request creates an import job; whose output contains the @id of the import_jobs record. You can extract the UUID from the @id, whose format is /api/3/import_job/<uuid>, and use this UUID in future requests to trigger the import.

Step 2: Generate the import options.

GET /api/import/<import job uuid>

This request populates the options object for the import job with the default options required for import. After generating the defaults, you can modify the default options by updating the import job record with the following requests.

To get the options object:

GET /api/3/import_jobs/<import job uuid>

To modify the options object:

PUT /api/3/import_jobs/<import job uuid> 
{ 
"options": (modified options object) 
} 

Step 3: Trigger the import.

PUT /api/import/<import job uuid>

This request triggers the import, which runs asynchronously. You can check the status of the import using the following request:

GET /api/3/import_jobs/<import job uuid>

Exporting Configurations

Follow these steps to export a configuration, in the JSON format, using the API:

Step 1: Create an export template or use an existing export template.

POST /api/3/export_templates 
{ 
  "options": { 
    "modules": [...], 
    "viewTemplates": [...], 
    "picklistNames": [...], 
    "views": [...], 
    "reports": [...], 
    "dashboards": [...], 
    "roles": [...],   
    "appSettings": [...], 
    "playbooks": { 
      "collections": [...], 
      "includeVersions": false, 
      "globalVariables": [...] 
    } 
  }, 
  "name": "Configuration Export" 
} 

Following is a sample template containing data:

{ 
  "options": { 
    "modules": [ 
      "agents" 
    ], 
    "viewTemplates": [ 
      "modules-agents-list", 
      "modules-agents-detail", 
      "modules-agents-form" 
    ], 
    "picklistNames": [ 
      "/api/3/picklist_names/114d88e4-ceaa-4b9f-842b-cca8db90f418", 
      "/api/3/picklist_names/a7ce1d03-a4e4-4750-afdd-ca3cbb6a03b3", 
      "/api/3/picklist_names/663eb9f2-d362-4640-a2f1-f5432c6d3c4e", 
      "/api/3/picklist_names/a255a02f-2f4d-4535-baaf-6c64c1d6f5d0" 
    ], 
    "views": [ 
      "app" 
    ], 
    "reports": [ 
      "11ece146-396e-42f8-a2c4-358550c6f03f" 
    ], 
    "dashboards": [ 
      "2bc7fd32-1cc6-48b0-bcbb-3a7c09938d4a" 
    ], 
    "roles": [ 
      "/api/3/roles/21d7a7c6-9d68-438f-b732-e8950c5f745b" 
    ], 
    "appSettings": [ 
      "sso" 
    ], 
    "playbooks": { 
      "collections": [], 
      "includeVersions": false, 
      "globalVariables": [ 
        "Body" 
      ] 
    } 
  }, 
  "name": "Configuration Export" 
} 

Alternatively, you can also create the export template using the Configuration Export Wizard in the FortiSOAR UI and use the UUID of that template for further requests.

Step 2: Trigger the export.

PUT /api/export?fileName=<file name ending in .json>&template=<export template uuid>

This request triggers the export and sends the following response:

{"@type": "ExportJob", "jobUuid": "<export job uuid>"}

Step 3: Download the file.

GET /api/3/export_jobs/ <export job uuid>

To request retrieves the status of the export and sends the following response:

{"file": {…}, "status": "Export Complete"}

When the status equals “Export Complete”, a file object is returned. You can download the exported file using its "File IRI".

Integration APIs

You can use 'Integration APIs' can be used in playbooks to perform various actions such as retrieving health information for connectors, creating configurations for connectors, etc.

Retrieving connector details

  • To get a list of all connectors installed on a FortiSOAR instance:
    GET api/integration/connectors/
  • To get a list of all connectors that being developed on a FortiSOAR instance:
    POST /api/integration/connector/development/list/
    Body {}
    Note: Body is Empty JSON.
  • To get details of any installed connector:
    POST api/integration/connectors/<connector_name> /<connector_version>/
    Body {}
    Note: Body is Empty JSON.
    Example: api/integration/connectors/cyops_utilities/3.1.2/
    Note: If the specified version, 3.1.2, in our example is not installed, then the API returns details of same connector (cyops_utilities) with latest version installed, for example, version 3.1.1.

Creating configurations for any connector

To create configurations for connectors:

POST /api/integration/configuration/
Body
{
   "connector": <connector_id>,
   "connector_name": <connector_name>,
   "connector_version": <connector_version>,
   "name": <config_name>,
   "config_id": <config_id>,
   "default": <true/false>,
   "config": {
     "<connector_config_field1>”: "<value>",
     "<connector_config_field2>”: "<value>",
     "<connector_config_field3>”: "<value>",
   },
}

Example of the 'Body' of a connector:

{
   "connector": 2,
   "connector_name": "imap",
   "connector_version": "3.5.6",
   "name": "test",
   "config_id": "b6412f73-a1b0-4446-a66a-99460133b780",
   "default": true,
   "config": {
     "host": "imap.gmail.com",
     "port": "993",
     "username": "demo@gmail.com",
     "password": "test@123",
     "ssl": true,
     "source": "INBOX",
     "destination": "PROCESSED",
     "verify": true,
     "notification_service": ""
   }
}

Notes:

  • You must specify either the connector_id or connector_name.
  • You must specify the connector_version.
    If connector_version specified is invalid, then the latest installed version of same connector is considered.
  • It is not mandatory to provide the config_id, as a UUID gets automatically generated.

Retrieving health check details for a connector

To get the heath check details for a connector:
GET /api/integration/connectors/healthcheck/<connector_name>/<connector_version>/?config=<config_id>

Example: /api/integration/connectors/healthcheck/imap/3.5.6/?config=a7c7df29-1f5c-426e-981b-b1ab1b7692cb

Note: If you specify an invalid config_id, then the health check details of the 'default' configuration of the specified connector is returned.

Deleting a configuration of a connector

To delete a specific configuration of a connector:
DELETE /api/integration/configuration/<id>/

Example: /api/integration/configuration/8

Executing an action of a installed connector

To execute an action of an installed connector:

POST /api/integration/execute/
Body
{
   "connector": <connector_id>,
   "version": <connector_version>,
   "config": <config_id>,
   "operation": "<action_name>",
   "params": {
     "<action_param1>": <value>,
     "<action_param2>": <value>
   },
}

Example of the 'Body' of a connector:

{
   "connector": "imap",
   "connector_version": "3.5.6",
   "config": "a7c7df29-1f5c-426e-981b-b1ab1b7692cb",
   "operation": "fetch_email_new",
   "params": {
     "limit_count": 30,
     "parse_inline_image": true
   }
}

Uninstalling a connector

To uninstall a connector:
DELETE /api/integration/connectors/<id>/

Example: /api/integration/connectors/15

Workflow Execution

You can use the Workflow Execution API to debug playbook execution, apply filters on running playbooks, retrieve playbook IDs, list execution logs, etc.

Workflow Execution History

GET /api/wf/api/workflows/?format=json: Used to list the workflow execution history.

GET /api/wf/api/workflows/29/?format=json: Used to retrieve the detailed view of a particular workflow execution history based on the ID specified.

You can filter the workflow execution history by specifying various query parameters such as, ordering, and filters such as status. An example of the Workflow Execution API with parameters and filters is: GET /api/wf/api/workflows/?format=json&status=finished&ordering=-created.

Following query parameters are supported:

  • Offset - The initial index from which to return the results.
  • Limit - The maximum number of results to return per page.
  • Ordering - The field using which you want to sort the results. For example, ordering=-created sorts the results in the descending order based on the creation date.

Following filters are supported:

  • template_iri – Filters the workflow execution history based on the playbook IRI specified, i.e., retrieves the execution history for a particular playbook. For example, /api/wf/api/workflows/?template_iri= "/api/3/workflows/".
  • records - Filters the workflow execution history based on the record ID specified, i.e., retrieves the execution history for playbooks execution on a specific record. For example, /api/wf/api/workflows/?records= "/api/3/alerts/alert_id".
  • status – Filters the workflow execution history based on the running status of the playbooks. The running state of the playbooks can be incipient, active, failed, finished, awaiting, skipped, or terminated. For example, /api/wf/api/workflows/?status=failed, retrieves the execution history of all playbooks that have failed.
  • ?created_after=""&created_before="" – Filters the workflow execution history based on the time range specified. For example, /api/wf/api/workflows/?created_after=2020-11-08&created_before=2020-11-10, retrieves the execution history of all playbooks that are executed between the 8th and 10th of November, 2020.
  • ?parent__isnull=True – Filters the workflow execution history to retrieve the history of only the parent playbooks, i.e., specifying this filter will filter out the execution history of all children playbooks.
  • tags_exclude="",&tags_include="" – Filters the workflow execution history based on the comma-separated list of tags specified. You can specify that you want to include the execution history of playbooks containing particular tags or you want to exclude the execution history of playbooks containing particular tags or a combination of both. For example, /api/wf/api/workflows/?tags_exclude=system,&tags_include=ingestion,critical retrieves the execution history of all playbooks that contain the ingestion or critical tags and excludes all playbooks containing the system tag.

Workflow Execution Log

FortiSOAR version 6.4.4 has enhanced the Workflow Execution Log API (/api/wf/api/query/workflow_logs/) to fetch data from the database based on user configuration. The workflow_logs API now supports queries in the POST request. If {'query': {}} is found in the POST body of the API call, then the query set is formed based on the users' input data. Otherwise, the query works as per the current functionality, i.e., the query picks up parameters from the URL.

An example of a query containing the supported filters follows:

{
    "logic": "AND/OR",
    "limit": "30",
    "sort": [{
        field: "modified/status/name"
        direction: "asc/desc"
    }],
    "filters": [{
        "field": "status/user/tags/modified/name",
        "operator": "eq/contains/neq/ncontains/gte/lte",
        "value": ""
    }],
    "aggregates": [{
            "operator": "groupBy/count",
            "field": "status/user/name/id"
        }
    ]
}

An example of a query containing nested filters follows:

 "logic": "OR",
    "limit": 30,
    "filters": [{
        "logic": "OR",
        "filters": [{
            "field": "tags",
            "operator": "contains",
            "value": "test"
        }, {
            "field": "tags",
            "operator": "contains",
            "value": "testing"
        }]
    }, {
        "logic": "AND",
        "filters": [{
            "field": "status",
            "operator": "eq",
            "value": "finished"
        }, {
            "field": "status",
            "operator": "eq",
            "value": "failed"
        }]
    }]
}

Deleting workflow logs and cleaning up the workflow table

You can also use the Workflows API to retrieve details of an existing schedule used to purge workflow logs, update details and configuration of an existing schedule used to purge workflow logs, and also delete workflow logs.

You can use the 'Workflow Table Cleanup' API (new in version 7.0.2) to shrink the space of the workflow space and make unused space available to system.

Deleting workflow logs

You can use the Workflows API to delete workflow logs along with a date filter.

Request

METHOD: DELETE
URL: /api/wf/api/workflows/delete/?format=json
BODY:
{
  "date": "<Before_Date_filter>",
  "userId": "<user_id>",
  "user": "<user_name>"
  "exclude_awaiting_wf": <true/false>
}

Response

{"result": "deleting workflows"}

The following filters are supported:

  • date: The date before which the workflow logs should be deleted.
  • exclude_awaiting_wf: Whether or not workflow logs that are in the 'awating' state should be excluded from deletion. If you specify true then the workflow logs that are in the 'awating' state are excluded from deletion, i.e., they are not deleted.

Example

Delete /api/wf/api/workflows/delete/?format=json 
Body  
{ 

  "date": "2021-05-03T18:30:00.000Z", 
  "userId": "3451141c-bac6-467c-8d72-85e0fab569ce", 
  "user": "CS Admin", 
  "exclude_awaiting_wf": true 
} 

Cleanup the Workflow table

The 'Workflow Table Cleanup' API clears all the empty rows in tables and indexes and makes the unused space available to the system, which helps in improving the performance by optimizing the space.

POST /api/wf/api/workflows/auto_vacuum/?format=json: Used to clean up the workflow table and all the tables that are related to the workflow table:

Request

METHOD: POST
URL: /api/wf/api/workflows/auto_vacuum/?format=json
BODY:
{
  "date": "2021-07-22 09:00:35",
  "userId": "<current_users_id>",
  "user": "<current_user_name>"
}

Log Collection Operations

There are two APIs introduced in version 7.0.0 for collecting FortiSOAR logs. Log collection can be a long-running task, so the API should be asynchronous and should not wait for the log collection operation to be completed. Therefore, two APIs are added: One API starts the process of collecting logs and the other one downloads the collected log file.

The logs get collected in the /opt/cyops-api/workspace/logs directory and users require Security Read permission to perform the log collection operations.

Triggering log collection

To start the process of log collection, use the following request:

Request

POST/api/3/utils/log-collect HTTP/1.1 
Host: <account_id>.fortisoar.forticloud.com 
Authorization: <Bearer Token> 
{
    "password": "Test"
}

Note: The Password parameter is optional, i.e., you do not need to input the password.

Response

{
    "filename": "fortisoar-logs.tar.gz.gpg"
}

The filename is "fortisoar-logs.tar.gz.gpg" if you have supplied a password in the request. Else, the filename is "fortisoar-logs.tar.gz".

If the log collection is triggered successfully, then status code 200 is returned. If another log collection request is running, then status code 202 is returned.

Downloading the collected log file

To download the collected log file, use the following request:

Request

GET /api/3//utils/log-collect?filename=<filename> HTTP/1.1 
Host: <account_id>.fortisoar.forticloud.com 
Authorization: <Bearer Token> 

Response

A file is downloaded with the name fortisoar-logs.tar.gz.gpg (or fortisoar-logs.tar.gz) according to the input provided (password specified or not) in the API request, if corresponding previous log collection operation was successful.

If log collection process is still running, then status code 202 is returned. If the log collection file is not found, then status code 400 is returned.

API Methods

CRUD API

Authentication API

Authenticate

This API is used to generate a JWT authentication token for FortiSOAR authentication using username and password. It returns a JSON response containing the JWT token which you can then use to call other FortiSOAR APIs by passing it into the Authorization header. For example, Authorization: "Bearer {Token}".

Request

  METHOD: POST
  URL: https://{HOSTNAME}/auth/authenticate
  BODY:
  {
  	"credentials":
    {
      	"loginid": "{{username}}",
      	"password":"{{password}}"
    }
  }

Response

{
  	token:  “VALID JWT TOKEN"
}

FortiSOAR licensing

You can deploy the FortiSOAR enterprise license by running the csadm command as a root user: csadm license --deploy-enterprise-license <License File Path> . For more information on the FortiSOAR Admin CLI (csadm), see the FortiSOAR Admin CLI chapter in the "Administration Guide." For more information on licensing, see the Licensing FortiSOAR chapter in the "Deployment Guide." You can also deploy the FortiSOAR license using the API.

Deploying FortiSOAR license

You can deploy the FortiSOAR license using the API with or without an authorization token.

Deploying FortiSOAR license without an authorization token

From version 7.0.0 onwards, you can deploy the FortiSOAR license using the "Unauthenticate API", i.e, you can deploy the license without the need to generate the authorization token:

Request

POST /api/public/license HTTP/1.1
Host: fortisoar.fortinet.net
Content-Type: application/json
{
	"license_key": "<license_key>",
	"nodeId": "0961991714b6089a1d31983ea76f869e",
	"action": "deploy_license"
}

If the license is successfully deployed you will get the following response:

Response

STATUS: 200 OK

You can also retrieve the current status of license deployment using the following API:

Request

POST /api/public/license HTTP/1.1
Host: fortisoar.fortinet.net
Content-Type: application/json
{
   "nodeId": "0961991714b6089a1d31983ea76f869e",
   "action": "get_status"
}

Response

{

"depl_status": "finished",

"depl_info": {

"source": "192.168.56.1",

"user_id": null,

"ws_session_id": null,

"depl_start_time": "2020-12-23T12:23:30.771975"

}

}

Deploying FortiSOAR license with an authorization token

Before you can deploy the license file using the API, you require to generate the authorization token. Use the following curl call to get the token:

curl -X POST \
  https://<fortisoar_host>/auth/authenticate \
  -H 'Content-Type: application/json' \
  -d '{
	"credentials":
	{
		"loginid":"<loginid>",
		"password":"<password>"
	}
}

To deploy the license file using the API, make the following REST call:

curl -X POST 
  'https://<hostname>/api/auth/license 
  -H 'authorization: AUTH_TOKEN' 
  -H 'content-type: application/json'  
  -d '{
  		"license_key" : "LICENSE_KEY"
	}' 

The LICENSE_KEY value is the contents of the license file generated during the license generation step. As this API is an authenticated API, it can be used only when a valid license is already deployed. A successful deployment returns an HTTP 200 OK status.

Retrieving the license details

From version 7.0.0 onwards, you can retrieve the important license details for a given key, even before deploying the license, using the following API:

Request

POST /api/public/license HTTP/1.1
Host: fortisoar.fortinet.net
Content-Type: application/json
{
  "license_key": "<license_key>",
   "action": "get_info"
}

Response

{
 "serial_no": "FSRVMPTM20000065",
 "expiry_time": "2021-05-19 00:00:00",
 "hardware_key": "4a1782123dca6394b0d97879ca98bdf0",
 "max_users": 2, 
 "entitlements": {
     "branding": "advanced"
   },
 "type": "Evaluation",
 "edition": "Enterprise"
}

For licenses of type "Subscription", the values for max_users and expiry_time will be available only after the FortiSOAR license is deployed as the Subscription license details are fetched from the FortiGuard Distribution Network (FDN) server and therefore are available only after license deployment,

Once you have successfully deployed a FortiSOAR license, you can also retrieve the details of your license at any time using the following curl command:

curl -X GET 
  'https://<fortisoar_host>/auth/license/?param=license_details'  
  -H 'authorization: AUTH_TOKEN' 

The curl command displays a message similar to the following:

{
  "expired": false,
  "expired_nodes": [],
  "remaining_days": 180,
  "details": {
    "is_distributed": false,
    "role": [
      "master"
    ],
    "entitlements": {}
  },
  "nodes": {
    "6d1a908cc06887910ed3237e0c233fb1": {
      "message": "License Details: Max Users: 10, Expiring on: 2019-11-03, Issued for 180 days",
      "details": {
        "total_users": 10,
        "remaining_users": 9,
        "expiring_on": "2019-11-03",
        "issue_time": "2019-05-07 06:26:13.368238",
        "total_days": 180,
        "remaining_days": 180,
        "customer_name": "abc",
        "is_distributed": false,
        "entitlements": {},
        "role": [
          "master"
        ]
      },
      "node": {
        "nodeId": "6d1a908cc06887910ed3237e0c233fb1",
        "nodeName": "fortisoar.localhost",
        "status": "active",
        "role": "primary",
        "currentState": "primary server"
      }
    }
  }
}

From version 7.0.0 onwards you can also retrieve license details for a specific node using the 'node_id' parameter. When node_id value is "SELF", then license details are returned for the node on which the API call is received.

Request

GET /auth/license/?param=license_details&node_id=SELF HTTP/1.1
Host: dev.cyops.cyber
Authorization: <Bearer token>

Response

{
    "expired": false,
    "expired_nodes": [],
    "expired_nodes_details": [],
    "remaining_days": 90,
    "users": 2,
    "details": {
        "is_distributed": false,
        "role": null,
        "entitlements": {
            "branding": "advanced"
        }
    },
    "nodes": {
        "a840e36092f6edbcf9b6d97e918f81c6": {
            "details": {
                "issue_time": "2020-05-26 12:20:59.012831",
                "total_users": 2,
                "remaining_users": 1,
                "expiring_on": "2021-05-19",
                "remaining_days": 90,
                "customer_name": null,
                "is_distributed": false,
                "entitlements": {
                    "branding": "advanced"
                },
                "role": null,
                "type": "Evaluation",
                "serial_no": "FSRVMPTM20000061",
                "edition": "Enterprise"
            },
            "node": {
                "nodeId": "a840e36092f6edbcf9b6d97e918f81c6",
                "nodeName": "dev.cyops.cyber",
                "status": "active",
                "role": "primary",
                "comment": "primary server",
                "health": {}
            }
        }
    },
    "is_cloud_instance": false,
    "setup_type": "single-node"
}

API for administrators to forcefully log out users

This API can be used by an administrator to forcefully log out a user from FortiSOAR

POST /api/auth/token HTTP/1.1
Host: <host>
Content-Type: application/json
Accept: application/json
Authorization: <Bearer Token>
{
    "action": "logout",
    "users": [
        "d5d4e360-2725-40d1-9fe2-d9e9f3886a04"
    ]
}

Create users in bulk

Use the /api/3/insert/people API to create uses in bulk.

Request

METHOD: POST
URL: https://{HOSTNAME}/api/3/insert/people
BODY:
{"data":
 [
   {
     "username":"user4@gmail.com",
     "email":"user4@gmail.com",
     "firstname":"user4",
     "lastname":"4",
     "phoneMobile":"",
     "roles":[],
     "accessType":"Concurrent",
     "csActive":false,
     "loginType":6,
     "uuid":"482c47ad-edfd-42ec-b908-437cd5f86efb",
     "user":
       {
         "loginid":"user4@gmail.com",
         "user_type":6,
         "access_type":"Concurrent",
         "status":2
       }
   },
   {
     "username":"user5@gmail.com",
     "email":"user5@gmail.com",
     "firstname":"user5",
     "lastname":"5",
     "phoneMobile":"",
     "roles":[],
     "accessType":"Concurrent",
     "csActive":false,
     "loginType":6,
     "uuid":"3311f11e-2755-4076-8004-c028f17984a7",
     "user":
       {
         "loginid":"user5@gmail.com",
         "user_type":6,
         "access_type":"Concurrent",
         "status":2
       }
   }
 ]
} 

Note: user_type in the user key specifies the type of user to be created. For example "user_type":6 is used to creating SSO users.

High Availability Health Cluster API

This API is used to retrieve information for the nodes in a High Availability (HA) cluster from the database.

GET /api/auth/cluster/health/: Used to retrieve health information for all the nodes in an HA cluster from the database.

GET /api/auth/cluster/health?nodeId=<cluster-node-id>: Used to retrieve health information for a particular node in an HA cluster from the database.

GET /api/auth/cluster/health?latest=True&section=cpu,disk,ram,swap,all,services: Used to retrieve the latest health information for the node who is serving the API from the database.

Model Operations

Create Individual Model Records

Request

METHOD: POST
URL: /api/{version}/{collection}
BODY:
{
  "field1": "value1",
  "field2": "value2"
}

Example

Request

METHOD: POST
URL: /api/3/assets
BODY:
{
  "ip": "8.8.8.8",
  "hostname": "google-public-dns-a.google.com"
}

Response

STATUS: 201
BODY:
{
  "@id": "/api/3/assets/01199609-d60f-356b-a762-129a6e1b353b",
  "@type": "Asset",
  "ip": "8.8.8.8",
  "hostname": "google-public-dns-a.google.com"
}

Retrieve Collection of Model Records

The responses adhere to the Hydra Spec for pagination. Records that match the specified query are returned as objects within the "hydra:member" array.

Request

METHOD: GET
URL: /api/{version}/{collection}

Response

STATUS: 200
BODY:
{
  "@context": "/api/{version}/contexts/{collection type}",
  "@id": "/api/{version}/{collection}",
  "@type": "hydra:PagedCollection",
  /* Contains some Hydra pagination properties */
  "hydra:member": [
    { "@id": "/api/{version}/{collection}/{uuid}", ... },
    { "@id": "/api/{version}/{collection}/{uuid}", ... },
    { "@id": "/api/{version}/{collection}/{uuid}", ... }
  ]
}

From version 7.0.0 onwards, the 'Pagination' response has changed as follows:

  • The hydra 'next' attribute is not displayed in the API response, if there are no further results.
  • The Item per page key has been removed.
  • The new 'pagination' response has hydra: view with first page, next page, and last page information.

If you require the legacy view for records, though it is not recommended, you can add the $legacy_collection_view=true query parameter in the API request. If you set the $legacy_collection_view=true parameter, then the API request will also contain the following older keys:

  • 'hydra:itemsPerPage'
  • 'hydra:firstPage'
  • 'hydra:lastPage'

Example

Request

METHOD: GET
URL: /api/3/assets

Response

STATUS: 200
BODY:
{
  "@context": "/api/3/contexts/Asset",
  "@id": "/api/3/assets",
  "@type": "hydra:PagedCollection",
  "hydra:totalItems": 2,
  "hydra:itemsPerPage": 30,
  "hydra:firstPage": "/api/3/assets",
  "hydra:lastPage": "/api/3/assets",
  "hydra:member": [
    {
      "@id": "/api/3/assets/01199609-d60f-356b-a762-129a6e1b353b",
      "@type": "Asset",
      "ip": "8.8.8.8",
      "hostname": "google-public-dns-a.google.com"
    },
    {
      "@id": "/api/3/assets/017d3845-e204-367c-b74d-6bb37a8239b7",
      "@type": "Asset",
      "ip": "8.8.4.4",
      "hostname": "google-public-dns-b.google.com"
    }
  ]
}

Retrieve Single Model Records

Request

METHOD: GET
URL: /api/{version}/{collection}/{uuid}

Response

STATUS: 200
BODY:
{
  "@id": "/api/{version}/{collection}/{uuid}",
  "@type": "{collection type}",
  "field1": "value1",
  "field2": "value2"
}

Example

Request

METHOD: GET
URL: /api/3/assets/01199609-d60f-356b-a762-129a6e1b353b

Response

STATUS: 200
BODY:
{
  "@id": "/api/3/assets/01199609-d60f-356b-a762-129a6e1b353b",
  "@type": "Asset",
  "ip": "8.8.8.8",
  "hostname": "google-public-dns-a.google.com"
}

Update Single Model Records

Request

METHOD: PUT
URL: /api/{version}/{collection}/{uuid}
BODY:
{
  "field1": "value1",
  "field2": "value2"
}

Example

Request

METHOD: GET
URL: /api/3/assets/01199609-d60f-356b-a762-129a6e1b353b
BODY:
{
  "ip": "8.8.8.8"
}

Response

STATUS: 200
BODY:
{
  "@id": "/api/3/assets/01199609-d60f-356b-a762-129a6e1b353b",
  "@type": "Asset",
  "ip": "8.8.8.8",
  "hostname": "google-public-dns-a.google.com"
}

Delete Single Model Records

Caution

Deleting models can result in system instability and data model. We advise that you do not delete models after creation.

Request

METHOD: DELETE
URL: /api/{version}/{collection}/{uuid}

Example

Request

METHOD: DELETE
URL: /api/3/assets/01199609-d60f-356b-a762-129a6e1b353b

Response

STATUS: 204
REASON: No Content

Insert records in bulk

You can use the Bulk Insert API to insert records in bulk, in a module that you specify.

From version 7.0.0 onwards, the bulk API response has been changed to 'success' or 'failure', compared to earlier releases where multistage single, failed, and bad requests were passed.

Note

It is recommended that you insert up to 200 smaller records such as assets, indicators, etc. in single request and loop over your dataset. If you have larger records such as, alerts and incidents with large sourcedata, then the recommended batch size is 100.

Request

METHOD: POST
URL: {{YourFortiSOARHostname}}/api/{version}/insert/{moduleType}
BODY: {
		"data”: [{record 1}, {record 2}]
	  }		
}

Example

Request

METHOD: POST
URL: {{YourFortiSOARHostname}}/api/3/insert/alerts
BODY: {
		"data": [
        {
            "name": "bulk record 1",
            "description": "<p>bulk record 1 description</p>",
            "severity": "/api/3/picklists/58d0753f-f7e4-403b-953c-b0f521eab759"
        },{
            "name": "bulk record 2",
            "description": "<p>bulk record 2 description</p>",
            "severity": "/api/3/picklists/58d0753f-f7e4-403b-953c-b0f521eab759"
        },{
            "name": "bulk record 3",
            "description": "<p>bulk record 3 description</p>",
            "severity": "/api/3/picklists/58d0753f-f7e4-403b-953c-b0f521eab759"
        }
    ]	
}

Response: If all the records are inserted successfully, then you will get a 200 OK response. If not all the records can be inserted, then you will get a 207 (Partially Deleted) response.

Example of a complete response:

{
   “@context”: “/api/3/contexts/Alert”,
   “@id”: null,
   “@type”: “hydra:Collection”,
   “hydra:member”: [
       {
           inserted record data
       }
   ]
}

Delete records in bulk

You can use the Bulk Delete API to delete records in bulk, in a module that you specify.

Request

METHOD: DELETE
URL: {{YourFortiSOARHostname}}/api/{version}/delete/{moduleType}
BODY: {
		"ids": ["value1", "value2", "value3"]
	  }		
}

Example

Request

METHOD: DELETE
URL: {{YourFortiSOARHostname}}/api/3/delete/alerts
BODY: {
		"ids": ["13d7115a-2d4d-4bfb-bdb8-efabfce547f011", 
				"13d7115a-2d4d-4bfb-bdb8-efabfce547f012", 
				"13d7115a-2d4d-4bfb-bdb8-efabfce547f013"]
	  }		
}

Response: If all the records are deleted successfully, then you will get a 200 OK response. If not all the records can be deleted, if for example, you have provided an ID of an already deleted record, then you will get a 207 (Partially Deleted) response.

Update records in bulk

You can use the Bulk Update API to update records in bulk, in a module that you specify.

Request

METHOD: PUT
URL: {{YourFortiSOARHostname}}/api/{version}/update/{moduleType}
BODY: {
	“data” : [
		{
 			"field1": "value1",
  			"field2": "value2", 
  			"field3": "value3"
		},
		{
 			"field1": "value1",
  			"field2": "value2", 
  			"field3": "value3"
		}
	]
}

Example

Request

METHOD: PUT
URL: {{YourFortiSOARHostname}}/api/3/update/alerts
BODY: {
	“data” : [
		{
 			“@id”: “/api/3/alerts/a3abeb23-f323-45a9-856b-2bf9d10386cb”,
  			“source”: “1238765”, 
  			"description": "Test 1"
		},
		{
 			“@id”: “/api/3/alerts/8c086c21-2c79-4488-ae22-d0e116469fe2”,
  			“source”: “097353”,
  			“description”: “Test 2”,
		}
	]
}

Response: The response will contain all the fields specified in the metadata of the module. Following is a snippet extract of a successful response:

STATUS: 200
BODY: {
	“data” : [
		{
 			“@id”: “/api/3/alerts/a3abeb23-f323-45a9-856b-2bf9d10386cb”,
  			“source”: “1238765”, 
  			"description": "Test 1"
		},
		{
 			“@id”: “/api/3/alerts/8c086c21-2c79-4488-ae22-d0e116469fe2”,
  			“source”: “097353”,
  			“description”: “Test 2”,
		}
	]
}

Notes:

  • If you provide the body of the request appropriately, then all the records get successfully updated to the specified module, and you get a 200 OK response.
  • If you do not provide an id for an object (record), then the module is partially updated with the records that have an associated id. Records that do not have an id will not be updated in the specified module. In this case, you get a 207 response, which will list the records that are not updated.
  • If you specify a null value for any field, those records get successfully updated.

Upsert records

Note

Upsert works only if you have defined uniqueness for records in the module you want to upsert records. If you have not defined record uniqueness, the upsert operation will always insert records. Also, note that when you are upserting records, fields that are marked as non-editable also get updated and the upsert behavior for uniqueness will not work for fields that are marked as encrypted.

Single Upsert API

You can use the Upsert API to either update an existing record, if any record matches the unique list of fields you have specified for that module using the Module Editor, or insert a new record.

Request

Following is a sample request for a single upsert request:

METHOD: POST
URI: {{YourFortiSOARHostname}}/api/3/upsert/{moduleType}
BODY: 
      {
	   	"name": "value1",
  		"sourceId": null, 
  		"severity": "value2"
      }

Bulk Upsert API

You can use the Bulk Upsert API to either bulk update multiple records, if the records match the unique list of fields you have specified for that module, or bulk insert new records.

Request

Following is a sample request for a bulk upsert request:

METHOD: POST
URI: {{YourFortiSOARHostname}}/api/3/bulkupsert/{moduleType}
BODY:[ 
       {
	   	"name": "value1",
  		"sourceId": "null", 
  		"severity": "value2"
	   },
      {
	   	"name": "value1",
  		"sourceId": "null", 
  		"severity": "value2"
	   }
]

Response: If all the records are upserted successfully, then you will get a 200 OK response. If some records are upserted successfully and some records are not upserted, then you will get a 207 (Partial Upsert) response. If none of the records are upserted successfully, then you will get a 400 response.

Relationship Operations

For these examples, we will expect that an Incident has already been created in the system. All these operations will affect the assets field of an Incident.

Get Relationship

Request

METHOD: GET
URL: /api/3/incidents/bbdc13f8-015f-4615-8c63-4cebb6ec991b/assets

Response

{
  "@context": "/api/3/contexts/Asset",
  "@id": "/api/3/incidents/bbdc13f8-015f-4615-8c63-4cebb6ec991b/assets",
  "@type": "hydra:PagedCollection",
  "hydra:totalItems": 1,
  "hydra:itemsPerPage": 30,
  "hydra:firstPage": "/api/3/incidents/bbdc13f8-015f-4615-8c63-4cebb6ec991b/assets",
  "hydra:lastPage": "/api/3/incidents/bbdc13f8-015f-4615-8c63-4cebb6ec991b/assets",
  "hydra:member": [
    {
      "@id": "/api/3/assets/2ac5eafd-e7dd-465e-8ddd-6b9aeb7125c0",
      "@type": "Asset",
      "macAddress": "as:se:t2",
      "id": 639
    }
  ]
}

From version 7.0.0 onwards, the support for getting the count of related records by passing the $relationshipCount flag (api/3/<module>/uuid/<associateModule>?Countonly=true) on only queries has been removed. Now, to get relationships count, FortiSOAR has provided alternate route of aggregation support on /api/query/module, which is much faster.

Append Existing Object to Relationship

Request

METHOD: POST
URL: /api/3/incidents/bbdc13f8-015f-4615-8c63-4cebb6ec991b/assets
BODY:
{
  "@id": "/api/3/assets/e0a3521f-67de-473f-a9a0-7f2d44626567"
}

Response

{
  "@id": "/api/3/assets/e0a3521f-67de-473f-a9a0-7f2d44626567",
  "@type": "Asset",
  "macAddress": "as:se:t1",
  "id": 638
}

The behavior of linking records relationships has changed in version 7.0.0 because if there is a record that is linked to thousands of other records, an update to such records causes constant high CPU usage. An example of such a record would be indicators like org name that get extracted as part of every alert and get linked to thousands of alerts. Therefore, it is recommended that you link a maximum of 99 records in a single API call. This is because, if there are less than 99 records linked then the framework checks if the record being linked is already present in existing relations and if the same record is linked again and again, post-update triggers on relation "isChanged" is not triggered, also the linking is not audited again every time. However, from the 100th linked record, the framework only looks at the __link, __unlink keys, and hence, if the same record is linked again and again, post-update triggers on relation "isChanged" will get triggered, and also the linking gets audited again every time.

Append New Object to Relationship

Request

METHOD: POST
URL: /api/3/incidents/bbdc13f8-015f-4615-8c63-4cebb6ec991b/assets
BODY:
{
  "macAddress": "as:se:t3",
  "assetType": "laptop"
}

Response

{
  "@id": "/api/3/assets/5434a6e1-e9cd-4ecf-ba6b-f8ac82c3effc",
  "@type": "Asset",
  "macAddress": "as:se:t3",
  "id": 639
  "assetType": "laptop"
}

Delete Relationship

Request

METHOD: DELETE
URL: /api/3/incidents/bbdc13f8-015f-4615-8c63-4cebb6ec991b/assets/
e0a3521f-67de-473f-a9a0-7f2d44626567

Response

STATUS: 204
REASON: No Content

Audit Log Purge Operations

You can use the Audit Log Purge API to purge audit logs on an automated as well as on-demand basis.

Stop Automatic Purging of Audit Logs

To stop automatic purging of audit logs, run the following API:

Request

Method: DELETE 
URL:  /gateway/audit/activities/ttl
Content-Type: application/json
Authorization: <Bearer Token>

Example:

DELETE /gateway/audit/activities/ttl
Content-Type: application/json
Authorization: <Bearer Token>

Response: If the API is successfully run you will get a 200 OK response, which stops the automatic purging of audit logs.

Delete audit logs before a particular date

To delete audit logs before a particular date, run the following API:

Request

Method: DELETE 
URL:  /gateway/audit/activities
Authorization: <Bearer Token>
Cache-Control: no-cache

Example:

DELETE /gateway/audit/activities?uptoDate=1524477805
Authorization: <Bearer Token>
Cache-Control: no-cache

Response: If the API is successfully run you will get a 200 OK response and then audit logs that exist before the specified date will be purged.

Export and Import Configurations Operations

From version 6.4.3 onwards, to import and export configurations, you can use the respective APIs. You can also schedule API-based configuration export and imports. Alternatively, you can also use the FortiSOAR UI to run a wizard-based export and import of configuration information. For more information on the using the wizard-based export and import, see the Configuration Export and Import topic in the Application Editor chapter of the "Administration Guide."

Importing Configurations

To import a configuration using the API, the configuration must be in the JSON format. Follow these steps to import a configuration:

Step 1: Create an import job.

    POST /api/3/import_jobs 
    { 
    "status": "In Progress", 
    "file": "/api/3/files/<uuid of uploaded json file>" 
    } 

This request creates an import job; whose output contains the @id of the import_jobs record. You can extract the UUID from the @id, whose format is /api/3/import_job/<uuid>, and use this UUID in future requests to trigger the import.

Step 2: Generate the import options.

GET /api/import/<import job uuid>

This request populates the options object for the import job with the default options required for import. After generating the defaults, you can modify the default options by updating the import job record with the following requests.

To get the options object:

GET /api/3/import_jobs/<import job uuid>

To modify the options object:

PUT /api/3/import_jobs/<import job uuid> 
{ 
"options": (modified options object) 
} 

Step 3: Trigger the import.

PUT /api/import/<import job uuid>

This request triggers the import, which runs asynchronously. You can check the status of the import using the following request:

GET /api/3/import_jobs/<import job uuid>

Exporting Configurations

Follow these steps to export a configuration, in the JSON format, using the API:

Step 1: Create an export template or use an existing export template.

POST /api/3/export_templates 
{ 
  "options": { 
    "modules": [...], 
    "viewTemplates": [...], 
    "picklistNames": [...], 
    "views": [...], 
    "reports": [...], 
    "dashboards": [...], 
    "roles": [...],   
    "appSettings": [...], 
    "playbooks": { 
      "collections": [...], 
      "includeVersions": false, 
      "globalVariables": [...] 
    } 
  }, 
  "name": "Configuration Export" 
} 

Following is a sample template containing data:

{ 
  "options": { 
    "modules": [ 
      "agents" 
    ], 
    "viewTemplates": [ 
      "modules-agents-list", 
      "modules-agents-detail", 
      "modules-agents-form" 
    ], 
    "picklistNames": [ 
      "/api/3/picklist_names/114d88e4-ceaa-4b9f-842b-cca8db90f418", 
      "/api/3/picklist_names/a7ce1d03-a4e4-4750-afdd-ca3cbb6a03b3", 
      "/api/3/picklist_names/663eb9f2-d362-4640-a2f1-f5432c6d3c4e", 
      "/api/3/picklist_names/a255a02f-2f4d-4535-baaf-6c64c1d6f5d0" 
    ], 
    "views": [ 
      "app" 
    ], 
    "reports": [ 
      "11ece146-396e-42f8-a2c4-358550c6f03f" 
    ], 
    "dashboards": [ 
      "2bc7fd32-1cc6-48b0-bcbb-3a7c09938d4a" 
    ], 
    "roles": [ 
      "/api/3/roles/21d7a7c6-9d68-438f-b732-e8950c5f745b" 
    ], 
    "appSettings": [ 
      "sso" 
    ], 
    "playbooks": { 
      "collections": [], 
      "includeVersions": false, 
      "globalVariables": [ 
        "Body" 
      ] 
    } 
  }, 
  "name": "Configuration Export" 
} 

Alternatively, you can also create the export template using the Configuration Export Wizard in the FortiSOAR UI and use the UUID of that template for further requests.

Step 2: Trigger the export.

PUT /api/export?fileName=<file name ending in .json>&template=<export template uuid>

This request triggers the export and sends the following response:

{"@type": "ExportJob", "jobUuid": "<export job uuid>"}

Step 3: Download the file.

GET /api/3/export_jobs/ <export job uuid>

To request retrieves the status of the export and sends the following response:

{"file": {…}, "status": "Export Complete"}

When the status equals “Export Complete”, a file object is returned. You can download the exported file using its "File IRI".

Integration APIs

You can use 'Integration APIs' can be used in playbooks to perform various actions such as retrieving health information for connectors, creating configurations for connectors, etc.

Retrieving connector details

  • To get a list of all connectors installed on a FortiSOAR instance:
    GET api/integration/connectors/
  • To get a list of all connectors that being developed on a FortiSOAR instance:
    POST /api/integration/connector/development/list/
    Body {}
    Note: Body is Empty JSON.
  • To get details of any installed connector:
    POST api/integration/connectors/<connector_name> /<connector_version>/
    Body {}
    Note: Body is Empty JSON.
    Example: api/integration/connectors/cyops_utilities/3.1.2/
    Note: If the specified version, 3.1.2, in our example is not installed, then the API returns details of same connector (cyops_utilities) with latest version installed, for example, version 3.1.1.

Creating configurations for any connector

To create configurations for connectors:

POST /api/integration/configuration/
Body
{
   "connector": <connector_id>,
   "connector_name": <connector_name>,
   "connector_version": <connector_version>,
   "name": <config_name>,
   "config_id": <config_id>,
   "default": <true/false>,
   "config": {
     "<connector_config_field1>”: "<value>",
     "<connector_config_field2>”: "<value>",
     "<connector_config_field3>”: "<value>",
   },
}

Example of the 'Body' of a connector:

{
   "connector": 2,
   "connector_name": "imap",
   "connector_version": "3.5.6",
   "name": "test",
   "config_id": "b6412f73-a1b0-4446-a66a-99460133b780",
   "default": true,
   "config": {
     "host": "imap.gmail.com",
     "port": "993",
     "username": "demo@gmail.com",
     "password": "test@123",
     "ssl": true,
     "source": "INBOX",
     "destination": "PROCESSED",
     "verify": true,
     "notification_service": ""
   }
}

Notes:

  • You must specify either the connector_id or connector_name.
  • You must specify the connector_version.
    If connector_version specified is invalid, then the latest installed version of same connector is considered.
  • It is not mandatory to provide the config_id, as a UUID gets automatically generated.

Retrieving health check details for a connector

To get the heath check details for a connector:
GET /api/integration/connectors/healthcheck/<connector_name>/<connector_version>/?config=<config_id>

Example: /api/integration/connectors/healthcheck/imap/3.5.6/?config=a7c7df29-1f5c-426e-981b-b1ab1b7692cb

Note: If you specify an invalid config_id, then the health check details of the 'default' configuration of the specified connector is returned.

Deleting a configuration of a connector

To delete a specific configuration of a connector:
DELETE /api/integration/configuration/<id>/

Example: /api/integration/configuration/8

Executing an action of a installed connector

To execute an action of an installed connector:

POST /api/integration/execute/
Body
{
   "connector": <connector_id>,
   "version": <connector_version>,
   "config": <config_id>,
   "operation": "<action_name>",
   "params": {
     "<action_param1>": <value>,
     "<action_param2>": <value>
   },
}

Example of the 'Body' of a connector:

{
   "connector": "imap",
   "connector_version": "3.5.6",
   "config": "a7c7df29-1f5c-426e-981b-b1ab1b7692cb",
   "operation": "fetch_email_new",
   "params": {
     "limit_count": 30,
     "parse_inline_image": true
   }
}

Uninstalling a connector

To uninstall a connector:
DELETE /api/integration/connectors/<id>/

Example: /api/integration/connectors/15

Workflow Execution

You can use the Workflow Execution API to debug playbook execution, apply filters on running playbooks, retrieve playbook IDs, list execution logs, etc.

Workflow Execution History

GET /api/wf/api/workflows/?format=json: Used to list the workflow execution history.

GET /api/wf/api/workflows/29/?format=json: Used to retrieve the detailed view of a particular workflow execution history based on the ID specified.

You can filter the workflow execution history by specifying various query parameters such as, ordering, and filters such as status. An example of the Workflow Execution API with parameters and filters is: GET /api/wf/api/workflows/?format=json&status=finished&ordering=-created.

Following query parameters are supported:

  • Offset - The initial index from which to return the results.
  • Limit - The maximum number of results to return per page.
  • Ordering - The field using which you want to sort the results. For example, ordering=-created sorts the results in the descending order based on the creation date.

Following filters are supported:

  • template_iri – Filters the workflow execution history based on the playbook IRI specified, i.e., retrieves the execution history for a particular playbook. For example, /api/wf/api/workflows/?template_iri= "/api/3/workflows/".
  • records - Filters the workflow execution history based on the record ID specified, i.e., retrieves the execution history for playbooks execution on a specific record. For example, /api/wf/api/workflows/?records= "/api/3/alerts/alert_id".
  • status – Filters the workflow execution history based on the running status of the playbooks. The running state of the playbooks can be incipient, active, failed, finished, awaiting, skipped, or terminated. For example, /api/wf/api/workflows/?status=failed, retrieves the execution history of all playbooks that have failed.
  • ?created_after=""&created_before="" – Filters the workflow execution history based on the time range specified. For example, /api/wf/api/workflows/?created_after=2020-11-08&created_before=2020-11-10, retrieves the execution history of all playbooks that are executed between the 8th and 10th of November, 2020.
  • ?parent__isnull=True – Filters the workflow execution history to retrieve the history of only the parent playbooks, i.e., specifying this filter will filter out the execution history of all children playbooks.
  • tags_exclude="",&tags_include="" – Filters the workflow execution history based on the comma-separated list of tags specified. You can specify that you want to include the execution history of playbooks containing particular tags or you want to exclude the execution history of playbooks containing particular tags or a combination of both. For example, /api/wf/api/workflows/?tags_exclude=system,&tags_include=ingestion,critical retrieves the execution history of all playbooks that contain the ingestion or critical tags and excludes all playbooks containing the system tag.

Workflow Execution Log

FortiSOAR version 6.4.4 has enhanced the Workflow Execution Log API (/api/wf/api/query/workflow_logs/) to fetch data from the database based on user configuration. The workflow_logs API now supports queries in the POST request. If {'query': {}} is found in the POST body of the API call, then the query set is formed based on the users' input data. Otherwise, the query works as per the current functionality, i.e., the query picks up parameters from the URL.

An example of a query containing the supported filters follows:

{
    "logic": "AND/OR",
    "limit": "30",
    "sort": [{
        field: "modified/status/name"
        direction: "asc/desc"
    }],
    "filters": [{
        "field": "status/user/tags/modified/name",
        "operator": "eq/contains/neq/ncontains/gte/lte",
        "value": ""
    }],
    "aggregates": [{
            "operator": "groupBy/count",
            "field": "status/user/name/id"
        }
    ]
}

An example of a query containing nested filters follows:

 "logic": "OR",
    "limit": 30,
    "filters": [{
        "logic": "OR",
        "filters": [{
            "field": "tags",
            "operator": "contains",
            "value": "test"
        }, {
            "field": "tags",
            "operator": "contains",
            "value": "testing"
        }]
    }, {
        "logic": "AND",
        "filters": [{
            "field": "status",
            "operator": "eq",
            "value": "finished"
        }, {
            "field": "status",
            "operator": "eq",
            "value": "failed"
        }]
    }]
}

Deleting workflow logs and cleaning up the workflow table

You can also use the Workflows API to retrieve details of an existing schedule used to purge workflow logs, update details and configuration of an existing schedule used to purge workflow logs, and also delete workflow logs.

You can use the 'Workflow Table Cleanup' API (new in version 7.0.2) to shrink the space of the workflow space and make unused space available to system.

Deleting workflow logs

You can use the Workflows API to delete workflow logs along with a date filter.

Request

METHOD: DELETE
URL: /api/wf/api/workflows/delete/?format=json
BODY:
{
  "date": "<Before_Date_filter>",
  "userId": "<user_id>",
  "user": "<user_name>"
  "exclude_awaiting_wf": <true/false>
}

Response

{"result": "deleting workflows"}

The following filters are supported:

  • date: The date before which the workflow logs should be deleted.
  • exclude_awaiting_wf: Whether or not workflow logs that are in the 'awating' state should be excluded from deletion. If you specify true then the workflow logs that are in the 'awating' state are excluded from deletion, i.e., they are not deleted.

Example

Delete /api/wf/api/workflows/delete/?format=json 
Body  
{ 

  "date": "2021-05-03T18:30:00.000Z", 
  "userId": "3451141c-bac6-467c-8d72-85e0fab569ce", 
  "user": "CS Admin", 
  "exclude_awaiting_wf": true 
} 

Cleanup the Workflow table

The 'Workflow Table Cleanup' API clears all the empty rows in tables and indexes and makes the unused space available to the system, which helps in improving the performance by optimizing the space.

POST /api/wf/api/workflows/auto_vacuum/?format=json: Used to clean up the workflow table and all the tables that are related to the workflow table:

Request

METHOD: POST
URL: /api/wf/api/workflows/auto_vacuum/?format=json
BODY:
{
  "date": "2021-07-22 09:00:35",
  "userId": "<current_users_id>",
  "user": "<current_user_name>"
}

Log Collection Operations

There are two APIs introduced in version 7.0.0 for collecting FortiSOAR logs. Log collection can be a long-running task, so the API should be asynchronous and should not wait for the log collection operation to be completed. Therefore, two APIs are added: One API starts the process of collecting logs and the other one downloads the collected log file.

The logs get collected in the /opt/cyops-api/workspace/logs directory and users require Security Read permission to perform the log collection operations.

Triggering log collection

To start the process of log collection, use the following request:

Request

POST/api/3/utils/log-collect HTTP/1.1 
Host: <account_id>.fortisoar.forticloud.com 
Authorization: <Bearer Token> 
{
    "password": "Test"
}

Note: The Password parameter is optional, i.e., you do not need to input the password.

Response

{
    "filename": "fortisoar-logs.tar.gz.gpg"
}

The filename is "fortisoar-logs.tar.gz.gpg" if you have supplied a password in the request. Else, the filename is "fortisoar-logs.tar.gz".

If the log collection is triggered successfully, then status code 200 is returned. If another log collection request is running, then status code 202 is returned.

Downloading the collected log file

To download the collected log file, use the following request:

Request

GET /api/3//utils/log-collect?filename=<filename> HTTP/1.1 
Host: <account_id>.fortisoar.forticloud.com 
Authorization: <Bearer Token> 

Response

A file is downloaded with the name fortisoar-logs.tar.gz.gpg (or fortisoar-logs.tar.gz) according to the input provided (password specified or not) in the API request, if corresponding previous log collection operation was successful.

If log collection process is still running, then status code 202 is returned. If the log collection file is not found, then status code 400 is returned.