Alert webhooks
The webhook reference for developers - the JSON body an alert sends, the HMAC signature to verify, and the delivery rules.
This is the developer reference for alert webhooks: what arrives at your server, how to prove it came from us, and how delivery behaves. Setting one up takes no code and is covered in Alerts & warnings; come here when you are writing the receiver.
The request
Each notification is a POST with a JSON body:
{
"version": 1,
"event": "alert.triggered",
"firedAt": "2026-08-03T04:12:07.881Z",
"site": {
"subdomain": "ardooie",
"title": "Ardooie Meteo",
"url": "https://ardooie.pro-weather.com"
},
"alert": {
"id": "clx0alertruleid",
"metric": "tempLow",
"label": "Temperature below",
"kind": "threshold",
"reminder": false
},
"reading": { "value": -1.4, "text": "-1.4 °C", "unit": "°C", "detail": null },
"threshold": { "value": 0, "text": "0.0 °C" },
"observedAt": 1754194320
}reading.value and reading.text are null for an event alert, which reports
an occurrence rather than a number; reading.detail carries the specifics
(which channel, which record, which upload). alert.reminder is true when
the notification is a repeat of a condition already reported.
Verifying the signature
Every request carries three headers:
| Header | Meaning |
|---|---|
X-ProWeather-Event | alert.triggered or alert.test |
X-ProWeather-Timestamp | Unix seconds at which we signed the request |
X-ProWeather-Signature | sha256= followed by the hex HMAC-SHA256 of <timestamp>.<raw body>, keyed with your signing secret |
Compute the same HMAC over the raw body (before any JSON parsing) and compare it with a constant-time comparison. Reject anything whose timestamp is more than a few minutes old, so a captured request cannot be replayed at you.
import { createHmac, timingSafeEqual } from 'node:crypto';
function verify(rawBody, headers, secret) {
const ts = Number(headers['x-proweather-timestamp']);
if (!Number.isFinite(ts) || Math.abs(Date.now() / 1000 - ts) > 300) return false;
const expected = `sha256=${createHmac('sha256', secret)
.update(`${ts}.${rawBody}`)
.digest('hex')}`;
const a = Buffer.from(expected);
const b = Buffer.from(headers['x-proweather-signature'] ?? '');
return a.length === b.length && timingSafeEqual(a, b);
}The signing secret is generated for you and shown under Alerts → Webhook. Changing the URL keeps the same secret, so a receiver that already verifies signatures does not break.
Delivery rules
- The endpoint must be HTTPS and cannot point at a private network address.
- Redirects are not followed.
- We wait 6 seconds for a response.
- There is no retry queue: a failed delivery leaves the alert unlatched, so the next refresh (about 5 minutes) tries again while the condition still holds. A receiver that was briefly down misses nothing that is still true.
Use Send test under Alerts → Webhook to exercise the receiver; the
test request is signed exactly like a real one, with
X-ProWeather-Event: alert.test.
Next steps
- Alerts & warnings: creating the alerts that call this
- Public API & RSS feed: reading your conditions instead of being called
- Troubleshooting if deliveries fail
Alerts & warnings
Show official weather warnings on your site, and get an email or webhook when your station crosses a threshold, moves too fast, or something happens.
Use a custom domain
Serve your Pro Weather site from a domain you own, like weather.yourclub.org: add one CNAME record and HTTPS is issued and renewed for you. A Pro feature.
