Message configuration
Supported payload types
Each destination type has specific schema structures tailored to its payload type. For Slack, the schema varies depending on whether the payload type is Structured or Raw.
| Payload type | payload_type API value | Description |
|---|---|---|
| Structured | structured | The user provides templates for discrete fields (e.g., Title, Description, Footer). The system builds a Slack payload from these fields. |
| Raw | raw | The user provides a template that must render to a valid JSON object that follows Slack's API payload format. Allows full control over notification content. |
- Structured payload type
- Raw payload type
| UI label | API field name | Rendered output type | Required | Description |
|---|---|---|---|---|
| Title | title | String | true | The title of the Slack notification. |
| Description | description | String | false | A brief description of the Slack notification. |
| Footer | footer | String | false | Footer text for the Slack notification. |
For raw payload type, the Slack message schema is configured directly using a JSON payload. The templates in the provided payload are rendered and the result is sent as-is to the Slack API.
| UI label | API field name | Rendered output type | Required | Description |
|---|---|---|---|---|
| Payload | payload | JSONObject | true | The payload of the request to be sent to Slack. |
To edit the payload, go to Integrations, then Notification Center, then Presets, then New alert preset, and open the Advanced tab in Message.
The payload accepts any Block Kit layout. Paste the template below into Payload, then adjust the blocks and variables to suit your alert.
Alert notification template
This template renders a headline, the triggered or resolved state with a timestamp, the alert description, the alert type and group-by keys, and a breakdown of the groups that triggered.
{%- set NL = "
" -%}
{%- set headerText = alert.highestPriority ~ " - " ~ alertDef.name | truncate(length=149, end="…") -%}
{%- set description = alertDef.description | default(value="") -%}
{%- set descriptionText = "*Description:* " ~ description | truncate(length=2900, end="…") -%}
{%- set typeText = "*Alert type:*" ~ NL ~ alertDef.type -%}
{%- set groupByKeys = alertDef.groupByKeys | join(sep=", ") -%}
{%- set groupByText = "*Group by:*" ~ NL ~ groupByKeys | truncate(length=1900, end="…") -%}
{%- set retriggerMinutes = alertDef.incidentSettings.retriggeringPeriod.minutes | default(value="n/a") -%}
{%- set contextText = "Alert ID: `" ~ alertDef.id ~ "` | Re-trigger period: " ~ retriggerMinutes ~ "m" -%}
{#- set_global is required here: a plain `set` inside a loop resets every iteration. -#}
{%- set_global groupsText = "*Affected groups:*" -%}
{%- for g in alert.groups | slice(end=20) -%}
{%- set keyValues = g.keyValues | json_encode | truncate(length=120, end="…") -%}
{%- set_global groupsText = groupsText ~ NL ~ "• `" ~ keyValues ~ "` - priority " ~ g.priority -%}
{%- endfor -%}
{
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": {{ headerText | json_encode }},
"emoji": true
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "{% if alert.status == 'Triggered' %}:red_circle: *Triggered*{% else %}:large_green_circle: *Resolved*{% endif %} • {{ alert.timestamp | date(format='%Y-%m-%d %H:%M:%S UTC') }}"
}
},
{% if description %}
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": {{ descriptionText | json_encode }}
}
},
{% endif %}
{
"type": "section",
"fields": [
{ "type": "mrkdwn", "text": {{ typeText | json_encode }} },
{ "type": "mrkdwn", "text": {{ groupByText | json_encode }} }
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": {{ groupsText | json_encode }}
}
},
{ "type": "divider" },
{
"type": "context",
"elements": [
{ "type": "mrkdwn", "text": {{ contextText | json_encode }} }
]
}
]
}
The {%- set -%} block at the top assembles each piece of text first, then the payload places the finished values into blocks. Building the text separately keeps the length limits and the JSON escaping in one place, and it keeps the payload readable.
Three details in that block affect the output:
NLholds a literal newline, because Tera string literals do not interpret\n.- The loop uses
set_globalrather thanset. A plainsetinside a loop is scoped to the iteration, so the accumulated text would reset on every pass. slice(end=20)caps the breakdown at the first 20 alert groups. Raise the value to list more, and keep the result within the 3000-character limit for asection.
On alert types that do not group, such as logsImmediate, Group by renders with no value and the breakdown lists a single empty group as {}. Guard both with {% if %} if you would rather omit them.
Variables used
| Variable | Description |
|---|---|
alertDef.name | Name of the alert definition. |
alertDef.description | Description of the alert definition. |
alertDef.type | Alert type, for example metricThreshold. |
alert.highestPriority | Highest priority across the alert groups, for example P1. |
alertDef.groupByKeys | Keys the alert groups by. Empty on alert types that do not group, such as logsImmediate. |
alertDef.id | Unique identifier of the alert definition. |
alertDef.incidentSettings.retriggeringPeriod.minutes | Minutes before the alert can trigger again. |
alert.status | Current status of the alert, Triggered or Resolved. |
alert.timestamp | Time the alert was triggered. |
alert.groups | Alert groups, each with priority and keyValues. |
For the full set of fields, see Alerts. For syntax, see Dynamic templating.
Guidelines for raw payloads
Escape every interpolated value. Pipe any value that can contain quotation marks or line breaks, such as an alert name or description, through json_encode, as the template above does for headerText and descriptionText. The filter adds the surrounding quotation marks, so omit them in the payload. An unescaped quotation mark in an alert name renders invalid JSON, and the notification fails.
Keep blocks non-empty. Slack rejects a section block whose text renders empty. Supply a fallback with the default filter, or start the text with a static label as the template above does for groupsText.
Respect the Slack limits. A message holds up to 50 blocks, a header up to 150 characters, a section text up to 3000 characters, and a section up to 10 fields, each up to 2000 characters. Apply the truncate filter to values of unpredictable length.
Configure the triggered and resolved states. Each preset holds distinct templates for the Triggered and Resolved states. Either set a payload per state, or branch on alert.status as the template above does.
Validate before saving. Preview the layout in Block Kit Builder, then select Send test notification to confirm the rendered payload reaches your channel.
Next steps
Configure a Slack connector to define where notifications are sent in Connector configuration.