Documentation

Webhooks

Webhook delivery, typical uses and what to watch out for when configuring them.

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

  1. In Slack: Apps → "Incoming WebHooks" → "Add to Slack"
  2. Choose a channel → copy the webhook URL
  3. Enter the URL under Account → Notifications → alert webhook URL

Setting up Teams

  1. In Teams: channel → "..." → Connectors → "Incoming Webhook"
  2. Give it a name → copy the URL
  3. 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.

Further reading