Version:

Version:

Version:

Version:


Table of Contents

API Guide

Download PDF
Copy Link

API Endpoints Reference

This gives a summary of the API endpoints available within FortiSOAR organized via category.

Category Description
Modules General access for CRUD operations on records within the Modules defined in the system database
Playbooks Access to both Playbook models, Step types (core system), Steps, and Custom Endpoints (Custom API Endpoint Triggers)
Configuration General management of the configuration of the system, including Users / Appliances (actors), View Templates, and Module / Model definitions

Query Parameters

Most endpoints allow for query parameters to be appended to the URL for scoping the specific data set being returned. Parameters are used to filter results from the query and change the result format.

Syntax

  1. The beginning of the query string is denoted by a ? appended to the end of a valid endpoint URL.
  2. Operational parameter values should start with a $.
  3. Filter values should not have a $.
  4. Parameters specify the specific value using =.
  5. Parameters are chained using the & character.

Sample URL

https://FortiSOAR.ROOT.URL/api/3/{collection}/{uuid}?parameter1=value&parameter2=value

Operations

The standard query parameters are given in the following table.

Parameter Valid Values Action
$relationships true, yes, false (default) Show or hide full field and value context for related records
$export true, yes, false (default) Display record in exportable/importable JSON format, e.g., "@id" is turned from an IRI to a simple "uuid" value
{fieldName} Any valid format for field type with url-encoded for special characters Filter results by fieldName using the equivalence operator. A fieldName can contain double underscores to specify a key within an object. For example, status__itemValue or assignedToPerson__firstname.
{fieldName}${operator} Any valid format for field type with url-encoded for special characters Filter results by fieldName using any operator. Operators that are supported are found in the Query API Reference chapter. A fieldName can contain double underscores to specify a key within an object.
$orderby Any valid {fieldName}, optional -{fieldName} operand Sort the returned data set by the values in a specific field, may be chained and accepts -value for inverse ordering
$limit An integer between 1 and 214748364 Maximum number of records to return in a query (default is 30)

Examples

/api/3/alerts?name=Full Alert Name
/api/3/alerts?name$like=%partial name%
/api/3/alerts?eventCount$gte=10&eventCount$lt=20
/api/3/alerts?status__itemValue=Open
/api/3/tasks?assignedToPerson__firstname$like=%doe%
/api/3/alerts?status__itemValue$in=Open |Resolved|In Progress
/api/3/alerts?$limit=100&$orderby=-createDate&$relationships=true

Module Endpoints

Module endpoints are grouped here by the Component to which they belong. At the root of the API, the models are not organized by Component. The component definition only exists within the system view metadata for defining the navigation.

Note

An important concept to grasp is that the Modules within the UI generally refer to a 1:1 relationship with a table. Beyond the UI, many of the Modules in the Role Editor are actually composed of multiple data models within the API. This section refers to the Modules that have a 1:1 data model relationship.

There are 3 optional endpoint formats defined within all modules. Each of these endpoints supports a specific set of standard operations.

Module Root

/api/3/{plural_module_name}

The Module Root displays a paginated listing of all records within that module. The default sorting is by last modified date.

/api/3/{plural_module_name}?{$filter_query}

The Module Root may be filtered to a specific set of criteria as opposed to generally listing all models within the database.

Supported Operations

All Module Root endpoints support the following operations.

Operation Description Formats
GET Allows you to read the list of records -
POST Insert a new record of the specified module type JSON
PUT Update an existing record, requires "@id" JSON
DELETE Delete an existing record, requires, requires "@id" -

Module Records

/api/3/{plural_module_name}/{record_uuid}

Supported Operations

All Module Record endpoints support the following operations.

Operation Description Formats
GET Allows you to read the list of records -

Playbook Endpoints

Custom Endpoints (Custom API Endpoint Trigger)

Endpoints Available

https://FortiSOAR.ROOT.URL/api/triggers/1/{name}
OR
https://FortiSOAR.ROOT.URL/api/triggers/1/deferred/{name}

These are user-defined endpoints generated based on the specified arbitrary name included in the Playbook trigger.

Custom API Endpoint Trigger

The deferred endpoints allow for alternate authentication means, i.e., no HMAC (token) requirement, for external systems that may only offer Basic or non-authenticated webhooks (No Authentication).

Configuration Endpoints

The Configuration endpoints primarily govern system and user interaction. Generally, it should not be necessary to use these endpoints outside of the UI, but they are provided here as a reference.

Model Metadatas

Caution

Modifications to the Model Metadatas and Attributes are not recommended due to the potential for database manipulation leading to a potentially difficult recovery..

Model Metadata describes every piece of customizable data models in our system. We have two pieces of metadata: Model and Attribute. Models are comprised of any number of Attributes. Attributes can be of any type, ranging from any JSON primitive type to relationships with existing entities. These relationships can be of type 'toMany' or 'toOne'.

ModelMetadata: /api/3/apidoc/ModelMetadata

  • Type [type]
    Metadata type, JSON primitive for attributes or internal types for models. See type for AttributeMetadata for valid JSON primitives.
  • Parent Type [parentType]
    The type of the parent, if set to null, will default to the BaseEntity class.
  • Table Name [tableName]
    The table name for ORM, this will be the table that is created in the database.
  • Ownable [ownable]
    Determines if this class should have the ownable fields, user ownable and team ownable.
  • Trackable [trackable]
    Determines if this module should have the trackable fields (createDate, createUser, modifyDate, modifyUser)
  • Indexable [indexable]
    Determines if this class should have the indexable fields (id). This gives the object a global sequence id field.
  • Attributes [attributes]
    Key-value list of the attributes for this class. These attributes can be described here: /api/3/apidoc/AttributeMetadata
  • Display Template [displayTemplate]
    Template for the display name of record as an AngularJS template.
  • Descriptions [descriptions]
    Map of description type => description, example:
      {
          "singular" : "Alert",
          "plural" : "Alerts"
      }
    

