---
title: Tines
---

runZero integrates with ((Tines)) to help you automate workflows related to your asset data. This helps teams leverage runZero to the fullest while optimizing the team's workflows with automation. A [video demo](https://loom.com/share/ff57a5828b584442936b20ed622d51fe) is available to show the final outcome of these instructions.

## Requirements {#tines-requirements}
* A Tines account
* runZero Export API and Organization API tokens

There are two ways to integrate runZero and Tines:
* Follow the steps to create a [custom story in Tines](#tines-custom-story), or
* Use the **[runZero sample story](#runzero-sample-story)** to begin with a story outline.

## Tines custom story

A Tines story is a collection of actions that work together towards a specific goal, like a playbook. Tines has a Story Library that contains ready-made automated playbooks, or you can create a your own custom story if they don't have one that matches your needs. That's what we'll need to do here. 

### Step 1: Creating a Tines story and adding runZero API credentials
1. After logging in to Tines, create a new story.
2. Use the `+` in the **credentials** section to add a [**text** credential](https://www.tines.com/docs/credentials/text). 
    * **Name**: specify a name for the credential, for example `runzero_export_token`.
    * **Value**: your [runZero export API token](leveraging-the-api.md), which can be obtained from the desired [runZero organization](https://console.runzero.com/organizations) page. Export API tokens start with `ET`.
3. Use the `+` in the **credentials** section to add another [**text** credential](https://www.tines.com/docs/credentials/text). 
    * **Name**: specify a name for the credential, for example `runzero_org_token`.
    * **Value**: your [runZero organization API token](leveraging-the-api.md), which can be obtained from the desired [runZero organization](https://console.runzero.com/organizations) page. Organization API tokens start with `OT`.

### Step 2: Creating a Tines webhook action 
1. Add a **[Webhook](https://www.tines.com/docs/actions/types/webhook)** action to your story.
2. Click the **Webhook** action and copy the webhook URL, which will look like `https://<tenant-name>.tines.com/webhook/<guid>`.

### Step 3: Creating a runZero alert template 
1. Create an [alert template](https://console.runzero.com/alerts/template/create/) in runZero:
    * **Name**: name for template
    * **Template type**: JSON
    * **Subject line for message**: leave empty 
    * **Body of message**: the following JSON example will include the rule name and the search URL in the alert message body: `{"rule_name":"{{rule.name}}","search_url":"{{search.url}}"}`
2. Create an [alert channel](https://console.runzero.com/alerts/channel/create/) in runZero:
    * **Name**: name for alert channel 
    * **Channel type**: webhook
    * **Webhook URL**: the webhook URL you copied from Tines

### Step 4: Creating a rule in runZero
Now that you have your template ready to go, you will want to identify which triggers to alert on. Some common examples are:

* **Asset query results** - When there is a match on a query in runZero after a scan completes
* **New assets found** - When a scan completes with new assets
* **Agent offline** - When your runZero Explorer stops checking in to the console
* **Task failed** - When a task fails for any reason

We will use the **asset query results** selection for the rest of the steps. Our example will be any asset that has an open Telnet port `port:23`. You can [see more example queries](search-query-examples.md).

1. Create an [alert rule](https://console.runzero.com/alerts/rule/create/).
2. Select `asset-query-results` and click _Configure rule_.
3. Input values for the rule:
    * **Name**: name of the rule.
    * **Conditions**: optional parameters that will trigger the alert when all conditions match.
      * **Query**: query the assets must match, such as `port:23` for our example.
      * **Number of matches**: the numeric comparison logic for the **value**.
      * **Value**: the threshold of matches to trigger the rule.
      * **Limit to organization**: allows you to limit the alert to a specific organization in runZero
      * **Limit to site**: allows you to limit the alert to a specific site in runZero 
      * **Action**: notify 
        * **Notification channel**: name of the alert channel you created in step 2.
        * **Notification template**: name of the alert template you created in step 2.

### Step 5: Handling the data in Tines 
1. The [**Webhook** action](https://www.tines.com/docs/actions/types/webhook) created in [Step 2](#step-2-creating-a-tines-webhook-action) will be the entry point for the runZero alert in Tines.
2. Add an [**Event Transform**](https://www.tines.com/docs/actions/types/event-transformation/extract) to parse the search from the URL provided in the runZero alert. If you connect the **Webhook** action to this one, some parameters will automatically populate.
    * Mode: extract 
    * Matchers:
      * Path: `path_to_alert_search`, for example `receive_alerts_from_runzero.body.search_url` if your **Webhook** action is named "RECEIVE alerts from runZero"
      * Regex: `\?.*`
      * Extract to: `search`
3. Add an [Event Transform](https://www.tines.com/docs/actions/types/event-transformation/explode) that takes the output of the previous step. If you connect the previous **Event Transform** action with this one, some parameters will automatically populate.
    * Mode: explode 
    * Matchers:
      * Path: `path_to_extraction_transform`, for example `get_search_from_url.search` if your previous **Event Transform** action is named "GET search from URL"
      * To: `individual_item`
4. Add an [HTTP Request](https://www.tines.com/docs/actions/types/http-request) to make an API call to the runZero Export API.
    * URL: the `path_to_explosion_transform` added to the end of the runZero API URL endpoint, for example `https://console.runZero.com/api/v1.0/export/org/assets.json<<get_search_from_regex.individual_item>>` if your previous **Event Transform** action is named "GET search from regex"
    * Content Type: JSON
    * Method: get
    * Use the **+ Option** button to add **Headers**: 
      * Change `header` to `Authorization` 
      * Change `value` to `Bearer CREDENTIAL.runzero_export_token`
5. Add an [Event Transform](https://www.tines.com/docs/actions/types/event-transformation/explode) that takes the runZero Export API output and loops through each value.
    * Mode: explode
    * Path: `path_to_HTTP_request`, for example `get_assets_from_runzero.body` if your **HTTP Request** action is named "GET assets from runZero"
    * To: `individual_item`

### Step 6: Personalized automation in Tines
Now that you have received the alert, parsed the search, and obtained the assets from the runZero Export API, it's time to add your own flare. While you will likely want to do something more crafty, the sample story provided includes these two actions as examples. 

1. [Send an email](https://www.tines.com/docs/actions/types/email) to the destination of your choice for each asset. The sample JSON shows how you might customize it to put the context you'd like in the Subject and Body of the email. 
2. The [HTTP Request](https://www.tines.com/docs/actions/types/http-request) action shows how you might reach back into runZero to add tags to the assets after other data is gathered. 

## runZero sample story
The [sample story below](#runzero-sample-story-json) can be imported to Tines to do all of the actions outlined in the steps above. Simply save a JSON file with the contents below, and use the **Import** button in Tines to upload it. After importing, you will need to complete the following steps. 

### Step 1: Update credentials in Tines
1. Replace the `runzero_export_token` credential:
    * **Name**: specify a name for the credential, such as `runzero_export_token` 
    * **Type**: text
    * **Value**: your [runZero export API token](leveraging-the-api.md), which can be obtained from the desired [runZero organization](https://console.runzero.com/organizations) page. Export API tokens start with `ET`.
2. Replace the `runzero_org_token` credential:
    * **Name**: specify a name for the credential, such as `runzero_org_token` 
    * **Type**: text
    * **Value**: your [runZero organization API token](leveraging-the-api.md), which can be obtained from the desired [runZero organization](https://console.runzero.com/organizations) page. Organization API tokens start with `OT`.

### Step 2: Create runZero alert template
1. Create an [alert template](https://console.runzero.com/alerts/template/create/) in runZero:
    * **Name**: name for template
    * **Template type**: JSON
    * **Subject line for message**: leave empty 
    * **Body of message**: the following JSON example will include the rule name and the search URL in the alert message body: `{"rule_name":"{{rule.name}}","search_url":"{{search.url}}"}`
2. Create an [alert channel](https://console.runzero.com/alerts/channel/create/) in runZero:
    * **Name**: name for alert channel 
    * **Channel type**: webhook
    * **Webhook URL**: the webhook URL you copied from Tines

### Step 3: Create the rule in runZero
Now that you have your template ready to go, you will want to identify which triggers to alert on. Some common examples are:

* Asset query results: when there is a match on a query in runZero after a scan completes.
* New assets found: when a scan completes with new assets.
* Agent offline: when your runZero Explorer stops checking in to the console.
* Task failed: when a task fails for any reason.

We will use the **asset query results** selection for the rest of the steps. Our example will be any asset that has an open Telnet port `port:23`. You can [see more example queries](search-query-examples.md).

1. Create a [new alert rule](https://console.runzero.com/alerts/rule/create/).
2. Select `asset-query-results` and click `Configure rule`.
3. Input values for the rule:
    * **Name**: name of the rule.
    * **Conditions**: optional parameters that will trigger the alert when all conditions match.
      * **Query**: query the assets must match, such as `port:23` for our example.
      * **Number of matches**: the numeric comparison logic for the **value**.
      * **Value**: the threshold of matches to trigger the rule.
      * **Limit to organization**: allows you to limit the alert to a specific organization in runZero
      * **Limit to site**: allows you to limit the alert to a specific site in runZero 
      * **Action**: notify 
        * **Notification channel**: name of the alert channel you created in step 2.
        * **Notification template**: name of the alert template you created in step 2.

### runZero sample story JSON

```json
{
  "schema_version": 4,
  "standard_lib_version": 6,
  "name": "runZero Sample Story",
  "description": null,
  "guid": "7706b502e51b4c68f0dbe9721c88d665",
  "slug": "runzero_sample_story",
  "exported_at": "2022-10-27T22:22:37Z",
  "agents": [
    {
      "type": "Agents::WebhookAgent",
      "name": "RECEIVE alerts from runZero",
      "disabled": false,
      "guid": "ab1f5bf7be49c943d893ab993ade9421",
      "options": {
        "path": "da6e90c0b276bdda97e6bfa31ad50787",
        "secret": "5e290305e0a483bf843f1213f0f21dda",
        "verbs": "get,post"
      },
      "reporting": {
        "time_saved_value": 0,
        "time_saved_unit": "minutes"
      },
      "monitoring": {
        "monitor_all_events": false,
        "monitor_failures": false,
        "monitor_no_events_emitted": null
      },
      "width": null
    },
    {
      "type": "Agents::HTTPRequestAgent",
      "name": "GET assets from runZero",
      "disabled": false,
      "guid": "d54d8f3f5b0ea857308f45f61a224547",
      "options": {
        "url": "https://console.runZero.com/api/v1.0/export/org/assets.json<<get_search_from_regex.individual_item>>",
        "content_type": "application_json",
        "method": "get",
        "headers": {
          "Authorization": "Bearer <<CREDENTIAL.runzero_export_token>>"
        }
      },
      "reporting": {
        "time_saved_value": 0,
        "time_saved_unit": "minutes"
      },
      "monitoring": {
        "monitor_all_events": false,
        "monitor_failures": false,
        "monitor_no_events_emitted": null
      },
      "width": null,
      "schedule": []
    },
    {
      "type": "Agents::EventTransformationAgent",
      "name": "GET search from URL",
      "disabled": false,
      "guid": "d62ddd189bb9080d778d900f2292504d",
      "options": {
        "mode": "extract",
        "matchers": [
          {
            "path": "=receive_alerts_from_runzero.body.search_url",
            "regexp": "\\?.*",
            "to": "search"
          }
        ]
      },
      "reporting": {
        "time_saved_value": 0,
        "time_saved_unit": "minutes"
      },
      "monitoring": {
        "monitor_all_events": false,
        "monitor_failures": false,
        "monitor_no_events_emitted": null
      },
      "width": null,
      "schedule": null
    },
    {
      "type": "Agents::EventTransformationAgent",
      "name": "GET search from regex",
      "disabled": false,
      "guid": "41afc5c4d4c0fdb694d14e1eb380688a",
      "options": {
        "mode": "explode",
        "path": "=get_search_from_url.search",
        "to": "individual_item"
      },
      "reporting": {
        "time_saved_value": 0,
        "time_saved_unit": "minutes"
      },
      "monitoring": {
        "monitor_all_events": false,
        "monitor_failures": false,
        "monitor_no_events_emitted": null
      },
      "width": null,
      "schedule": null
    },
    {
      "type": "Agents::EventTransformationAgent",
      "name": "LOOP through assets for follow up actions",
      "disabled": false,
      "guid": "b9ada61162bdf006f09d264845ebd304",
      "options": {
        "mode": "explode",
        "path": "=get_assets_from_runzero.body",
        "to": "individual_item"
      },
      "reporting": {
        "time_saved_value": 0,
        "time_saved_unit": "minutes"
      },
      "monitoring": {
        "monitor_all_events": false,
        "monitor_failures": false,
        "monitor_no_events_emitted": null
      },
      "width": null,
      "schedule": null
    },
    {
      "type": "Agents::EmailAgent",
      "name": "SEND Email Action",
      "disabled": false,
      "guid": "0e9647b114f315d480f1f85c58e481d3",
      "options": {
        "recipients": "youremail@email.com",
        "reply_to": "youremail@email.com",
        "sender_name": "Your Name",
        "subject": "<<receive_alerts_from_runzero.body.rule_name>>",
        "body": "Alert: <<receive_alerts_from_runzero.body.rule_name>>\n\\<br />\n\\<br />\nLink to asset: https://console.runzero.com/inventory/<<loop_through_assets_for_follow_up_actions.individual_item.id>>\n\\<br />\n\\<br />\nAddresses: <<loop_through_assets_for_follow_up_actions.individual_item.addresses>>\n\\<br />\n\\<br />\nServices:\n<<NEWLINE_TO_BR(NEAT_JSON(loop_through_assets_for_follow_up_actions.individual_item.services))>>"
      },
      "reporting": {
        "time_saved_value": 0,
        "time_saved_unit": "minutes"
      },
      "monitoring": {
        "monitor_all_events": false,
        "monitor_failures": false,
        "monitor_no_events_emitted": null
      },
      "width": null,
      "schedule": null
    },
    {
      "type": "Agents::HTTPRequestAgent",
      "name": "TAG assets in runZero",
      "disabled": false,
      "guid": "c3171fed91ec40d39572260295a63ae0",
      "options": {
        "url": "https://console.runZero.com/api/v1.0/org/assets/<<loop_through_assets_for_follow_up_actions.individual_item.id>>/tags",
        "content_type": "application_json",
        "method": "patch",
        "headers": {
          "Authorization": "Bearer <<CREDENTIAL.runzero_org_token>>"
        },
        "payload": {
          "tags": "hello=from_tines"
        }
      },
      "reporting": {
        "time_saved_value": 0,
        "time_saved_unit": "minutes"
      },
      "monitoring": {
        "monitor_all_events": false,
        "monitor_failures": false,
        "monitor_no_events_emitted": null
      },
      "width": null,
      "schedule": []
    }
  ],
  "diagram_notes": [
    {
      "content": "Hello! Thanks for importing the runZero Sample Story. \n\nThis story is a basic example of what you can do with runZero and Tines. \n\nPrerequisites:\n1. Create a text [credential](https://www.tines.com/docs/credentials/text) called `runzero_export_token`. Set the value as your [runZero export token](docs/leveraging-the-api.md), which can be obtained from the desired [runZero organization](https://console.runzero.com/organizations) page. Export tokens start with `ET`.\n2. Create a text [credential](https://www.tines.com/docs/credentials/text) called `runzero_org_token`. Set the value as your as your [organization API token](docs/leveraging-the-api.md), which can be obtained from the desired [runZero organization](https://console.runzero.com/organizations). Organization API tokens start with `OT`. \n\nThe steps are as follows:\n\n1. **RECEIVE alerts** provides the webhook destination for your runZero alerts \n\n2. **GET search from URL** parses out the search string from the URL provided in the runZero alert \n\n3. **GET search from regex** takes the list provided in step 2 and allows you to use the individual value \n\n4. **GET assets from runZero** uses the runZero Export API to get the list of assets related to the alert \n\n5. **LOOP through assets for follow up actions** takes the list of assets and sends each to the next steps individually \n\n6. **NOTE**: this is the step that you could implement more custom logic in most cases. All of the initial runZero and Tines data transfer is done, but it's your chance to customize this story to fit your use case. \n\n7. **SEND email action** simply sends an email to the destination of your choice \n\n8. **TAG assets in runZero** adds a tag in runZero to each asset showing an example of how you might reach back into runZero after doing other automated activities ",
      "position": [
        165.0,
        180.0
      ],
      "guid": "0e4b9b331dc65316849f7b089bf7bde2",
      "width": 375
    }
  ],
  "links": [
    {
      "source": 0,
      "receiver": 2
    },
    {
      "source": 1,
      "receiver": 4
    },
    {
      "source": 2,
      "receiver": 3
    },
    {
      "source": 3,
      "receiver": 1
    },
    {
      "source": 4,
      "receiver": 6
    },
    {
      "source": 4,
      "receiver": 5
    }
  ],
  "diagram_layout": "{\"ab1f5bf7be49c943d893ab993ade9421\":[555,180],\"d54d8f3f5b0ea857308f45f61a224547\":[555,450],\"d62ddd189bb9080d778d900f2292504d\":[555,270],\"41afc5c4d4c0fdb694d14e1eb380688a\":[555,360],\"b9ada61162bdf006f09d264845ebd304\":[555,555],\"0e9647b114f315d480f1f85c58e481d3\":[555,690],\"c3171fed91ec40d39572260295a63ae0\":[780,690]}",
  "send_to_story_enabled": false,
  "entry_agent_guid": null,
  "exit_agent_guids": [],
  "exit_agent_guid": null,
  "keep_events_for": 604800,
  "reporting_status": true,
  "send_to_story_access": null,
  "send_to_stories": [],
  "form": null,
  "forms": []
}
```
