Message Templates
Message templates control how events are formatted before delivery. Templates support three output formats: Discord embeds, Slack Block Kit messages, and Telegram HTML.
Template Formats
Templates support two config versions:
v1 — Flat (single platform)
A single TemplateConfig object that applies to all platforms. This is the simpler format and is still fully supported:
{
"title": "{{.Meta.EventType}}",
"description": "New event from {{.Body.repository.full_name}}",
"color": 16750848,
"fields": [
{
"name": "Action",
"value": "{{.Body.action}}",
"inline": true
}
],
"footer": "Dispatch",
"thumbnail": "{{.Body.sender.avatar_url}}",
"author": "{{.Body.sender.login}}",
"timestamp": true
}
v2 — Multi-platform
A PlatformTemplateConfig envelope with per-platform variants. Dispatch selects the platform matching the destination type, falling back to default if no specific variant is configured:
{
"version": 2,
"platforms": {
"discord": {
"title": "{{.Meta.EventType}}",
"description": "{{.Body.repository.full_name}}",
"color": 5763719,
"fields": [
{ "name": "Action", "value": "{{.Body.action}}", "inline": true }
],
"timestamp": true
},
"slack": {
"slack_blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*{{.Meta.EventType}}* — {{.Body.repository.full_name}}"
}
}
]
},
"telegram": {
"telegram_html": "<b>{{.Meta.EventType}}</b>\n{{.Body.repository.full_name}}\n\nAction: <code>{{.Body.action}}</code>"
},
"default": {
"title": "{{.Meta.EventType}}",
"description": "{{.Body.repository.full_name}}",
"timestamp": true
}
}
}
Discord Embed Config
The Discord platform config (or v1 flat config) renders a Discord embed:
Fields
| Field | Type | Description |
|---|---|---|
title | string | Embed title (max 256 chars). Supports template syntax. |
description | string | Main content (max 4096 chars, supports markdown). Supports template syntax. |
color | integer | Decimal color code (e.g., 16711680 for red, 65280 for green) |
fields | array | Up to 25 embed fields |
footer | string | Footer text. Supports template syntax. |
thumbnail | string | URL for thumbnail image. Supports template syntax. |
author | string | Author name. Supports template syntax. |
timestamp | boolean | Whether to include an ISO 8601 timestamp |
Embed Fields
Each field in the fields array has:
| Field | Type | Description |
|---|---|---|
name | string | Field label (max 256 chars). Supports template syntax. |
value | string | Field content (max 1024 chars). Supports template syntax. |
inline | boolean | Whether to display inline (side-by-side with other inline fields) |
Slack Block Kit Config
For Slack destinations, set a slack_blocks array in the platform config. This renders natively as a Slack Block Kit message. All string values inside the blocks support template expressions:
{
"slack_blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "{{upper .Meta.EventType}}"
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Repository*\n{{.Body.repository.full_name}}"
},
{
"type": "mrkdwn",
"text": "*Action*\n{{.Body.action}}"
}
]
},
{
"type": "divider"
}
]
}
If slack_blocks is not set, the Discord embed fields are auto-converted to a Slack attachment format.
Telegram HTML Config
For Telegram destinations, set a telegram_html field in the platform config. This string supports template expressions and is sent as HTML. Supported HTML tags:
| Tag | Effect |
|---|---|
<b> / <strong> | Bold |
<i> / <em> | Italic |
<u> / <ins> | Underline |
<s> / <strike> / <del> | Strikethrough |
<code> | Inline code |
<pre> | Code block |
<blockquote> | Block quote |
<a href="url"> | Hyperlink |
<tg-spoiler> | Hidden spoiler |
{
"telegram_html": "<b>{{upper .Meta.EventType}}</b> on <code>{{.Body.repository.full_name}}</code>\n\n{{.Body.pull_request.title}}\n\nOpened by: {{.Body.sender.login}}"
}
If telegram_html is not set, Dispatch auto-converts the Discord embed fields to Telegram HTML.
Template Variables
All template fields have access to two objects:
.Body
The full event payload as a nested map. Access any field using dot notation:
{{.Body.action}}
{{.Body.repository.full_name}}
{{.Body.pull_request.title}}
{{.Body.commits[0].message}}
.Meta
Event metadata:
| Variable | Description |
|---|---|
{{.Meta.EventType}} | The extracted event type (e.g., push, pull_request) |
{{.Meta.EventID}} | The unique event ID (UUID) |
{{.Meta.EndpointID}} | The endpoint that received the event |
{{.Meta.Timestamp}} | ISO 8601 timestamp of when the event was received |
Template Functions
The following functions are available in template expressions:
| Function | Description | Example |
|---|---|---|
upper | Convert to uppercase | {{upper .Body.action}} |
lower | Convert to lowercase | {{lower .Body.action}} |
default | Fallback value if empty | {{default .Body.name "Unknown"}} |
truncate | Truncate to N characters | {{truncate .Body.description 100}} |
json | Format value as JSON | {{json .Body.commits}} |
ansiGray | Discord ANSI gray color | {{ansiGray "text"}} |
ansiRed | Discord ANSI red color | {{ansiRed "error"}} |
ansiGreen | Discord ANSI green color | {{ansiGreen "success"}} |
ansiYellow | Discord ANSI yellow color | {{ansiYellow "warning"}} |
ansiBlue | Discord ANSI blue color | {{ansiBlue "info"}} |
ansiPink | Discord ANSI pink color | {{ansiPink "text"}} |
ansiCyan | Discord ANSI cyan color | {{ansiCyan "text"}} |
ansiWhite | Discord ANSI white color | {{ansiWhite "text"}} |
ansiBold | Discord ANSI bold | {{ansiBold "text"}} |
ansiUnderline | Discord ANSI underline | {{ansiUnderline "text"}} |
ANSI color functions are only meaningful inside Discord code block descriptions (```ansi ```). They have no effect in Slack or Telegram output.
Auto-Formatting
When no template is assigned to an endpoint-destination link, Dispatch uses auto-detection based on the event payload to generate an appropriate embed.
GitHub Events
If the payload contains repository and sender fields, Dispatch generates a specialized embed based on the event type:
- push — commit summary with author, branch, and commit messages
- pull_request — PR title, description, status, and labels
- issues — issue title, body, assignees, and labels
- release — release name, tag, and description
- workflow_run — workflow name, status, and conclusion
- And more GitHub event types with tailored formatting
GitLab Events
If the payload contains a project object with a GitLab structure, Dispatch generates embeds for:
- Push Hook — branch, commit count, and commit messages
- Merge Request Hook — MR title, description, and status
- Issue Hook — issue title and description
Bitbucket Events
For Bitbucket payloads (containing repository.scm = "git" and Bitbucket-style structure):
- repo:push — branch and commit summary
- pullrequest:created / fulfilled / rejected — PR title, status, and participants
Jira Events
For Jira payloads (webhookEvent field present):
- jira:issue_created — issue key, summary, type, and priority
- jira:issue_updated — field changes with old/new values
- jira:issue_deleted — issue key and summary
Linear Events
For Linear payloads (type and organizationId fields present):
- Issue lifecycle events — title, status, priority, and assignee
- Comment events — comment text and issue context
- Project updates — project name and status changes
Stripe Events
For Stripe payloads (object field with "api_version" present, or livemode field):
- charge.succeeded / failed — amount, currency, and customer
- payment_intent.succeeded / payment_failed — amount and status
- subscription.created / updated / deleted — plan name and customer
- invoice.paid / payment_failed — amount due and customer
Slack Events
If the payload contains team_id, api_app_id, and type: event_callback, Dispatch generates Slack-specific embeds for:
- Messages, reactions, channel events, member events, pins, files, emoji changes, and more
Default
For unrecognized payloads, Dispatch creates a simple embed with the raw JSON payload formatted as a code block.
Routing Rules
Each endpoint-destination link can have routing rules that select different templates based on event fields:
[
{
"field": "body.action",
"op": "eq",
"value": "opened",
"template_id": "uuid-for-opened-template"
},
{
"field": "body.action",
"op": "eq",
"value": "closed",
"template_id": "uuid-for-closed-template"
}
]
Rules are evaluated top-to-bottom. The first matching rule's template is used. If no rule matches, the default link template (or auto-formatting) is used. A routing rule can also specify a transform_id to override the transform for that rule.
Supported Operators
| Operator | Description |
|---|---|
eq | Equals |
neq | Not equals |
contains | Contains substring |
not_contains | Does not contain substring |
exists | Field exists and is non-empty |
not_exists | Field does not exist or is empty |