Skip to content

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}"
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.

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 external_url, and duration appears only for runs that have one.

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.

  • A missing or empty url, or one that isn’t http:// or https://.
  • An empty key in headers.