Alerts
Alert channels
Email, Slack, Discord and signed webhooks, including how to verify a webhook signature.
Email, Slack, Discord, PagerDuty and signed webhooks are all included. Add channels under Channels and use Send test to check delivery.
Severity
Every alert has a severity, so the loud channels only fire when it matters:
| Severity | Alerts |
|---|---|
| Critical | Spend crosses 100% of a budget. A hard cap fired, failed, or ran as a dry run because your plan lacks hard caps. A cap restore failed. |
| Warning | Spend crosses 80%. Usage spike. Cloudflare rejected a token or polling keeps failing. A dry-run cap you chose ran. A cap was restored. |
| Info | Spend crosses 50%. The month-end forecast crosses 100%. |
Slack and Discord messages are labelled [CRITICAL], [WARNING] or [INFO], and Discord embeds are coloured to match. Webhook bodies carry a top-level severity field.
Minimum severity
Each Slack, Discord, PagerDuty or webhook channel has a minimum severity and only receives alerts at or above it. Point a pager at Critical so it wakes someone only for a breach or a cap, and leave a team Slack channel on Info to see everything. Change it on the channel row at any time; alerts already queued for a channel are dropped if they fall below its new minimum.
Alert email to org owners and admins is not filtered by severity.
PagerDuty
SignalFlare sends alerts to PagerDuty through the Events API v2.
- In PagerDuty, open the service that should page, go to Integrations, and add an Events API v2 integration.
- Copy its Integration Key (also called the routing key).
- In SignalFlare, add a channel of type PagerDuty, paste the key, and keep the minimum severity at Critical.
- Press Test critical alert on the Channels page and check that your phone rings.
The key is stored encrypted and only its last four characters are ever shown again. Each alert’s PagerDuty severity matches its SignalFlare severity. Repeats for the same budget, alert type and month share a dedup key, so they collapse into one incident instead of paging again. When a hard cap is restored, SignalFlare resolves the incident it opened. Test alerts share one dedup key per channel, so resolve the test incident in PagerDuty once you have seen it.
Spend in a PagerDuty incident is an estimate from sampled analytics. It is an early warning, not your invoice.
Test alerts
Send test on a channel delivers a clearly labelled TEST alert at that channel’s minimum severity, through the same delivery path real alerts use, and shows whether it arrived.
Test critical alert at the top of the Channels page sends a TEST critical alert to every active channel that receives critical alerts and lists the result for each one. Use it after setting up a pager to check that a real breach would reach you. Test alerts use sample numbers and are rate limited to a few per minute.
Slack and Discord
Create an incoming webhook in Slack or Discord and paste its URL. Messages name the account, the budget, the estimated spend and what happened.
Webhooks
We POST JSON to your URL:
{
"type": "signalflare.alert",
"severity": "critical",
"test": false,
"alert": { "kind": "threshold", "severity": "critical", "message": "…", "estimate": true },
"sentAt": 1760550120
}
Test alerts arrive with "type": "signalflare.alert.test" and "test": true.
If you set a secret, each request carries X-SignalFlare-Signature: the hex HMAC-SHA256 of the raw request body, keyed with your secret. Verify it before trusting the payload:
async function isValidSignature(secret: string, body: string, signature: string) {
const enc = new TextEncoder();
const key = await crypto.subtle.importKey(
'raw', enc.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'],
);
const mac = new Uint8Array(await crypto.subtle.sign('HMAC', key, enc.encode(body)));
const expected = [...mac].map((b) => b.toString(16).padStart(2, '0')).join('');
if (expected.length !== signature.length) return false;
let diff = 0;
for (let i = 0; i < expected.length; i++) diff |= expected.charCodeAt(i) ^ signature.charCodeAt(i);
return diff === 0;
}
Respond with any 2xx. Failed deliveries are retried a few times and then recorded in the alert history.
Unsubscribing
Every alert email has a one-click unsubscribe link that stops email for that address without touching your other channels.