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.
View consolidated permissions for users or appliances
Use this API to view the aggregated list of effective permissions based on different roles assigned to a given user or appliance.
Request
METHOD: GET
URL: https://<IP>/api/actors/permission/<actor uuid>
Response
{ "application": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "security": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "appliances": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "people": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "routers": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "tenants": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "agents": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "contentHub": { "create": false, "read": true, "update": false, "delete": false, "execute": false, "fields": [] }, "workflows": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "files": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "activities": { "create": true, "read": true, "update": true, "delete": false, "execute": false, "fields": [] }, "reporting": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "attachments": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "comments": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "companies": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "fsr_queues": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "shifts": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "tasks": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "connectors": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "email_templates": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "schedules": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "approvals": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "saved_reports": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "dashboard": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "widgets": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "data_archival": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "rules": { "create": true, "read": true, "update": true, "delete": true, "execute": false, "fields": [] }, "solutionpacks": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "alerts": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "announcements": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "assets": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "campaigns": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "communication": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "events": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "hunt": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "incidents": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "indicators": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "sla_template": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "warrooms": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] }, "scenario": { "create": true, "read": true, "update": true, "delete": true, "execute": true, "fields": [] } }
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§ion=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
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.
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 a207
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
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: PUT
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
orconnector_name
. - You must specify the
connector_version
.
Ifconnector_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.
Notification Framework APIs
Channel APIs
Get List of all Channels
Use this API to retrieve a list of all notification channels in your system. The API response contains the list of channels in the hydra:member
property.
Request
METHOD: GET
URL: /api/rule/api/channel/
Response
{ "@context": "/rule/api/channel/context/", "hydra:nextPage": null, "hydra:previousPage": null, "hydra:totalItems": 6, "hydra:itemsPerPage": 10, "hydra:firstPage": "/rule/api/channel/", "hydra:lastPage": "/rule/api/channel/?offset=0", "hydra:member": [] }
Update Channel
Use this API to update any non-system channel, i.e., any channel created by a user. The API will return the updated channel in its response.
Request
METHOD: PUT
URL: /api/rule/api/channel/<channel_uuid>/
BODY:
{ "type": "connector", "name": "demo channel", "description": "This is the demo channel", "config": { "config": "88c3d39c-2fa9-4731-b00d-29815008f17c", "version": "2.4.3", "label": "SMTP", "connector": "smtp", "operation": "send_email" }, "retryCount": 0, "is_active": true, "default_params": { "to_recipients": "", "cc_recipients": "", "bcc_recipients": "", "body": "", "subject": "", "iri_list": "" } }
Create Channel
Use this API to create a custom channel that contains the configuration for any rule that requires to be executed.
Following is an example to create a 'connector' type channel that contains the configuration details of the connector that is used in the channel.
Request
METHOD: POST
URL: /api/rule/api/channel/
BODY:
{ "type": "connector", "name": "demo channel", "description": "This is the demo channel for updating", "config": { "config": "88c3d39c-2fa9-4731-b00d-29815008f17c", "version": "2.4.3", "label": "SMTP", "connector": "smtp", "operation": "send_email" }, "retryCount": 0, "is_active": true, "default_params": { "to_recipients": "demo@fortinet.com", "cc_recipients": "", "bcc_recipients": "", "body": "", "subject": "", "iri_list": "" } }
Delete Channel
Use this API to delete any non-system channel, i.e., any channel created by a user.
Request
METHOD: DELETE
URL: /api/rule/api/channel/<channel_uuid>/
BODY: {}
Rules APIs
Get List of all Rules
Use this API to retrieve a list of all rules in your system. The API response contains the list of rules in the hydra:member
property.
Request
METHOD: GET
URL: /api/rule/api/rules/
Response
{ "@context": "/rule/api/rules/context/", "hydra:nextPage": null, "hydra:previousPage": null, "hydra:totalItems": 6, "hydra:itemsPerPage": 10, "hydra:firstPage": "/rule/api/rules/", "hydra:lastPage": "/rule/api/rules/?offset=0", "hydra:member": [] }
Create Rule
Use this API to create a custom rule. The API will return the created rule in its response.
Request
METHOD: POST
URL: /api/rule/api/rules
BODY:
{ "name": "demo rule", "entity_type": "alerts", "event_type": "create", "trigger_condition": { "sort": [], "limit": 30, "logic": "AND", "filters": [{ "field": "status", "operator": "eq", "value": "/api/3/picklists/fac53e73-8d16-4189-98d5-95fbd1555232", "_value": { "itemValue": "Closed", "@id": "/api/3/picklists/fac53e73-8d16-4189-98d5-95fbd1555232" }, "type": "object" }] }, "actions": [{ "type": "connector", "params": { "body": "", "subject": "", "iri_list": "", "cc_recipients": "", "to_recipients": "demo@fortinet.com", "bcc_recipients": "" }, "channel_uuid": "8b8d5061-4cd2-4366-9f5a-6db47c7a18a6", "enabled": true }], "is_system": false, "is_active": true, "priority": 10, "event_source": "crudhub", "source": null, "channel_preference_field": null, "visible": true, "category": "generic", "expiry": null, "entity_id": null, "parent_rule": null, "workflow": null, "entity_name": "Alerts" }
Update Rule
Use this API to update any rule. The API will return the updated rule in its response.
Request
METHOD: PUT
URL: /api/rule/api/rules/<rule_uuid>/
BODY: Same as the body of the 'Create Rule' API but with updated fields.
Delete Rule
Use this API to delete any rule.
Request
METHOD: DELETE
URL: /api/rule/api/rules/<rule_uuid>/
BODY: {}
Bulk Rule Delete
Use this API to delete multiple rules at once by specifying a list containing the UUIDs of the rules you want to delete.
Request
METHOD: DELETE
URL: /api/rule/api/rules/bulk/delete
BODY: {"uuids":<list_of_rule_uuids>}
Response:{"message":"Rules are been deleted Successfully"}
Clone Rules
Use this API to clone multiple rules at once by specifying a list containing the UUIDs of the rules you want to clone.
Request
METHOD: POST
URL: /api/rule/api/rules/bulk/clone
BODY: {"uuids":[<list_of_rule_uuids>]}
Response:{"message":"Rules are been cloned Successfully"}
Bulk Update Rules
Use this API to update multiple rules at once by specifying a list containing the UUIDs of the rules you want to update and the parameters you want to update.
Request
METHOD: PUT
URL: /api/rule/api/rules/bulk/update
BODY:
{ "uuids": [<list_of_rule_uuids>], "payload": { "is_active": false } }
Response:{"message":"Rules are been updated Successfully"}
Get all the system notifications
Use this API to retrieve a list of all notifications from your system. The API will return the list of all system notifications in its response.
Request
METHOD: POST
URL: /api/rule/api/system-notification/notifications/?format=json
BODY: {}
Supported Query parameters
read
Theread
parameter takes boolean values 'true' or 'false' and returns all the system notification that are not-read or read.
For example the following API call:/api/rule/api/system-notification/notifications/?format=json&read=false
returns all unread notifications-
entity_type__in
Theentity_type__in
parameter takes either a single string or a comma-separated string of multiple values and returns all the system notification belongs to the given entity type.
For example the following API call:/api/rule/api/system-notification/notifications/?format=json&entity_type__in=approvals,manualinput
returns all notifications of type 'approval' or 'manual input'.
Mark system notification as read
Use this API to mark a specific system notification as read on your FortiSOAR system by specifying the UUID of the system notification you want to mark as read.
Request
METHOD: POST
URL: /api/rule/api/system-notification/read/?format=json
BODY: {“uuid”: <uuid_of_system_notification>}
Purging Notifications APIs
Purging of System Notification
Use this API to purge system notifications from your FortiSOAR system.
Purge all read system notifications
Use this API to delete all system notifications that are read from your FortiSOAR system.
Request
METHOD: POST
URL: /api/rule/api/system-notification/purge/?format=json&read=true
BODY: {}
Response:{"result": "System Notification purge started", "status": "started"}
Purge all system notifications
Use this API to delete all system notifications, whether read or unread, from your FortiSOAR system.
Request
METHOD: POST
URL: /api/rule/api/system-notification/purge/?format=json
BODY: {}
Response:{"result": "System Notification purge started", "status": "started"}
Purging of Notification Failure logs
Use this API to delete notification failure logs from your FortiSOAR system that are older than the date specified in the payload.
Request
METHOD: DELETE
URL: /api/rule/api/pending-notification/purge
BODY: {"date":"2022-06-20T07:58:01.447Z","userId":"<user_uuid>","user":"<user_name>"}
Response:{"result": "Failed Notification Logs purging initiated", "status": "started"}
Schedule API
Triggering a schedule immediately
You can trigger a schedule immediately using the 'scheduled
' API.
Request
METHOD: POST
URL: /api/wf/api/scheduled/trigger-now/
Response
If the schedule is successfully triggered then the API will give the following response:
{"message":"The associated schedule is successfully triggered"}