> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rootly.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Available Liquid Filters

> Comprehensive reference of built-in and custom Liquid filters for data manipulation, formatting, and string processing in Rootly workflows.

Rootly registers the filters below on top of the [standard Liquid filters](https://shopify.github.io/liquid/). Use them anywhere you can author a Liquid template — workflow tasks, message templates, post-mortem templates, custom field templates, and the in-product Liquid Explorer.

## Lookups & Filtering

### find

* `find: arg1, 'arg2'`
  * `arg1`. String
  * `arg2`. String

```js JS theme={null}
// Pretending object is the following object [{"id": "apple"}, {"id": "banana"}]
{{ object | find: 'id', 'banana' }}
// Output
// {"id": "banana"}
```

### where

Filters an array, returning every element that matches. Pair with `find` (returns the first match) when you need all results.

* `where: 'arg1', 'arg2'`
  * `arg1`. String — key path, dot-separated for nested lookups
  * `arg2`. String (optional) — when omitted, keeps elements where `arg1` is truthy

```js JS theme={null}
// Pretending object is [{"role":"commander","name":"Alice"},{"role":"commander","name":"Bob"},{"role":"scribe","name":"Cara"}]
{{ object | where: 'role', 'commander' }}
// Output
// [{"role":"commander","name":"Alice"},{"role":"commander","name":"Bob"}]

{{ incident.subscribers | where: 'role', 'commander' | size }}
// Count of commanders subscribed to the incident
```

### get

* `get: 'arg'`
  * `arg`. String

```js JS theme={null}
// Pretending object is the following object {"id": "id", "incident": {"title": "Something is on fire!"}}
{{ object | get: 'incident.title' }}
// Output
// Something is on fire!
```

### slice

* `slice: '\*arg'`
  * `arg`. String
  * ... As many args as you need

```js JS theme={null}


// Pretending object is the following object {"key": "hello", "value": "world", "foo": "bar"}

{{ object | slice: 'key' }}

// Output
// {"key": "hello"}

{{ object | slice: 'key', 'foo' }}

// Output
// {"key": "hello", "foo": "bar"}
```

## Arrays & Hashes

### flatten

* flatten

```js JS theme={null}

// Pretending object is the following object \["1", "2", \["3"\]\]
{{ object | flatten }}
// Output
// \["1","2","3"\]
```

### push

Appends a value to the end of an array. A comma-separated string is split into an array first.

* `push: 'arg'`
  * `arg`. String

```js JS theme={null}
{{ '1,2,3' | push: '4' }}
// Output
// ["1", "2", "3", "4"]
```

### pop

Removes the last `n` elements from an array.

* `pop: arg`
  * `arg`. Integer (default `1`)

```js JS theme={null}
{{ '1,2,3,4' | pop: 2 }}
// Output
// ["1", "2"]
```

### shift

Removes the first `n` elements from an array.

* `shift: arg`
  * `arg`. Integer (default `1`)

```js JS theme={null}
{{ '1,2,3,4' | shift: 2 }}
// Output
// ["3", "4"]
```

### unshift

Prepends a value to the start of an array. A comma-separated string is split into an array first.

* `unshift: 'arg'`
  * `arg`. String

```js JS theme={null}
{{ '2,3,4' | unshift: '1' }}
// Output
// ["1", "2", "3", "4"]
```

### keys

Returns the keys of a hash as an array. Useful for iterating slug-keyed objects like `team.services`, `team.functionalities`, and `team.groups`.

* `keys`

```js JS theme={null}
// Pretending team.services is {"api": {...}, "web": {...}}
{{ team.services | keys }}
// Output
// ["api", "web"]

{% for slug in team.services | keys %}- {{ slug }}
{% endfor %}
```

### values

Returns the values of a hash as an array.

* `values`

```js JS theme={null}
{{ team.services | values | size }}
// Number of services on the team
```

### to\_values

* `to_values: 'key'`
  * `key` is optional

```js JS theme={null}

// Pretending object is the following object {"key": "hello", "value": "world"}
{{ object | to_values }}

// Output
// \[{"value":"world"}\]

{{ object | to_values: 'key' }}

// Output
// \[{"value":"hello"}\]
```

## JSON

### to\_json

Also available as `json`.

* `to_json`

```js JS theme={null}
// Pretending object is the following object [{"key": "hello", "value": "world"}]
{{ object | to_json }}
// Output
// [{"key":"hello","value":"world"}]
```

### parse\_json

Parses a JSON string into a hash or array — the inverse of `to_json`. Useful when an alert payload field arrives as a stringified JSON blob.

* `parse_json`

```js JS theme={null}
{{ '{"key":"hello"}' | parse_json | get: 'key' }}
// Output
// hello

{{ alert.data.body | parse_json | get: 'severity' }}
// Reach into a stringified JSON payload nested in alert data
```

Returns the input unchanged if it can't be parsed.

## Dates & Time

### smart\_date

* `smart_date: 'arg'`
  * `arg`. String
* This is using [https://github.com/mojombo/chronic](https://github.com/mojombo/chronic) under the hood.

```js JS theme={null}


{{ 'now' | smart_date: 'tomorrow' }}
// Output
// 2023-06-29 12:00:00 -0700
```

### date\_add

* `date_add: amount, 'date_part'`
  * `amount`. Integer (positive to add, negative to subtract)
  * `date_part`. String - one of: year, month, day, hour, minute, second, millisecond (plurals supported)

Adds a specified amount of time to a date. Works with 'now', 'today', ISO date strings, Time, and Date objects.

```js JS theme={null}
{{ 'now' | date_add: 1, 'day' | date: '%Y-%m-%d' }}
// Output
// 2023-06-30 (tomorrow)

{{ '2023-06-29T10:30:00Z' | date_add: 2, 'hours' | date: '%Y-%m-%d %H:%M' }}
// Output  
// 2023-06-29 12:30

{{ incident.target_resolve_date | date_add: -30, 'minutes' }}
// Output
// 30 minutes before the target resolve date
```

### date\_minus

* `date_minus: amount, 'date_part'`
  * `amount`. Integer (positive to subtract, negative to add)
  * `date_part`. String - one of: year, month, day, hour, minute, second, millisecond (plurals supported)

Subtracts a specified amount of time from a date. Works with 'now', 'today', ISO date strings, Time, and Date objects.

```js JS theme={null}
{{ 'now' | date_minus: 7, 'days' | date: '%Y-%m-%d' }}
// Output
// 2023-06-22 (a week ago)

{{ incident.created_at | date_minus: 1, 'hour' | date: '%Y-%m-%d %H:%M' }}
// Output
// 1 hour before the incident was created

{{ 'today' | date_minus: 6, 'months' }}
// Output
// 6 months ago
```

### to\_iso8601

* `to_iso8601`

```js JS theme={null}
// Pretending object is the following datetime
{{ object | to_iso8601 }}
// Output
// 2023-06-29T12:00:00-07:00
```

### to\_utc

* `to_utc`

Converts a date to UTC timezone. Works with 'now', 'today', ISO date strings, Time, and Date objects.

```js JS theme={null}
{{ incident.started_at | to_utc | date: '%Y-%m-%d %H:%M:%S' }}
// Output
// 2023-06-29 15:30:00 (converted to UTC)

{{ 'now' | to_utc | date: '%Y-%m-%d %H:%M:%S UTC' }}
// Output  
// 2023-06-29 19:45:23 UTC

{{ '2023-06-29T10:30:00-05:00' | to_utc | date: '%Y-%m-%d %H:%M:%S' }}
// Output
// 2023-06-29 15:30:00
```

Useful for synchronizing incident timestamps with timeline values, ensuring all dates display in UTC regardless of user timezone.

### in\_time\_zone

* ` in_time_zone: 'time_zone'`
  * `time_zone`. Any timezone listed in [Timezones](/liquid/timezones)﻿﻿

```js JS theme={null}

{{ now | in_time_zone: 'Europe/London' | date: '%Y-%m-%d %H:%M %Z' }}
```

See [Timezones](/liquid/timezones)﻿ for available values

### distance\_of\_time\_in\_words

* `distance_of_time_in_words: 'arg', 'precise'`
  * `arg`. String (optional)
  * `precise`. String (optional)

```js JS theme={null}
{{ 3720 | distance_of_time_in_words }}
// Output
// about 1 hour
{{ 3720 | distance_of_time_in_words: 0, 'precise' }}
// Output
// 1 hour and 2 minutes
{{ 'May 1, 2020' | distance_of_time_in_words: 'May 31, 2020' }}
// Output
// about 1 month
{{ 'May 1, 2020' | distance_of_time_in_words: 'May 31, 2020', 'precise' }}
// Output
// 4 weeks and 2 days
```

### distance\_of\_time\_in\_words\_to\_now

* `distance_of_time_in_words_to_now: 'precise'`
  * `precise`. String (optional)

```js JS theme={null}
{{ 'May 1, 2020' | distance_of_time_in_words_to_now }}
// Output
// over 2 years
{{ 'May 1, 2020' | distance_of_time_in_words_to_now: 'precise' }}
// Output
// 2 years and 7 months
```

## Tables

### to\_table

* `to_table: 'table_type', 'title', 'time_zone', 'format'`
  * `table_type`. String — `events` or `action_items`
  * `title`. String — table heading
  * `time_zone`. String — any timezone listed in [Timezones](/liquid/timezones)
  * `format`. String — `ascii`, `markdown`, `html`, or `atlassian_markdown`

The `events` type renders timeline columns: Date, User, Event. The `action_items` type renders: Creation Date, Due Date, Kind, Priority, Status, Assignee, Summary.

```js JS theme={null}
{{ incident.events | to_table: 'events', 'Timeline', 'America/Los_Angeles', 'markdown' }}

{{ incident.action_items | to_table: 'action_items', 'Action Items', 'UTC', 'atlassian_markdown' }}
```

## Regex

### regex\_match

Find first match and return array with full match and capture groups

* `regex_match: 'regex', 'flags'`
  * `regex` a ruby regular expression
  * `flags` optional string with regex flags: 'i' (case insensitive), 'm' (multiline), 'x' (extended)

```js JS theme={null}
{{ 'Key1: value1' | regex_match: 'Key(\d+): (.+)' | first }}
// Output
// Key1: value1

{{ 'Key1: value1' | regex_match: 'Key(\d+): (.+)' | last }}
// Output  
// value1

{{ 'user@example.com' | regex_match: '(\w+)@(\w+\.\w+)' | size }}
// Output
// 3 (full match + 2 capture groups)
```

```js JS theme={null}
// Case insensitive matching
{{ 'HELLO world' | regex_match: 'hello', 'i' | first }}
// Output
// HELLO

// Multiline matching  
{{ "Line 1\nLine 2\nDone" | regex_match: 'line.*done', 'im' | first }}
// Output
// Line 1
// Line 2  
// Done
```

Perfect for extracting data from email alert payloads:

```js JS theme={null}
{{ alert.body | regex_match: 'Severity: (.+)' | last }}
// Extract severity level from alert body

{{ alert.body | regex_match: 'Host: ([\w\.-]+)' | last }}  
// Extract hostname from alert
```

### regex\_match\_all

Find all matches and return array of results

* `regex_match_all: 'regex', 'flags'`
  * `regex` a ruby regular expression
  * `flags` optional string with regex flags: 'i' (case insensitive), 'm' (multiline), 'x' (extended)

```js JS theme={null}
{{ 'foo 123 bar 456 baz 789' | regex_match_all: '\d+' | size }}
// Output
// 3

{{ 'foo 123 bar 456 baz 789' | regex_match_all: '\d+' | first }}
// Output
// 123

{{ 'foo 123 bar 456 baz 789' | regex_match_all: '\d+' | last }}
// Output  
// 789
```

```js JS theme={null}
// Extract all email addresses
{{ 'Contact support@example.com or admin@test.org' | regex_match_all: '[\w\.-]+@[\w\.-]+\.\w+' | size }}
// Output
// 2

// Case insensitive matching
{{ 'ERROR: failed, error: timeout' | regex_match_all: 'error: (\w+)', 'i' | first }}
// Output
// failed
```

Ideal for parsing multiple values from alert payloads:

```js JS theme={null}
// Extract all IP addresses from alert body
{{ alert.body | regex_match_all: '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b' }}

// Extract all key-value pairs
{{ alert.body | regex_match_all: 'Key\d+: ([^\n]+)' }}
```

### regex\_replace

Global replace

* `regex_replace: 'regex', 'replacement'`
  * `regexp` a ruby regular expression
  * `replacement` a ruby regular expression

```js JS theme={null}
{{ 'foo bar 123 456' | regex_replace: '\d+', 'baz' }}
// Output
// foo bar baz baz
```

### regex\_replace\_first

First match replace

* `regex_replace_first: 'regex', 'replacement'`
  * `regexp` a ruby regular expression
  * `replacement` a ruby regular expression

```js JS theme={null}
{{ 'foo bar 123 456' | regex_replace_first: '\d+', 'baz' }}
// Output
// foo bar baz 456
```

### regex\_remove

Global match remove

* `regex_remove: 'regex'`
  * `regexp` a ruby regular expression

```js JS theme={null}
{{ 'foo bar 123 456' | regex_remove: '\d+' }}
// Output
// foo bar
```

### regex\_remove\_first

First match remove

* `regex_remove_first: 'regex'`
  * `regexp` a ruby regular expression

```js JS theme={null}
{{ 'foo bar 123 456' | regex_remove_first: '\d+' }}
// Output
// foo bar  456
```

## Slack Helpers

### to\_slack\_markdown

Converts standard Markdown into Slack's mrkdwn flavor (e.g., `**bold**` becomes `*bold*`, link syntax is rewritten, lists are formatted). Use in any task that posts to Slack.

* `to_slack_markdown`

```js JS theme={null}
{{ '**Critical**: payment service is down. See [runbook](https://example.com).' | to_slack_markdown }}
// Output
// *Critical*: payment service is down. See <https://example.com|runbook>.
```

Returns an empty string for non-string inputs.

### format\_text\_for\_slack

Escapes characters that would break a Slack JSON payload — converts double quotes to single quotes and escapes newlines and carriage returns.

* `format_text_for_slack`

```js JS theme={null}
{{ 'She said "hello"
line two' | format_text_for_slack }}
// Output
// She said 'hello'\nline two
```

Use when interpolating user-supplied text into a hand-built Slack Block Kit JSON payload.

## String Manipulation

### dasherize

* `dasherize`

```js JS theme={null}
{{ 'hello_world' | dasherize }}
// Output
// hello-world
```

### parameterize

* `parameterize`
  * `separator` (default to '-')

```js JS theme={null}
{{ 'Hello World' | parameterize }}
// Output
// hello-world
{{ 'Hello World' | parameterize: '_' }}
// Output
// hello_world
```

### camelize

* `camelize`

```js JS theme={null}
{{ 'hello world' | camelize }}
// Output
// Hello world
```

### titleize

* `titleize`

```js JS theme={null}

{{ 'hello world' | titleize }}
// Output
// Hello World
```

### singularize

* `singularize`

```js JS theme={null}
{{ 'cars' | singularize }}
// Output
// car
```

### pluralize

* `pluralize`

```js JS theme={null}
{{ 'car' | pluralize }}
// Output
// cars
```

### humanize

* `humanize`

```js JS theme={null}
{{ '0' | humanize }}
// Output
// No
{{ '1' | humanize }}
// Output
// Yes
{{ 'incident_management' | humanize }}
// Output
// Incident Management
```

### shuffle

* `shuffle`

```js JS theme={null}
{{ '123456789' | shuffle }}
// Output
// 973426581
```

## Encoding

### base64\_encode

Base64-encodes a string using strict encoding (no line breaks).

* `base64_encode`

```js JS theme={null}
{{ 'Aladdin:open sesame' | base64_encode }}
// Output
// QWxhZGRpbjpvcGVuIHNlc2FtZQ==
```

Common use — build a Basic auth header for a workflow HTTP task:

```js JS theme={null}
Authorization: Basic {{ secrets.username | append: ':' | append: secrets.password | base64_encode }}
```

### base64\_decode

Decodes a strict-Base64 string. Raises a Liquid argument error on invalid input.

* `base64_decode`

```js JS theme={null}
{{ 'QWxhZGRpbjpvcGVuIHNlc2FtZQ==' | base64_decode }}
// Output
// Aladdin:open sesame
```

### base64\_url\_safe\_encode

Base64-encodes using the URL-safe alphabet (`-` and `_` instead of `+` and `/`).

* `base64_url_safe_encode`

```js JS theme={null}
{{ 'subjects?ids=1,2,3' | base64_url_safe_encode }}
// Output
// c3ViamVjdHM_aWRzPTEsMiwz
```

### base64\_url\_safe\_decode

Decodes a URL-safe Base64 string.

* `base64_url_safe_decode`

```js JS theme={null}
{{ 'c3ViamVjdHM_aWRzPTEsMiwz' | base64_url_safe_decode }}
// Output
// subjects?ids=1,2,3
```

## Markdown & HTML

### markdown\_to\_html

Renders Markdown to sanitized HTML — useful when an integration expects HTML input (e.g., email templates, webhook payloads).

* `markdown_to_html`

```js JS theme={null}
{{ '# Title

This is **bold** text.' | markdown_to_html }}
// Output
// <h1>Title</h1>
// <p>This is <strong>bold</strong> text.</p>
```

Output is sanitized to a safelist of tags and attributes; links get `rel="nofollow noopener noreferrer"`. Returns an empty string for nil input.

### html\_to\_markdown

Inverse of `markdown_to_html`. Handles most common HTML elements including headings, paragraphs, lists, links, code blocks, and tables.

* `html_to_markdown`

```js JS theme={null}
{{ '<h1>Title</h1><p>This is <strong>bold</strong> text.</p>' | html_to_markdown }}
// Output
// # Title
// 
// This is **bold** text.
```

```js JS theme={null}
{{ '<ul><li>Item 1</li><li>Item 2</li></ul>' | html_to_markdown }}
// Output
// - Item 1
// - Item 2
```

Returns empty string for nil or empty input. Preserves original HTML on conversion errors.

## URLs

### shortener

* `shortener`

```js JS theme={null}
{{ 'https://rootly.com/account/incidents/123456' | shortener }}
// Output
// https://root.ly/1234
```

## AI

### open\_ai\_completion

Sends the input string to OpenAI as the user prompt and returns the completion text. Useful for inline summarization or text transformation directly inside a Liquid template.

* `open_ai_completion`

```js JS theme={null}
{{ alert.description | open_ai_completion }}
// Returns OpenAI's completion using the alert description as the prompt
```

<Tip>
  For most use cases, prefer the dedicated AI workflow tasks (`Create OpenAI Chat Completion`, `Create Anthropic Chat Completion`, etc.) over this filter — they expose model selection, system prompts, temperature, and message history, which this filter does not.
</Tip>

Returns `"something went wrong"` on failure.

## Integration Converters

Rootly's severity, priority, and status enums don't always map 1-to-1 to vendor enums. Converter filters translate a Rootly value to the equivalent vendor value when building HTTP payloads or workflow task arguments. They take no extra arguments unless noted.

```js JS theme={null}
{{ incident.severity | linear_severity_converter }}
// Maps Rootly severity to Linear's severity scale

{{ action_item.priority | clickup_priority_converter }}
// Maps Rootly priority to ClickUp's priority scale
```

| Filter                              | What it converts                                  |
| ----------------------------------- | ------------------------------------------------- |
| `linear_severity_converter`         | Rootly severity → Linear                          |
| `linear_priority_converter`         | Rootly priority → Linear                          |
| `trello_archivation_converter`      | Rootly status → Trello archivation                |
| `asana_completion_converter`        | Rootly status → Asana completion                  |
| `github_completion_converter`       | Rootly status → GitHub issue state                |
| `gitlab_completion_converter`       | Rootly status → GitLab issue state                |
| `shortcut_archivation_converter`    | Rootly status → Shortcut archivation              |
| `shortcut_completion_converter`     | Rootly status → Shortcut completion               |
| `zendesk_severity_converter`        | Rootly severity → Zendesk                         |
| `zendesk_priority_converter`        | Rootly priority → Zendesk                         |
| `zendesk_completion_converter`      | Rootly status → Zendesk (takes a `type` arg)      |
| `service_now_severity_converter`    | Rootly severity → ServiceNow                      |
| `service_now_completion_converter`  | Rootly status → ServiceNow                        |
| `freshservice_severity_converter`   | Rootly severity → Freshservice                    |
| `freshservice_priority_converter`   | Rootly priority → Freshservice                    |
| `freshservice_completion_converter` | Rootly status → Freshservice (takes a `type` arg) |
| `opsgenie_completion_converter`     | Rootly status → Opsgenie (takes a `type` arg)     |
| `clickup_severity_converter`        | Rootly severity → ClickUp                         |
| `clickup_priority_converter`        | Rootly priority → ClickUp                         |
| `motion_severity_converter`         | Rootly severity → Motion                          |
| `motion_priority_converter`         | Rootly priority → Motion                          |
