Webhooks
A watcher can deliver to your own server instead of Telegram. The body is the alert's payload, the signature proves it came from Fletch, and a delivery can arrive more than once.
Register an endpoint
Needs a key with watchers:write. The response carries the secret once; no route returns it again, and rotating is the only way to get a new one.
curl -X POST https://fletch.now/api/v1/webhooks \
-H "Authorization: Bearer flk_…" \
-H "content-type: application/json" \
-d '{"name":"prod","url":"https://example.com/fletch"}'Then create a watcher with webhookId set, or move an existing one with a PATCH. Setting it to null sends that watcher back to Telegram.
Verify the signature
Each POST carries X-Fletch-Signature: t=<unix>,v1=<hex>, where the hex is an HMAC-SHA256 of "<t>.<body>" with your endpoint's secret. Compare in constant time, and reject a timestamp far from now.
import crypto from "node:crypto";
function verify(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}Retries and duplicates
A 2xx is a delivery. Anything else is retried with full-jitter backoff up to 8 attempts, then the delivery is failed. The timeout is 10 seconds.
The body carries a stable id, so key on it: the same alert can arrive twice. queuedAt is when Fletch matched the event and sentAt is when the attempt was posted, so on a retry they differ.