Alerting from functions
Inspect webhook requests and delivery responses in Webhook Relay functions, and POST an alert to any URL when something looks wrong.
Functions can do more than reshape payloads — they can inspect the request or the delivery response and alert an external system when something is off.
Two common patterns:
- Request function (runs before delivery) — parse the body; if it is not valid JSON (or a required field is missing), POST an alert to a URL.
- Response function (runs after delivery) — if the destination returned an empty body, POST an alert to a URL.
Set alert_webhook_url as a config variable on the function so the alert endpoint is not hard-coded in the source.
For a deeper look at post-delivery hooks, status codes, and rewriting the recorded response, see Response (post-delivery) functions.
Example 1: alert when the request is not valid JSON
Attach this as a request function (before delivery). It tries to parse r.body as JSON. If parsing fails, it posts an alert to your URL and stops forwarding so a bad payload never reaches the destination.
// Request function — runs BEFORE delivery.
// Alert if the body is missing or is not valid JSON.
var url = cfg.get("alert_webhook_url");
if (!r.body || r.body.trim() === "") {
if (url) {
http.post(url, JSON.stringify({
type: "invalid_request",
reason: "empty body",
output: r.metadata["output_name"],
path: r.path
}), { headers: { "Content-Type": "application/json" } });
}
r.stopForwarding();
return;
}
var payload;
try {
payload = JSON.parse(r.body);
} catch (e) {
if (url) {
http.post(url, JSON.stringify({
type: "invalid_request",
reason: "body is not valid JSON",
error: String(e),
output: r.metadata["output_name"],
path: r.path
}), { headers: { "Content-Type": "application/json" } });
}
r.stopForwarding();
return;
}
// Optional: also require a field
if (!payload || payload.id == null) {
if (url) {
http.post(url, JSON.stringify({
type: "invalid_request",
reason: "missing required field: id",
output: r.metadata["output_name"]
}), { headers: { "Content-Type": "application/json" } });
}
r.stopForwarding();
return;
}
// Body looks fine — continue delivery as-is (or call r.setBody(...) to reshape it).
Example 2: alert when the response body is empty
Attach this as a response function (after delivery). When the destination answers with a success status but an empty body — a common silent-failure pattern — post an alert to your URL.
// Response function — runs AFTER delivery.
// Alert if the destination returned an empty body.
var empty = !r.responseBody || r.responseBody.trim() === "";
if (!empty) {
return; // body present — nothing to do
}
var url = cfg.get("alert_webhook_url");
if (!url) {
return;
}
http.post(url, JSON.stringify({
type: "empty_response",
reason: "destination returned an empty body",
status: r.responseStatus,
output: r.metadata["output_name"],
destination: r.metadata["output_url"]
}), { headers: { "Content-Type": "application/json" } });
You can combine this with a status check (r.responseStatus === 0 or >= 400) if you also want alerts on timeouts and HTTP errors. See Response (post-delivery) functions for failure-status examples and for rewriting the recorded response when a 200 should count as failed.
Setup checklist
- Create a function in the dashboard (use the REQUEST tab for example 1, RESPONSE tab for example 2).
- Add a config variable
alert_webhook_urlpointing at your Slack incoming webhook, PagerDuty, Discord, or any HTTP endpoint that accepts POST JSON. - Attach the function to an output:
- Request function →
function_id(before delivery) - Response function →
response_function_id(after delivery)
- Request function →
Related
- Read, write request data —
r.body,r.setBody,r.stopForwarding, config variables. - Make HTTP requests —
http.post/http.requestused to send the alert. - Response (post-delivery) functions — full response API, empty-200 handling, flagging the recorded response.
- Accessing metadata —
output_name,output_url, and other fields useful in alerts.
