Prometheus Alertmanager integration
Forward Prometheus alerts to Unit Oncall using Alertmanager's webhook receiver. Alertmanager groups firing/resolved alerts and POSTs a JSON body; Unit Oncall normalizes it, routes it to a Schedule, and pages the on-call responder.
Setup
-
In Unit Oncall, create a Webhook (Integrations → Webhooks → New). Choose a Team and default Schedule. Standard auth mode is the simpler choice — the secret is embedded in the URL, so no extra config is needed — but Secure mode also works because Alertmanager's
webhook_configssupportshttp_configheaders. Copy the generated Webhook URL. -
In your
alertmanager.yml, add a webhook receiver and route alerts to it:receivers: - name: unit-oncall webhook_configs: - url: "https://<your-api-host>/api/v1/wh/{token}" send_resolved: true route: receiver: unit-oncall -
Reload Alertmanager so the configuration takes effect.
Alertmanager's payload has a top-level status, commonLabels, and an alerts array. The recommended rule below reads the first alert in that array.
Webhook URL
Unit Oncall exposes a single unified receive endpoint. The token in the path identifies the webhook (and, in Standard mode, carries the secret):
POST https://<your-api-host>/api/v1/wh/{token}
{token}is an opaque, encrypted value generated when you create the Webhook. Treat it as a credential.- Standard auth mode (recommended for Alertmanager): the secret is embedded in the token, so the URL is self-contained.
- Secure auth mode: the secret is sent as the
X-Webhook-Secretheader or awebhook_secretbody field. Alertmanager'swebhook_configssupportshttp_configheaders, so Secure mode is also viable.
Recommended transformation rule
This rule reads the first entry of the alerts array. It uses the alertname label as the fingerprint, builds a title from the status and alert name, maps the severity label to Unit Oncall severities, and maps startsAt as the detection time.
{
"name": "Prometheus Alertmanager",
"description": "Maps Alertmanager webhook receiver payloads to Unit Oncall alerts.",
"is_active": true,
"mappings": {
"fingerprint": {
"type": "jsonpath",
"path": "$.alerts[0].labels.alertname"
},
"title": {
"type": "format",
"format": "[{$.status}] {$.alerts[0].labels.alertname}"
},
"severity": {
"type": "jsonpath",
"path": "$.alerts[0].labels.severity",
"mapping": {
"critical": "critical",
"warning": "warning",
"info": "info",
"page": "critical"
},
"default": "warning"
},
"message": {
"type": "jsonpath",
"path": "$.alerts[0].annotations.description",
"default": "Alertmanager alert (no description annotation provided)"
},
"timestamp": {
"type": "jsonpath",
"path": "$.alerts[0].startsAt"
},
"tags": {
"type": "jsonpath",
"path": "$.alerts[0].labels.instance"
}
}
}
See the Transformation Rule reference for the full field and mapping syntax.
Troubleshooting
- No alert arrives. Use
amtoolor trigger a test alert, then confirm the Webhook is enabled in Unit Oncall and the receiver URL is complete. 403 webhook disabled. The Webhook'sis_enabledisfalse. Enable it.- Resolved alerts stay open. Set
send_resolved: trueon the receiver, and make sure thefingerprintresolves to the same value for both firing and resolved notifications. MapstartsAtso transition ordering is correct — see the note in the Transformation Rule reference. - Severity is always the default. Your rules do not set a
severitylabel, or it has an unmapped value. Add the label or extend themappingtable. - Only one alert shows up. Alertmanager groups multiple alerts into one notification; this rule reads
alerts[0]. Tune yourgroup_byso each notification represents one logical incident, or send one alert per group.
