Post to a Custom Webhook#
When a service has no official integration, it usually has a webhook. This example posts a JSON payload to any URL you control, the generic building block for notifications and automation.
The Script#
// webhook.js
import env from "env";
const body = {
source: "geartrain",
message: "Daily job finished",
at: new Date().toISOString(),
};
const res = await fetch(env.get("WEBHOOK_URL"), {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Webhook-Secret": env.get("WEBHOOK_SECRET"),
},
body: JSON.stringify(body),
});
if (!res.ok) {
throw new Error(`Webhook failed: ${res.status}`);
}
console.log("Webhook delivered");
How It Works#
- The payload is plain JSON: adapt the fields to whatever the receiving service expects.
- Extra headers, such as a shared secret, are a common way for the receiver to verify the request came from you. A secret header alone does not protect the body from tampering; use an HMAC signature when the receiver needs to verify both authenticity and integrity.
- If the receiver only needs a signal and no data, send an empty body
with
body: ""and drop theContent-Typeheader.
Setup#
Create two secrets:
| Secret | Value |
|---|---|
WEBHOOK_URL |
The endpoint that receives the post |
WEBHOOK_SECRET |
A shared secret the receiver checks |
If the receiver does not check a secret, drop that header and secret.