Tips for creating Generic API queries for dashboard charts

Tips to help you create Generic API queries and dashboard charts more easily cover data requirements for specific chart types, results mapping for when the returned JSON is not an array, and dynamic titles.

Data format

The APIs that are called must return data in a specific JSON format for the dashboard to be able to read the data. APIs return either a JSON array (when there are multiple results) or a JSON object (when there is only one result). Returned JSON objects are converted into a JSON array containing one element.

Most IBM® QRadar® APIs return data in a format that the dashboard can process. Other APIs, such as app APIs, might require you to use the dashboard results mapping to extract a specific key of the returned JSON object.

Data requirements for tabular charts

For tabular charts, APIs must return either a JSON object (when there is only one result) or a JSON array of elements representing tabular data. For example:

[{
      "rowstring": "Thanksgiving eCard Emails Distributing Malware",
      "category": "Threat Activity",
      "relevance": "25%",
      "href": "/app/href"
    }, {
      "title": "PyXie - RAT Written In Python",
      "category": "Threat Activity",
      "relevance": "25%",
      "href": "/app/href"
    }, ...

Data requirements for pie charts and single-series bar charts

For pie charts and single-series bar charts, APIs must return either a JSON object (when there is only one result) or a JSON array that contains at least one label and one numeric metric. For example:
[{
    "Country": "Europe",
    "Count": 97
  }, {
    "Country": "Middle East",
    "Count": 85
  }, {
    "Country": "North America",
    "Count": 83
  }, ...

Data requirements for time series charts

For time series charts, APIs must return either a JSON object (when there is only one result) or a JSON array that contains at least one time-based metric using a valid date or milliseconds format, and one or many numeric metrics to plot on the Y-axis. The data must be ordered by time. For example:

[{
    "date": "2020-02-18",
    "Phishing": 7.21,
    "C2": 82.67,
    "Malware": 272.05,
    "EarlyWarning": 448.32
  }, {
    "date": "2020-02-19",
    "Phishing": 7.47,
    "C2": 94.14,
    "Malware": 121.84,
    "EarlyWarning": 665.33
  }, {
    "date": "2020-02-20",
    "Phishing": 8.05,
    "C2": 92.35,
    "Malware": 120.71,
    "EarlyWarning": 736.9
  }, ...

Data requirements for scatter geographic charts

Scatter geographic charts require a stringified JSON object (that is, an object that is converted by using the JSON.stringify() JavaScript function) containing a geo_json key with coordinates, and one numeric metric. For example:

[{
    "sourceIP": "81.12.213.121",
    "geoSource": "{\"geo_json\":{\"coordinates\":[44.4354,26.1033],\"type\":\"Point\"}}",
    "geoDest": "{\"geo_json\":{\"coordinates\":[1.0,38.0],\"type\":\"Point\"}}",
    "eventCount": 50
  }, {
    "sourceIP": "59.154.60.0",
    "geoSource": "{\"geo_json\":{\"coordinates\":[-33.494,143.2104],\"type\":\"Point\"}}",
    "geoDest": "{\"geo_json\":{\"coordinates\":[53.3472,-6.2439],\"type\":\"Point\"}}",
    "eventCount": 60
  }, { ...

Data requirements for choropleth geographic charts

Choropleth geographic charts require a stringified JSON object (that is, an object that is converted by using the JSON.stringify() JavaScript function) containing a country key with either the country/region name or the ISO-3 code of the country/region, and one numeric metric. For example:

[{
    "sourceIP": "81.12.213.121",
    "geoCountry": "{\"country\":{\"confidence\":null,\"name\":\"Romania\",\"iso_code\":\"ROU\",\"geo_id\":798549}}",
    "eventCount": 50
  }, {
    "sourceIP": "59.154.60.0",
    "geoCountry": "{\"country\":{\"confidence\":null,\"name\":\"Australia\",\"iso_code\":\"AUS\",\"geo_id\":2077456}}",
    "eventCount": 60
  }, { ...

Results mapping

If the root object in the returned JSON is not the array you want to plot, use the Results mapping field to define which key contains the relevant data you want to plot.

The results mapping uses the JSON dot (.) operator to traverse the document, starting from the root node. For example, in the following JSON object, the relevant data is under the items key, which is under the table root node. A table.items mapping is required for the dashboard to read the items array and ignore all other keys:

{
  "table": {
    "title": "Top 5 most relevant threats",
    "columns": [{
      "title": "Threat",
      "key": "title",
      "subkey": "category",
      "width": 75
    }, {
      "title": "X-Force Threat Score",
      "key": "relevance",
      "width": 0
    }],
    "items": [{
      "title": "Thanksgiving eCard Emails Distributing Malware",
      "category": "Threat Activity",
      "relevance": "25%",
      "href": "/app/href"
    }, {
      "title": "PyXie - RAT Written In Python",
      "category": "Threat Activity",
      "relevance": "25%",
      "href": "/app/href"
    }, { ...

If the returned JSON object itself is an array, as is the case for most default QRadar APIs, no mapping is necessary. But with QRadar apps, the returned JSON might have a different format.

Dynamic title

You can override a view name by using a dynamic title that describes the current state of the data. For example, a chart is titled "World Malicious Activity: <threat_name>", where the threat name changes over time. Dynamic titles require a title key with the dynamic title name, as shown in the following example:

{
  "title": "Worldwide Malicious Activity: emotet",
  "items": [{
    "sourceIP": "81.12.213.121",
    "geoSource": "{\"geo_json\":{\"coordinates\":[44.4354,26.1033],\"type\":\"Point\"}}",
    "geoDest": "{\"geo_json\":{\"coordinates\":[1.0,38.0],\"type\":\"Point\"}}",
    "geoCountry": "{\"country\":{\"confidence\":null,\"name\":\"Romania\",\"iso_code\":\"ROU\",\"geo_id\":798549}}",
    "eventCount": 50
  }, { ...

If the title key is under the root node, use the Title mapping field. The title mapping uses the JSON dot (.) operator to traverse the document, starting from the root node. For example, if the title key is under a table root node, you would specify a table.title mapping.