turbometrics can send an HTTP POST to a URL of your choice when an alert occurs. This works with Slack, Teams, Discord, Zapier, Make and every other tool that supports incoming webhooks.
Setting up Slack
- In Slack: Apps → "Incoming WebHooks" → "Add to Slack"
- Choose a channel → copy the webhook URL
- Enter the URL under Account → Notifications → alert webhook URL
Setting up Teams
- In Teams: channel → "..." → Connectors → "Incoming Webhook"
- Give it a name → copy the URL
- Enter the URL under Account → Notifications
Available events
| Event | When |
|---|---|
alert.triggered |
A scan alert is triggered (critical or warning) |
alert.resolved |
A scan alert resolves |
scan.completed |
A scan has completed successfully |
rum.alert.triggered |
A live data alert is triggered (p75 exceeds the threshold) |
rum.alert.resolved |
A live data alert resolves (p75 falls below the threshold) |
You can switch each event that is sent by webhook on or off individually under Account → Notifications.
Payload structure
alert.triggered / alert.resolved
turbometrics sends a JSON object for every alert:
{
"event": "alert.triggered",
"alert_id": 42,
"type": "score_drop",
"severity": "critical",
"title": "Score drop: example.com",
"message": "Score fell to 54 (previously: 78)",
"target_url": "https://example.com/",
"host": "example.com",
"region": "eu-central",
"scan_public_id": "01KN...",
"created_at": "2026-04-01T10:00:00+00:00"
}
For alert.resolved, the payload additionally contains "event": "alert.resolved" and "resolved_at".
scan.completed
{
"event": "scan.completed",
"url": "https://example.com/",
"score": 74,
"score_speed": 29,
"score_images": 73,
"score_caching": 96,
"score_tech": 90,
"lcp_ms": 2800,
"ttfb_ms": 141,
"cls": 0.001,
"tbt_ms": 1635,
"scan_url": "https://turbometrics.io/scan/01KN...",
"scanned_at": "2026-04-03T20:45:00+00:00"
}
Typical use case: forwarding scan results automatically into Google Sheets, Slack or Notion.
rum.alert.triggered / rum.alert.resolved
For live data (RUM) alerts, the following JSON object is sent:
{
"event": "rum.alert.triggered",
"alert_name": "LCP zu hoch",
"domain": "example.com",
"metric": "LCP",
"p75": 3200.0,
"threshold": 2500.0,
"unit": "ms",
"samples": 48,
"window_minutes": 60,
"triggered_at": "2026-04-05T10:00:00+00:00",
"rum_dashboard_url": "https://turbometrics.io/rum/1"
}
For rum.alert.resolved, the payload contains "resolved_at" instead of "triggered_at".
Webhook authentication
So that your endpoint can check whether an incoming request really comes from turbometrics, you can store an authentication header under Profile → Notifications.
turbometrics adds this header automatically to every outgoing webhook request — for all events (alerts, recovery, scan completed).
Configuration:
| Field | Description |
|---|---|
| Header name | Name of the HTTP header, e.g. X-Webhook-Secret or Authorization |
| Header value | The value your endpoint expects |
Example — the request that is sent:
POST https://hooks.your-domain.com/alert
Content-Type: application/json
X-Webhook-Secret: your-secret-token
{ "event": "alert.triggered", ... }
Checking it on the receiving end (PHP example):
$secret = $_SERVER['HTTP_X_WEBHOOK_SECRET'] ?? '';
if (!hash_equals('your-secret-token', $secret)) {
http_response_code(401);
exit;
}
The header value is stored encrypted and leaves turbometrics only as an HTTP header sent to the webhook URL you configured.
Note: Leave the header name blank → the auth header is removed. Leave the value field blank → the existing value is kept unchanged.
Retry behaviour
If a webhook delivery fails (no 2xx status code, or a timeout), turbometrics repeats the delivery automatically. Failed deliveries are logged and can be viewed under Profile > Notifications > Alert history. The webhook_attempts counter shows how often delivery was attempted. The webhook_response_code and webhook_last_error fields help with troubleshooting.
When they are sent
- Scan alerts (
alert.triggered/alert.resolved): webhooks are sent immediately when the alert is triggered or resolves. - Live data alerts (
rum.alert.triggered/rum.alert.resolved): webhooks are sent when the CheckRumAlerts command detects that a threshold has been exceeded. It runs every 5 minutes. - Scan completed (
scan.completed): the webhook is sent as soon as scan processing has finished.
Availability
Webhooks are available from the Pro plan onward.