Webhook
The webhook notifier sends a JSON POST to any HTTP endpoint: PagerDuty, n8n,
your own server. For Discord, use the
Discord notifier instead, which sends
messages Discord can display.
[notifiers.my-hook]type = "webhook"url = "${WEBHOOK_URL}"
[notifiers.my-hook.headers]Authorization = "Bearer ${WEBHOOK_TOKEN}"Fields
Section titled “Fields”| Key | Required | What it does |
|---|---|---|
url |
yes | The endpoint. Keep it out of the file; see Storing the secret. |
headers |
no | Extra HTTP headers sent with every request, like an auth token. Values can use ${...} too. |
template_path |
no | A Go template file that replaces the built-in JSON body. |
Webhook notifiers don’t accept a my-hook:<target> override.
What the body looks like
Section titled “What the body looks like”Each event is one POST with Content-Type: application/json. The keys are
stable, so you can parse them safely:
{ "kind": "run.failed", "severity": "error", "timestamp": "2025-01-15T02:30:45Z", "task": "backup-postgres", "title": "backup-postgres failed", "message": "Exited with code 1 after 3m 4s.", "trigger": "Scheduled run", "run": { "id": "01JXYZ...", "exit_code": 1, "triggered_by": "cron", "url": "https://runwisp.example.com/tasks/backup-postgres/01JXYZ...", "duration": "3m 4s" }, "output_tail": "Error: connection refused\ndial tcp ...", "reason": "exit 1", "source": "runwisp (bright-falcon)"}run, output_tail, and reason appear only when they apply. Inside run,
url needs the Web UI address, and
duration appears only for runs that have one.
Changing the body
Section titled “Changing the body”Point template_path at your own Go template. Start from the built-in
webhook.tmpl.json.
It gets the whole event and the same helpers as the
Slack template.
What’s rejected
Section titled “What’s rejected”- A missing or empty
url, or one that isn’thttp://orhttps://. - An empty key in
headers.