AttributeMetadata: /api/3/apidoc/AttributeMetadata

  • Id [id]
    The unique object id for this attribute, will be auto generated if not specified.
  • Type [type]
    Metadata type, JSON primitive for attributes or iri/internal types for models. Supported primitives are:
    integer,
    string,
    id,
    boolean,
    number,
    null
    object,
    array
    Note: Adding an array field type is currently not supported through the FortiSOAR UI.
    object and array are special types. See the Extended Data section below.
    Tip: null is supported in theory but might not make sense to use.
  • Name [name] (required, unique) The name of the attribute.
    Note: DO NOT use underscores in the field name. Must be Camel-Case.
  • Length [length]
    The length of the attribute. For anything less than 255, it will created in the SQL database as a VARCHAR with a defined length.
  • FormType [formType]
    The type of form to use to render this attribute. Supported types are:
    integer,
    text,
    textarea,
    checkbox,
    manyToMany,
    datetime,
    picklist,
    lookup,
    oneToMany,
    file,
    manyToOne,
    richtext,
    phone,
    email,
    json
  • Data Source [dataSource]
    The source of the data, not defined explicitly. An example of picklist lookups:
      {
          "module" : "picklists",
          "query": {
              "logic": "AND",
              "filters": [
                  {
                    "field": "listName__name",
                    "operator": "eq",
                    "value": "Criticality"
                  }
              ],
              "sort": [
                  {
                    "field": "orderIndex",
                    "direction": "ASC"
                  }
              ]
          }
      }
    
    An example of a relationship for all items in a collection, query is null because no query should be made to limit the lookup:
      {
          "module" : "alerts",
          "query" : null
      }
    
  • Searchable [searchable]
    Determines if this attribute should be searchable within a grid in the FortiSOAR UI. This does not affect record indexing in ElasticSearch. The field will yet be displayed in the global search results in the UI even if it is not marked as searchable.
  • Grid Column [gridColumn]
    Determines if this attribute should show up in a grid by default.
  • Mapped By [mappedBy]
    Field name on the referenced type, if it is a collection and not the owner of a relationship.
  • Inversed By [inversedBy] (validation enforced)
    Field name on the referenced type, if it is a collection and is the owner.
  • Owns Relationship [ownsRelationship] (validation enforced)
    Whether this model owns the relationships, if is collection
  • Validation [validation]
    Validation object, a list of validation attributes with boolean values or condition sets. Examples:
    { "required" : true }
    { "required" : false }
    Example of conditional validation: Only require resolved if status equals Resolved, only
      {
          "required": [
              {
                  "logic": "AND",
                  "result": true,
                  "filters": [
                      {
                          "field": "status",
                          "operator": "eq",
                          "value": "/api/3/picklists/97e9bc03-5a4c-43c6-b3a3-47422b42d288"
                      }
                  ]
              }
          ]
      }
    
  • Visibility [visibility
    Determines if this attribute should be visible during data entry.
    This can be the following:
    true, the default, will always be shown.
    false, will not show up in the application.
    Query object, see above, will be visible if the condition matches.
  • Readable [readable]
    Determines if this attribute should be returned during READ operations.
  • Writeable [writeable]
    Determines if this attribute should be modified during UPDATE operations.
  • Identifier [identifier]
    Determines if this attribute is a unique identifier for this class.
  • Unique [unique]
    Determines if the attribute is unique.
  • Display Name [displayName]
    Display name as a template using field names, example:
    {
        "displayName" : "{{ sourceId }}"
    }
    
  • Descriptions [descriptions]
    Map of description type => description, example:
      {
          "singular" : "Source ID"
      }
    

Examples

For the following examples, we will use alerts.

Viewing Model Metadata

To view a model, use GET on /api/3/model_metadatas/7ab10952-b2ea-4910-9762-eb685bdd29eb. You should receive a result like this:

{
  "@context": "/api/3/contexts/ModelMetadata",
  "@id": "/api/3/model_metadatas/7ab10952-b2ea-4910-9762-eb685bdd29eb",
  "@type": "ModelMetadata",
  "parentType": "/api/3/model_metadatas/base_entities",
  "tableName": "alerts",
  "ownable": true,
  "trackable": true,
  "indexable": true,
  "displayName": "{{ name }}",
  "descriptions": {
    "singular": "Alert",
    "plural": "Alerts"
  }
}
Model Attributes

All models will have attributes to describe the fields on the json. These can be retrieved by using:

GET /api/3/model_metadatas/<uuid>?$relationships=true

{
    "@id": "/api/3/model_metadatas/08854338-6440-4b66-a07f-9788086fa088",
    "@type": "ModelMetadata",
    "attributes": [
        {
            "@id": "/api/3/attrib_model_metadata/8582cab2-ed5a-4daa-abaa-0277cba104e9",
            "@type": "AttribModelMetadata",
            "sattrib": "/api/3/model_metadatas/08854338-6440-4b66-a07f-9788086fa088",
            "type": "string",
            "name": "firstname",
            "length": 255,
            "formType": "text",
            "dataSource": [],
            "searchable": true,
            "system": true,
            "encrypted": false,
            "gridColumn": true,
            "collection": false,
            "inversedField": null,
            "ownsRelationship": false,
            "validation": {
                "required": true,
                "minlength": 0,
                "maxlength": 255
            },
            "bulkAction": {
                "allow": false
            },
            "defaultValue": "",
            "dataSourceFilters": [],
            "tooltip": "",
            "visibility": true,
            "readable": true,
            "writeable": true,
            "identifier": false,
            "unique": false,
            "peerReplicable": true,
            "displayName": "{{ firstname }}",
            "descriptions": {
                "singular": "First Name"
            }
        }
    ],
    "type": "people",
    "parentType": "actors",
    "tableName": "actors",
    "ownable": false,
    "trackable": true,
    "peerReplicable": false,
    "defaultSort": [
        {
            "field": "firstname",
            "direction": "ASC"
        },
        {
            "field": "lastname",
            "direction": "ASC"
        }
    ],
    "indexable": true,
    "writable": true,
    "displayName": "{{ firstname }} {{ lastname }}",
    "descriptions": {
        "singular": "Person",
        "plural": "People"
    }
}

Exporting a Model

To export a model, use GET on /api/3/model_metadatas/<uuid>?$relationships=true&$export=true. You should receive a result like this:

{
  "@type": "ModelMetadata",
  "uuid": "7ab10952-b2ea-4910-9762-eb685bdd29eb",
  "type": "alerts",
  "tableName": "alerts",
  "attributes": [
    {
      "@type": "AttributeMetadata",
      "uuid": "16c855d3-29b4-4d29-90a8-8f322b556067",
      "name": "name",
      "length": 255,
      "searchable": true,
      "gridColumn": true,
      "validation": {
        "required": true
      },
      "displayName": "{{ name }}",
      "descriptions": {
        "singular": "Name"
      }
    },
    ...
  ]
}

Updating Model Metadata

To update a model, first, you should GET the model you would like to update. Then, use PUT with the fields you want to change:

PUT /api/3/model_metadatas/7ab10952-b2ea-4910-9762-eb685bdd29eb

{
	"ownable": true
}

To update attributes on a model, first, you should GET the model. Then use PUT on the attributes field with the modifications. You need to post all the attributes as a whole.

PUT /api/3/model_metadatas/7ab10952-b2ea-4910-9762-eb685bdd29eb

{
  "attributes": [
    {
      /* Existing with @id */
    },
    {
      /* New without @id */
    }
  ]
}

You can update an attribute. For example, going to /api/3/attribute_metadatas/56d50d6a5a4ef3f3348b4574 will return a single metadata.

Creating New Models

To create a new model, use the same syntax as you have used for updating the models; except use POST and specify a type and parentType.

POST /api/3/model_metadatas

{
	"type": "malware",
    "parentType": "/api/3/model_metadatas/base_entities",
    "descriptions": {
        "singular": "Malware",
        "plural": "Malware"
    },
    "tableName": "malware"
}

The plural description will be used as the Module description. TableName is required for Postgres implementations of this model.

View Template

Create List View

POST /api/3/system_view_templates

{
	"id": "modules/malwares-list",
	"type": "rows",
	"config": {
		"rows": [{
			"columns": [{
				"widgets": [{
					"type": "grid",
					"config": []
				}]
			}]
		}]
	}
}

Create Detail View

POST /api/3/system_view_templates

{
	"id": "modules/malwares/detail",
	"type": "rows",
	"config": {
		"rows": [{
			"columns": [{
				"widgets": [{
					"type": "form",
					"config": []
				}]
			}]
		}, {
			"columns": [{
				"widgets": [{
					"type": "relationship.subtab",
					"config": []
				}]
			}]
		}]
	}
}

Extended Data

The attribute types that are type: object or array are often referred to as: 'Extended Data'. These are schema-less json blobs that have minimal input validation.

Attribute metadata for these types will look like this:

[
    {
        "@type": "AttributeMetadata",
        "uuid": "60e00773-2de6-44aa-8af0-174e4fbdec17",
        "name": "extendedData",
        "type": "object",
        "formType": "object",
        "displayName": "{{ extendedData }}",
        "descriptions": {
            "singular": "Extended Data"
        }
    },
    {
        "@type": "AttributeMetadata",
        "uuid": "338040a1-6965-4e56-b71d-80cc83ecbeb7",
        "name": "extendedDatas",
        "type": "array",
        "formType": "array",
        "displayName": "{{ extendedDatas }}",
        "descriptions": {
            "singular": "Extended Data (Array)"
        }
    }
]

Examples of Valid Data

{
    "extendedData": {
        "test": 1234,
        "key2": [
            "randomdata"
        ]
    }
}
{
    "extendedDatas": [
        1234,
        {
            "nested": "object"
        }
    ]
}

Examples of Bad Data

{
    "extendedData": [
        "array",
        "on object",
        "is bad"
    ]
}
{
    "extendedDatas": {
        "do not": "post object to array"
    }
}

Indexing of Extended Data

Because of the limitations on ElasticSearch, extended data needs to be transformed into a string before it is indexed. Searches performed on this data will act like a traditional text search.

System Update

After making changes to the metadata, it is time to publish. If you have the UPDATE permission to the Application module, make a PUT command to /api/publish. You will get a response like this:

{
    "@type": "Publish",
    "status": "started"
}

This will indicate that a system update has begun. This will make every request to the API return a 503 until the publish is complete. The progress will look something like this:

{
  "@type": "SystemUpdate",
  "code": 503,
  "message": "Clearing cache",
  "progressPercent": 22,
  "startTime": 1460678007
}

Modules List

  • Route: modules/{{ module }}
  • Template: modules/{{ module }}/list
  • State: main.modules.list
  • Parameters:
    • module: name of module

Model-dependent page that will be able to utilize the state parameters to build widgets.

Simple Example

{
  "id": "modules/incidents/list",
  "type": "rows",
  "config": {
    "rows": [{
      "columns": [{
        "widgets": [{
          "type": "grid"
        }]
      }]
    }]
  }
}

Modules Detail

  • Route: modules/{{ module }}/{{ id }}
  • Template: modules/{{ module }}/detail
  • State: main.modulesDetail
  • Parameters:
    • module: name of the module
    • id: id of the given record

Model-dependent page that will be able to utilize the state parameters to build widgets.

Simple Example

{
  "id": "modules/incidents/detail",
  "type": "rows",
  "config": {
    "rows": [{
      "columns": [{
        "widgets": [{
          "type": "form"
        }]
      }]
    }, {
      "columns": [{
        "widgets": [{
          "type": "relationship.subtab",
          "config": []
        }]
      }]
    }]
  }
}

Modules Form

  • Route: modules/{{ module }}/add or modules/{{ module }}/edit/{{ id }}
  • Template: modules/{{ module }}/form
  • State: main.modulesAdd or main.modulesEdit
  • Parameters:
    • module: name of the module
    • id: id of the given record (on edit only)

Module edit and module add both use the form template to load in a template that both modes can share to display fields and a form to the user. Model-dependent page that will be able to utilize the state parameters to build widgets.

Example

{
  "id": "modules/incidents/form",
  "type": "form",
  "config": {
    "rows": [{
      "columns": [{
        "widgets": [{
          "config": {
            "rows": [{
              "columns": [{
                "fields": [
                  "name"
                ]
              }]
            }],
            "size": "large"
          },
          "type": "formGroup"
        }, {
          "config": {
            "rows": [{
              "columns": [{
                "fields": [
                  "description"
                ]
              }]
            }]
          },
          "type": "formGroup"
        }, {
          "config": {
            "rows": [{
              "columns": [{
                "fields": [
                  "phase",
                  "status"
                ]
              }]
            }],
            "title": "Summary"
          },
          "type": "formGroup"
        }, {
          "config": {
            "rows": [{
              "columns": [{
                "fields": [
                  "resolution"
                ]
              }]
            }],
            "title": "Resolved"
          },
          "type": "formGroup"
        }, {
          "config": {
            "rows": [{
              "columns": [{
                "fields": [
                  "confirmation",
                  "confidence",
                  "severity",
                  "category",
                  "source",
                  "originPoint",
                  "incidentLead"
                ]
              }]
            }],
            "title": "Details"
          },
          "type": "formGroup"
        }, {
          "config": {
            "rows": [{
              "columns": [{
                "fields": [
                  "dateOfIncident",
                  "discoveredOn",
                  "dwellTime",
                  "containmentTime",
                  "recoveryTime"
                ]
              }]
            }],
            "title": "Dates"
          },
          "type": "formGroup"
        }]
      }]
    }]
  }
}

Application

Template: app

The application template is a unique widget that is loaded when you login to exo. This template describes header and navigation details.

Simple Example

{
  "id": "app",
  "type": "app",
  "config": {
    "header": {
    },
    "navigation": [{
      "title": "Home",
      "icon": "fa fa-home",
      "require": [],
      "state": {
        "name": "main.dashboard",
        "parameters": []
      }
    }, {
      "title": "Vulnerability Management",
      "icon": "fa fa-bug",
      "items": [{
        "title": "Vulnerabilities",
        "require": {
          "module": "vulnerabilities",
          "action": "canRead"
        },
        "state": {
          "name": "main.modules.list",
          "parameters": {
            "module": "vulnerabilities"
          }
        }
      }, {
        "title": "Assets",
        "require": {
          "module": "assets",
          "action": "canRead"
        },
        "state": {
          "name": "main.modules.list",
          "parameters": {
            "module": "assets"
          }
        }
      }]
    }]
  }
}

Header

Header property is the collection of the header component details.

Navigation

Navigation property is an array of links to build the left-hand navigation bar.

Links

A single link can be created like below.

{
  "title": "Home", // Title of the page
  "icon": "fa fa-home", // Icon used for the link
  "require": {  // Restriction of the link. or collection of links
    "module": "vulnerabilities", // What module to restrict on
    "action": "canRead" // Restrited action (defaults to canRead).
  },
  "state": { // State and it's parameters
    "name": "main.dashboard",
    "parameters": []
  }
}

A collection of links will look like the following:

{
  "title": "Vulnerability Management", // Title of collection
  "icon": "fa fa-bug", // Icon used for the collection
  "items": [{ // array of links (same as single link)
    "title": "Vulnerabilities",
    "require": {
      "module": "vulnerabilities",
      "action": "canRead"
    },
    "state": {
      "name": "main.modules.list",
      "parameters": {
        "module": "vulnerabilities"
      }
    }
  }, {
    "title": "Assets",
    "require": {
      "module": "assets",
      "action": "canRead"
    },
    "state": {
      "name": "main.modules.list",
      "parameters": {
        "module": "assets"
      }
    }
  }]
}

API Endpoints Reference

This gives a summary of the API endpoints available within FortiSOAR organized via category.

Category Description
Modules General access for CRUD operations on records within the Modules defined in the system database
Playbooks Access to both Playbook models, Step types (core system), Steps, and Custom Endpoints (Custom API Endpoint Triggers)
Configuration General management of the configuration of the system, including Users / Appliances (actors), View Templates, and Module / Model definitions

Query Parameters

Most endpoints allow for query parameters to be appended to the URL for scoping the specific data set being returned. Parameters are used to filter results from the query and change the result format.

Syntax

  1. The beginning of the query string is denoted by a ? appended to the end of a valid endpoint URL.
  2. Operational parameter values should start with a $.
  3. Filter values should not have a $.
  4. Parameters specify the specific value using =.
  5. Parameters are chained using the & character.

Sample URL

https://FortiSOAR.ROOT.URL/api/3/{collection}/{uuid}?parameter1=value&parameter2=value

Operations

The standard query parameters are given in the following table.

Parameter Valid Values Action
$relationships true, yes, false (default) Show or hide full field and value context for related records
$export true, yes, false (default) Display record in exportable/importable JSON format, e.g., "@id" is turned from an IRI to a simple "uuid" value
{fieldName} Any valid format for field type with url-encoded for special characters Filter results by fieldName using the equivalence operator. A fieldName can contain double underscores to specify a key within an object. For example, status__itemValue or assignedToPerson__firstname.
{fieldName}${operator} Any valid format for field type with url-encoded for special characters Filter results by fieldName using any operator. Operators that are supported are found in the Query API Reference chapter. A fieldName can contain double underscores to specify a key within an object.
$orderby Any valid {fieldName}, optional -{fieldName} operand Sort the returned data set by the values in a specific field, may be chained and accepts -value for inverse ordering
$limit An integer between 1 and 214748364 Maximum number of records to return in a query (default is 30)

Examples

/api/3/alerts?name=Full Alert Name
/api/3/alerts?name$like=%partial name%
/api/3/alerts?eventCount$gte=10&eventCount$lt=20
/api/3/alerts?status__itemValue=Open
/api/3/tasks?assignedToPerson__firstname$like=%doe%
/api/3/alerts?status__itemValue$in=Open |Resolved|In Progress
/api/3/alerts?$limit=100&$orderby=-createDate&$relationships=true

Module Endpoints

Module endpoints are grouped here by the Component to which they belong. At the root of the API, the models are not organized by Component. The component definition only exists within the system view metadata for defining the navigation.

Note

An important concept to grasp is that the Modules within the UI generally refer to a 1:1 relationship with a table. Beyond the UI, many of the Modules in the Role Editor are actually composed of multiple data models within the API. This section refers to the Modules that have a 1:1 data model relationship.

There are 3 optional endpoint formats defined within all modules. Each of these endpoints supports a specific set of standard operations.

Module Root

/api/3/{plural_module_name}

The Module Root displays a paginated listing of all records within that module. The default sorting is by last modified date.

/api/3/{plural_module_name}?{$filter_query}

The Module Root may be filtered to a specific set of criteria as opposed to generally listing all models within the database.

Supported Operations

All Module Root endpoints support the following operations.

Operation Description Formats
GET Allows you to read the list of records -
POST Insert a new record of the specified module type JSON
PUT Update an existing record, requires "@id" JSON
DELETE Delete an existing record, requires, requires "@id" -

Module Records

/api/3/{plural_module_name}/{record_uuid}

Supported Operations

All Module Record endpoints support the following operations.

Operation Description Formats
GET Allows you to read the list of records -

Playbook Endpoints

Custom Endpoints (Custom API Endpoint Trigger)

Endpoints Available

https://FortiSOAR.ROOT.URL/api/triggers/1/{name}
OR
https://FortiSOAR.ROOT.URL/api/triggers/1/deferred/{name}

These are user-defined endpoints generated based on the specified arbitrary name included in the Playbook trigger.

Custom API Endpoint Trigger

The deferred endpoints allow for alternate authentication means, i.e., no HMAC (token) requirement, for external systems that may only offer Basic or non-authenticated webhooks (No Authentication).

Configuration Endpoints

The Configuration endpoints primarily govern system and user interaction. Generally, it should not be necessary to use these endpoints outside of the UI, but they are provided here as a reference.

Model Metadatas

Caution

Modifications to the Model Metadatas and Attributes are not recommended due to the potential for database manipulation leading to a potentially difficult recovery..

Model Metadata describes every piece of customizable data models in our system. We have two pieces of metadata: Model and Attribute. Models are comprised of any number of Attributes. Attributes can be of any type, ranging from any JSON primitive type to relationships with existing entities. These relationships can be of type 'toMany' or 'toOne'.

ModelMetadata: /api/3/apidoc/ModelMetadata

  • Type [type]
    Metadata type, JSON primitive for attributes or internal types for models. See type for AttributeMetadata for valid JSON primitives.
  • Parent Type [parentType]
    The type of the parent, if set to null, will default to the BaseEntity class.
  • Table Name [tableName]
    The table name for ORM, this will be the table that is created in the database.
  • Ownable [ownable]
    Determines if this class should have the ownable fields, user ownable and team ownable.
  • Trackable [trackable]
    Determines if this module should have the trackable fields (createDate, createUser, modifyDate, modifyUser)
  • Indexable [indexable]
    Determines if this class should have the indexable fields (id). This gives the object a global sequence id field.
  • Attributes [attributes]
    Key-value list of the attributes for this class. These attributes can be described here: /api/3/apidoc/AttributeMetadata
  • Display Template [displayTemplate]
    Template for the display name of record as an AngularJS template.
  • Descriptions [descriptions]
    Map of description type => description, example:
      {
          "singular" : "Alert",
          "plural" : "Alerts"
      }
    

AttributeMetadata: /api/3/apidoc/AttributeMetadata

  • Id [id]
    The unique object id for this attribute, will be auto generated if not specified.
  • Type [type]
    Metadata type, JSON primitive for attributes or iri/internal types for models. Supported primitives are:
    integer,
    string,
    id,
    boolean,
    number,
    null
    object,
    array
    Note: Adding an array field type is currently not supported through the FortiSOAR UI.
    object and array are special types. See the Extended Data section below.
    Tip: null is supported in theory but might not make sense to use.
  • Name [name] (required, unique) The name of the attribute.
    Note: DO NOT use underscores in the field name. Must be Camel-Case.
  • Length [length]
    The length of the attribute. For anything less than 255, it will created in the SQL database as a VARCHAR with a defined length.
  • FormType [formType]
    The type of form to use to render this attribute. Supported types are:
    integer,
    text,
    textarea,
    checkbox,
    manyToMany,
    datetime,
    picklist,
    lookup,
    oneToMany,
    file,
    manyToOne,
    richtext,
    phone,
    email,
    json
  • Data Source [dataSource]
    The source of the data, not defined explicitly. An example of picklist lookups:
      {
          "module" : "picklists",
          "query": {
              "logic": "AND",
              "filters": [
                  {
                    "field": "listName__name",
                    "operator": "eq",
                    "value": "Criticality"
                  }
              ],
              "sort": [
                  {
                    "field": "orderIndex",
                    "direction": "ASC"
                  }
              ]
          }
      }
    
    An example of a relationship for all items in a collection, query is null because no query should be made to limit the lookup:
      {
          "module" : "alerts",
          "query" : null
      }
    
  • Searchable [searchable]
    Determines if this attribute should be searchable within a grid in the FortiSOAR UI. This does not affect record indexing in ElasticSearch. The field will yet be displayed in the global search results in the UI even if it is not marked as searchable.
  • Grid Column [gridColumn]
    Determines if this attribute should show up in a grid by default.
  • Mapped By [mappedBy]
    Field name on the referenced type, if it is a collection and not the owner of a relationship.
  • Inversed By [inversedBy] (validation enforced)
    Field name on the referenced type, if it is a collection and is the owner.
  • Owns Relationship [ownsRelationship] (validation enforced)
    Whether this model owns the relationships, if is collection
  • Validation [validation]
    Validation object, a list of validation attributes with boolean values or condition sets. Examples:
    { "required" : true }
    { "required" : false }
    Example of conditional validation: Only require resolved if status equals Resolved, only
      {
          "required": [
              {
                  "logic": "AND",
                  "result": true,
                  "filters": [
                      {
                          "field": "status",
                          "operator": "eq",
                          "value": "/api/3/picklists/97e9bc03-5a4c-43c6-b3a3-47422b42d288"
                      }
                  ]
              }
          ]
      }
    
  • Visibility [visibility
    Determines if this attribute should be visible during data entry.
    This can be the following:
    true, the default, will always be shown.
    false, will not show up in the application.
    Query object, see above, will be visible if the condition matches.
  • Readable [readable]
    Determines if this attribute should be returned during READ operations.
  • Writeable [writeable]
    Determines if this attribute should be modified during UPDATE operations.
  • Identifier [identifier]
    Determines if this attribute is a unique identifier for this class.
  • Unique [unique]
    Determines if the attribute is unique.
  • Display Name [displayName]
    Display name as a template using field names, example:
    {
        "displayName" : "{{ sourceId }}"
    }
    
  • Descriptions [descriptions]
    Map of description type => description, example:
      {
          "singular" : "Source ID"
      }
    

Examples

For the following examples, we will use alerts.

Viewing Model Metadata

To view a model, use GET on /api/3/model_metadatas/7ab10952-b2ea-4910-9762-eb685bdd29eb. You should receive a result like this:

{
  "@context": "/api/3/contexts/ModelMetadata",
  "@id": "/api/3/model_metadatas/7ab10952-b2ea-4910-9762-eb685bdd29eb",
  "@type": "ModelMetadata",
  "parentType": "/api/3/model_metadatas/base_entities",
  "tableName": "alerts",
  "ownable": true,
  "trackable": true,
  "indexable": true,
  "displayName": "{{ name }}",
  "descriptions": {
    "singular": "Alert",
    "plural": "Alerts"
  }
}
Model Attributes

All models will have attributes to describe the fields on the json. These can be retrieved by using:

GET /api/3/model_metadatas/<uuid>?$relationships=true

{
    "@id": "/api/3/model_metadatas/08854338-6440-4b66-a07f-9788086fa088",
    "@type": "ModelMetadata",
    "attributes": [
        {
            "@id": "/api/3/attrib_model_metadata/8582cab2-ed5a-4daa-abaa-0277cba104e9",
            "@type": "AttribModelMetadata",
            "sattrib": "/api/3/model_metadatas/08854338-6440-4b66-a07f-9788086fa088",
            "type": "string",
            "name": "firstname",
            "length": 255,
            "formType": "text",
            "dataSource": [],
            "searchable": true,
            "system": true,
            "encrypted": false,
            "gridColumn": true,
            "collection": false,
            "inversedField": null,
            "ownsRelationship": false,
            "validation": {
                "required": true,
                "minlength": 0,
                "maxlength": 255
            },
            "bulkAction": {
                "allow": false
            },
            "defaultValue": "",
            "dataSourceFilters": [],
            "tooltip": "",
            "visibility": true,
            "readable": true,
            "writeable": true,
            "identifier": false,
            "unique": false,
            "peerReplicable": true,
            "displayName": "{{ firstname }}",
            "descriptions": {
                "singular": "First Name"
            }
        }
    ],
    "type": "people",
    "parentType": "actors",
    "tableName": "actors",
    "ownable": false,
    "trackable": true,
    "peerReplicable": false,
    "defaultSort": [
        {
            "field": "firstname",
            "direction": "ASC"
        },
        {
            "field": "lastname",
            "direction": "ASC"
        }
    ],
    "indexable": true,
    "writable": true,
    "displayName": "{{ firstname }} {{ lastname }}",
    "descriptions": {
        "singular": "Person",
        "plural": "People"
    }
}

Exporting a Model

To export a model, use GET on /api/3/model_metadatas/<uuid>?$relationships=true&$export=true. You should receive a result like this:

{
  "@type": "ModelMetadata",
  "uuid": "7ab10952-b2ea-4910-9762-eb685bdd29eb",
  "type": "alerts",
  "tableName": "alerts",
  "attributes": [
    {
      "@type": "AttributeMetadata",
      "uuid": "16c855d3-29b4-4d29-90a8-8f322b556067",
      "name": "name",
      "length": 255,
      "searchable": true,
      "gridColumn": true,
      "validation": {
        "required": true
      },
      "displayName": "{{ name }}",
      "descriptions": {
        "singular": "Name"
      }
    },
    ...
  ]
}

Updating Model Metadata

To update a model, first, you should GET the model you would like to update. Then, use PUT with the fields you want to change:

PUT /api/3/model_metadatas/7ab10952-b2ea-4910-9762-eb685bdd29eb

{
	"ownable": true
}

To update attributes on a model, first, you should GET the model. Then use PUT on the attributes field with the modifications. You need to post all the attributes as a whole.

PUT /api/3/model_metadatas/7ab10952-b2ea-4910-9762-eb685bdd29eb

{
  "attributes": [
    {
      /* Existing with @id */
    },
    {
      /* New without @id */
    }
  ]
}

You can update an attribute. For example, going to /api/3/attribute_metadatas/56d50d6a5a4ef3f3348b4574 will return a single metadata.

Creating New Models

To create a new model, use the same syntax as you have used for updating the models; except use POST and specify a type and parentType.

POST /api/3/model_metadatas

{
	"type": "malware",
    "parentType": "/api/3/model_metadatas/base_entities",
    "descriptions": {
        "singular": "Malware",
        "plural": "Malware"
    },
    "tableName": "malware"
}

The plural description will be used as the Module description. TableName is required for Postgres implementations of this model.

View Template

Create List View

POST /api/3/system_view_templates

{
	"id": "modules/malwares-list",
	"type": "rows",
	"config": {
		"rows": [{
			"columns": [{
				"widgets": [{
					"type": "grid",
					"config": []
				}]
			}]
		}]
	}
}

Create Detail View

POST /api/3/system_view_templates

{
	"id": "modules/malwares/detail",
	"type": "rows",
	"config": {
		"rows": [{
			"columns": [{
				"widgets": [{
					"type": "form",
					"config": []
				}]
			}]
		}, {
			"columns": [{
				"widgets": [{
					"type": "relationship.subtab",
					"config": []
				}]
			}]
		}]
	}
}

Extended Data

The attribute types that are type: object or array are often referred to as: 'Extended Data'. These are schema-less json blobs that have minimal input validation.

Attribute metadata for these types will look like this:

[
    {
        "@type": "AttributeMetadata",
        "uuid": "60e00773-2de6-44aa-8af0-174e4fbdec17",
        "name": "extendedData",
        "type": "object",
        "formType": "object",
        "displayName": "{{ extendedData }}",
        "descriptions": {
            "singular": "Extended Data"
        }
    },
    {
        "@type": "AttributeMetadata",
        "uuid": "338040a1-6965-4e56-b71d-80cc83ecbeb7",
        "name": "extendedDatas",
        "type": "array",
        "formType": "array",
        "displayName": "{{ extendedDatas }}",
        "descriptions": {
            "singular": "Extended Data (Array)"
        }
    }
]

Examples of Valid Data

{
    "extendedData": {
        "test": 1234,
        "key2": [
            "randomdata"
        ]
    }
}
{
    "extendedDatas": [
        1234,
        {
            "nested": "object"
        }
    ]
}

Examples of Bad Data

{
    "extendedData": [
        "array",
        "on object",
        "is bad"
    ]
}
{
    "extendedDatas": {
        "do not": "post object to array"
    }
}

Indexing of Extended Data

Because of the limitations on ElasticSearch, extended data needs to be transformed into a string before it is indexed. Searches performed on this data will act like a traditional text search.

System Update

After making changes to the metadata, it is time to publish. If you have the UPDATE permission to the Application module, make a PUT command to /api/publish. You will get a response like this:

{
    "@type": "Publish",
    "status": "started"
}

This will indicate that a system update has begun. This will make every request to the API return a 503 until the publish is complete. The progress will look something like this:

{
  "@type": "SystemUpdate",
  "code": 503,
  "message": "Clearing cache",
  "progressPercent": 22,
  "startTime": 1460678007
}

Modules List

  • Route: modules/{{ module }}
  • Template: modules/{{ module }}/list
  • State: main.modules.list
  • Parameters:
    • module: name of module

Model-dependent page that will be able to utilize the state parameters to build widgets.

Simple Example

{
  "id": "modules/incidents/list",
  "type": "rows",
  "config": {
    "rows": [{
      "columns": [{
        "widgets": [{
          "type": "grid"
        }]
      }]
    }]
  }
}

Modules Detail

  • Route: modules/{{ module }}/{{ id }}
  • Template: modules/{{ module }}/detail
  • State: main.modulesDetail
  • Parameters:
    • module: name of the module
    • id: id of the given record

Model-dependent page that will be able to utilize the state parameters to build widgets.

Simple Example

{
  "id": "modules/incidents/detail",
  "type": "rows",
  "config": {
    "rows": [{
      "columns": [{
        "widgets": [{
          "type": "form"
        }]
      }]
    }, {
      "columns": [{
        "widgets": [{
          "type": "relationship.subtab",
          "config": []
        }]
      }]
    }]
  }
}

Modules Form

  • Route: modules/{{ module }}/add or modules/{{ module }}/edit/{{ id }}
  • Template: modules/{{ module }}/form
  • State: main.modulesAdd or main.modulesEdit
  • Parameters:
    • module: name of the module
    • id: id of the given record (on edit only)

Module edit and module add both use the form template to load in a template that both modes can share to display fields and a form to the user. Model-dependent page that will be able to utilize the state parameters to build widgets.

Example

{
  "id": "modules/incidents/form",
  "type": "form",
  "config": {
    "rows": [{
      "columns": [{
        "widgets": [{
          "config": {
            "rows": [{
              "columns": [{
                "fields": [
                  "name"
                ]
              }]
            }],
            "size": "large"
          },
          "type": "formGroup"
        }, {
          "config": {
            "rows": [{
              "columns": [{
                "fields": [
                  "description"
                ]
              }]
            }]
          },
          "type": "formGroup"
        }, {
          "config": {
            "rows": [{
              "columns": [{
                "fields": [
                  "phase",
                  "status"
                ]
              }]
            }],
            "title": "Summary"
          },
          "type": "formGroup"
        }, {
          "config": {
            "rows": [{
              "columns": [{
                "fields": [
                  "resolution"
                ]
              }]
            }],
            "title": "Resolved"
          },
          "type": "formGroup"
        }, {
          "config": {
            "rows": [{
              "columns": [{
                "fields": [
                  "confirmation",
                  "confidence",
                  "severity",
                  "category",
                  "source",
                  "originPoint",
                  "incidentLead"
                ]
              }]
            }],
            "title": "Details"
          },
          "type": "formGroup"
        }, {
          "config": {
            "rows": [{
              "columns": [{
                "fields": [
                  "dateOfIncident",
                  "discoveredOn",
                  "dwellTime",
                  "containmentTime",
                  "recoveryTime"
                ]
              }]
            }],
            "title": "Dates"
          },
          "type": "formGroup"
        }]
      }]
    }]
  }
}

Application

Template: app

The application template is a unique widget that is loaded when you login to exo. This template describes header and navigation details.

Simple Example

{
  "id": "app",
  "type": "app",
  "config": {
    "header": {
    },
    "navigation": [{
      "title": "Home",
      "icon": "fa fa-home",
      "require": [],
      "state": {
        "name": "main.dashboard",
        "parameters": []
      }
    }, {
      "title": "Vulnerability Management",
      "icon": "fa fa-bug",
      "items": [{
        "title": "Vulnerabilities",
        "require": {
          "module": "vulnerabilities",
          "action": "canRead"
        },
        "state": {
          "name": "main.modules.list",
          "parameters": {
            "module": "vulnerabilities"
          }
        }
      }, {
        "title": "Assets",
        "require": {
          "module": "assets",
          "action": "canRead"
        },
        "state": {
          "name": "main.modules.list",
          "parameters": {
            "module": "assets"
          }
        }
      }]
    }]
  }
}

Header

Header property is the collection of the header component details.

Navigation

Navigation property is an array of links to build the left-hand navigation bar.

Links

A single link can be created like below.

{
  "title": "Home", // Title of the page
  "icon": "fa fa-home", // Icon used for the link
  "require": {  // Restriction of the link. or collection of links
    "module": "vulnerabilities", // What module to restrict on
    "action": "canRead" // Restrited action (defaults to canRead).
  },
  "state": { // State and it's parameters
    "name": "main.dashboard",
    "parameters": []
  }
}

A collection of links will look like the following:

{
  "title": "Vulnerability Management", // Title of collection
  "icon": "fa fa-bug", // Icon used for the collection
  "items": [{ // array of links (same as single link)
    "title": "Vulnerabilities",
    "require": {
      "module": "vulnerabilities",
      "action": "canRead"
    },
    "state": {
      "name": "main.modules.list",
      "parameters": {
        "module": "vulnerabilities"
      }
    }
  }, {
    "title": "Assets",
    "require": {
      "module": "assets",
      "action": "canRead"
    },
    "state": {
      "name": "main.modules.list",
      "parameters": {
        "module": "assets"
      }
    }
  }]
}