Send notifications to Discord
Set up Discord webhook notifications with copy-paste templates for alert events.
This recipe configures Planekeeper to send alert notifications to a Discord channel using webhooks. Discord requires a specific JSON format with a content field for text messages.
Prerequisites
- A running Planekeeper instance with at least one alert config
- Admin access to a Discord server
Why Discord needs custom templates
Discord’s webhook API expects a specific JSON structure with a content field for text messages. Planekeeper’s default notification payload does not match this format, so Discord will reject it with a 400 Bad Request error.
You must enable event-specific templates on the notification channel and provide templates that wrap your message in the {"content": "..."} structure Discord requires. The templates in this recipe handle this for you.
Step 1: Create a Discord webhook
- Open Discord and go to your target server
- Right-click the channel where you want notifications and select Edit Channel
- Go to Integrations > Webhooks
- Click New Webhook
- Give it a name (for example,
Planekeeper Alerts) - Click Copy Webhook URL
The URL looks like: https://discord.com/api/webhooks/123456789/abcdefg...
Step 2: Create a notification channel in Planekeeper
- Navigate to Notification Channels in the sidebar
- Click Create Channel
- Fill in the fields:
| Field | Value |
|---|---|
| Name | Discord Alerts |
| Channel Type | webhook |
| URL | Paste your Discord webhook URL |
- Check Use Event-Specific Templates
- Add the templates from step 3 below
- Click Create
Step 3: Add Discord templates
Copy and paste these templates into the corresponding fields.
New alert template
{"content": "**{{.Alert.Severity | upper}} Alert**: {{.Alert.ConfigName}}\n\n**Artifact:** {{.Alert.ArtifactName}}\n**Current:** {{.Alert.DiscoveredVersion}} -> **Latest:** {{.Alert.LatestVersion}}\n**Behind by:** {{.Alert.BehindBy}} ({{.Alert.RuleType}})\n\n[Click to Acknowledge]({{.AcknowledgeURL}})"}
This produces a message like:
CRITICAL Alert: ArgoCD Version Check
Artifact: argoproj.github.io/argo-helm/argo-cd Current: 5.46.0 -> Latest: 6.7.0 Behind by: 8 (minors_behind)
Acknowledged template
{"content": "{{if .IsAcknowledged}}**Acknowledged**: {{.Alert.ConfigName}} - {{.Alert.ArtifactName}}\nAcknowledged by {{.AcknowledgedBy}}{{else}}**Unacknowledged**: {{.Alert.ConfigName}} - {{.Alert.ArtifactName}}\nAcknowledgment was reset due to a version change{{end}}"}
Resolved template
{"content": "**Resolved**: {{.Alert.ConfigName}} - {{.Alert.ArtifactName}}\nThe version has been updated and no longer triggers this alert."}
Step 4: Test the channel
- Go to Notification Channels and find
Discord Alerts - Click Test
- Check your Discord channel for the test message
- If the test fails, verify the webhook URL is correct and the channel still exists
Discord rate limits
Discord limits webhook messages to 30 per minute per channel. If you have many alerts firing simultaneously, some deliveries may be delayed by Planekeeper’s retry logic.
Step 5: Create a notification rule
- Navigate to Notification Rules in the sidebar
- Click Create Rule
- Fill in the fields:
| Field | Value |
|---|---|
| Name | All Alerts to Discord |
| Channel | Select Discord Alerts |
| Severity Filter | Leave empty (matches all severities) |
| Event Filter | Leave empty (matches all events) |
- Click Create
All alert events now route to your Discord channel.
Route only critical alerts
To send only critical alerts to Discord, set the Severity Filter to critical. Create additional notification rules with different channels for other severity levels.
Customizing the format
Minimal template
For a compact notification without the acknowledge link:
{"content": "{{.Alert.Severity | upper}}: {{.Alert.ConfigName}} is {{.Alert.BehindBy}} behind ({{.Alert.DiscoveredVersion}} -> {{.Alert.LatestVersion}})"}
Template with rule details
For more context about why the alert was triggered:
{"content": "**{{.Alert.Severity | upper}}**: {{.Alert.ConfigName}}\nRule: {{.Alert.RuleName}} ({{.Alert.RuleType}})\nRepo: {{.Alert.RepositoryURL}}\nFile: {{.Alert.TargetFile}}\nVersion: {{.Alert.DiscoveredVersion}} -> {{.Alert.LatestVersion}}"}