Packages

HTTP POST webhook delivery channel for Raven alerts.

Current section

Files

Jump to
raven_integration_webhook lib integrations webhook.ex
Raw

lib/integrations/webhook.ex

defmodule Channels.Webhook do
@moduledoc """
Delivers notifications to an HTTP webhook endpoint.
POSTs a JSON body to the configured URL whenever a notification fires.
An optional bearer token can be set for endpoint authentication.
## Params
* `:url` — the endpoint URL to POST to (required)
* `:secret` — sent as `Authorization: Bearer <secret>` (optional)
## Payload shape
```json
{
"monitor_id": "my-http-check",
"monitor_name": "My HTTP Check",
"status": "down",
"previous_status": "up",
"occurred_at": "2026-05-30T12:00:00Z",
"node": "raven@indigo",
"instance_id": "inst-1",
"alert_started_at": "2026-05-30T11:46:00Z",
"duration_down_s": 840
}
```
`node`, `instance_id`, `alert_started_at`, and `duration_down_s` are
`null` whenever the firing handler didn't have that information — always
present in the payload, never omitted.
A 2xx response is considered successful. Any other status code or
connection error is returned as `{:error, reason}`.
"""
use CodeNameRaven.Channel, category: :webhook
alias CodeNameRaven.Channel.Notification
@impl true
def display_name, do: "Webhook"
@impl true
def params_template, do: %{url: "https://", secret: nil}
@impl true
def params_schema do
[
url: [type: :string, required: true],
secret: [type: :string]
]
end
@impl true
def deliver(%Notification{} = n, %{url: url} = params) when is_binary(url) and url != "" do
payload = %{
monitor_id: n.monitor_id,
monitor_name: n.monitor_name,
status: to_string(n.status),
previous_status: n.previous_status && to_string(n.previous_status),
occurred_at: DateTime.to_iso8601(n.occurred_at),
node: n.node && to_string(n.node),
instance_id: n.instance_id,
alert_started_at: n.alert_started_at && DateTime.to_iso8601(n.alert_started_at),
duration_down_s: Notification.duration_down(n)
}
headers =
[{"content-type", "application/json"}] ++
if(params[:secret], do: [{"authorization", "Bearer #{params[:secret]}"}], else: [])
case CodeNameRaven.Protocol.Http.request(:post, url, body: Jason.encode!(payload), headers: headers) do
{:ok, %{status: status}} when status in 200..299 -> :ok
{:ok, %{status: status}} -> {:error, "HTTP #{status}"}
{:error, reason} -> {:error, to_string(reason)}
end
end
def deliver(_notification, _params), do: {:error, "url is required"}
end