Create a webhook notifier

To configure a webhook notifier, enter a URL that specifies the endpoint to send HTTP POST requests to. You can use variables in your notifiers.

To create a webhook notifier:

  1. In the navigation menu select Alerts> Notifiers.

  2. Click Create notifier.

  3. Enter a descriptive name for the notifier.

  4. Select Webhook as the type of notifier you want to create.

  5. In the URL field, enter a URL, which is called as a POST request. For example:

    https://webhook.site/3723e8cb-b1b4-4399-86b0-e37f36a2acc5
  6. Optional: Select Notify when resolved to send a resolved alert notification.

  7. Click Save.

Webhook notifier request body

The following example outlines the body for a POST request to a webhook. The request consists of one triggered alert called "test alert" that has several associated labels, such as component, instance, and job.

This example contains several notable sections:

  • commonLabels: Contains labels that are common across all alerts in a notification display. Each alerting series includes the full list of labels. Any static labels that you define also display under commonLabels.
  • groupLabels: Contains label values for the related signal display, in addition to a "severity" for the label.
  • fingerprint: A representation of an alerting series, expressed as a deterministic value based on the hash of the labels.
{
  "notifier": "test webhook",
  "status": "firing",
  "alerts": [
    {
      "status": "firing",
      "labels": {
        "alertname": "test alert",
        "component": "remote_write",
        "instance": "localhost:3030",
        "job": "collector_binary",
        "severity": "critical",
        "pod_name": "prom-74cbfb46c9-2ftk9"
      },
      "annotations": {
        "ruleid": "32bb3fbe-c10b-44bb-a4c0-3d053f4a08cd",
        "monitor_slug": "test-monitor",
        "notification_policy_slug": "test-policy"
      },
      "startsAt": "2020-05-19T13:57:21.68227886Z",
      "endsAt": "0001-01-01T00:00:00Z",
      "fingerprint": "7424223989b20025"
    }
  ],
  "groupLabels": {
    "alertname": "test alert",
    "severity": "critical"
  },
  "commonLabels": {
    "alertname": "test alert",
    "component": "remote_write",
    "instance": "localhost:3030",
    "job": "collector_binary",
    "severity": "critical",
    "pod_name": "prom-74cbfb46c9-2ftk9"
  },
  "commonAnnotations": {
    "ruleid": "32bb3fbe-c10b-44bb-a4c0-3d053f4a08cd",
    "monitor_slug": "test-monitor",
    "notification_policy_slug": "test-policy"
  },
  "version": "4"
}

Webhook Signatures

Chronosphere webhooks include cryptographic signatures to ensure the authenticity and integrity of webhook requests.

Headers

Every outbound webhook includes these security headers:

  • Chronosphere-Webhook-Timestamp: The Unix timestamp of the time the webhook request was constructed. Example value: 1754255354.

  • Chronosphere-Webhook-Signature-V1: At least one hex-encoded signature. More than one signature may be included, separated by commas, in the event of key rotation. Note this string will always contain at least one comma, even if there is only one signature. This ensures that clients are splitting the header value by commas. Example value (note trailing comma): 05908e247179fd822f2508907632cb1c57721691b688d72577a22dc46d183d21,.

Retrieving Your Signing Key

If you are a member of a team with the SysAdmin role, you can retrieve your signing key in the Observability Platform web app.

  1. Click your profile icon from the menu bar and select My Account.

  2. The Webhook Signing Key field displays your key, but its value is hidden. Click the reveal icon to reveal its value, and then click the copy icon to copy its value to your clipboard.

Signature Algorithm

Signatures are generated using the HMAC-SHA256 algorithm with the following process:

  1. Construct the payload:

    payload = "v1:" + timestamp + ":" + request_body
  2. Generate HMAC-SHA256:

    for i, key in active_signing_keys:
       signatures[i] = HMAC-SHA256(payload, key)
  3. Hex encode:

    header_value = join(hex_encode(signatures), ",") + ","

Verification Steps

To verify a Chronosphere webhook signature:

Step 1: Extract headers

  • Get the Chronosphere-Webhook-Timestamp header value. Ensure the timestamp is within some tolerance. Chronosphere recommends a tolerance of five to 15 minutes.
  • Get the Chronosphere-Webhook-Signature-V1 header value.
  • Fail if either header is missing.

Step 2: Read request body

  • Read the complete HTTP request body as bytes.
  • Preserve the exact bytes. Disable any automatic parsing or formatting in your HTTP client.

Step 3: Construct verification payload

  • Construct a verification payload using the following syntax:

    verification_payload = "v1:" + timestamp + ":" + request_body

Step 4: Generate expected signature

  • Use HMAC-SHA256 with your signing key.
  • Hex-encode the result (lowercase).

Step 5: Compare signatures

  • Split the signature header on commas.
  • Trim whitespace from each signature.
  • Skip empty values.
  • Use constant-time comparison for each signature.
  • Accept if any signature matches.

Code Sample

Click to view an example of signature verification in Go.
// VerifyChronosphereWebhook verifies the signature of a Chronosphere webhook request.
// It returns nil if the signature is valid, or an error if invalid or missing.
func VerifyChronosphereWebhook(r *http.Request, signingKey string) error {
	// Get the timestamp and signature from headers
	timestamp := r.Header.Get("Chronosphere-Webhook-Timestamp")
	signature := r.Header.Get("Chronosphere-Webhook-Signature-V1")
 
	if timestamp == "" {
		return errors.New("missing Chronosphere-Webhook-Timestamp header")
	}
	if signature == "" {
		return errors.New("missing Chronosphere-Webhook-Signature-V1 header")
	}
 
	// Convert timestamp string to unix timestamp and validate age
	timestampInt, err := strconv.ParseInt(timestamp, 10, 64)
	if err != nil {
		return fmt.Errorf("invalid timestamp format: %w", err)
	}
 
	webhookTime := time.Unix(timestampInt, 0)
	now := time.Now()
	const maxAge = 5 * time.Minute
 
	if now.Sub(webhookTime) > maxAge {
		return fmt.Errorf("webhook timestamp is too old: %v ago", now.Sub(webhookTime))
	}
 
	// Read the request body
	body, err := io.ReadAll(r.Body)
	if err != nil {
		return fmt.Errorf("failed to read request body: %w", err)
	}
 
	// Create the payload to sign: "v1" + ":" + timestamp + ":" + request_body
	payload := "v1:" + timestamp + ":" + string(body)
 
	// Create HMAC-SHA256 signature
	h := hmac.New(sha256.New, []byte(signingKey))
	h.Write([]byte(payload))
	expectedSignature := hex.EncodeToString(h.Sum(nil))
 
	// The signature header may contain multiple comma-separated values for rotation
	signatures := strings.SplitSeq(signature, ",")
 
	// Check if any of the provided signatures match using constant-time comparison
	for sig := range signatures {
		sig = strings.TrimSpace(sig)
		if sig == "" {
			continue // Skip empty splits
		}
		if hmac.Equal([]byte(sig), []byte(expectedSignature)) {
			return nil // Valid signature found
		}
	}
 
	return errors.New("no matching signature found")
}

Webhook IP addresses

Chronosphere has established a list of static IP addresses which serve outbound webhook notification traffic. Use these addresses in your company’s allowlist to restrict traffic and maintain security.

Chronosphere also provides a full list of IP addresses (opens in a new tab).

Chronosphere doesn’t offer a published CIDR range.

Chronosphere Observability Platform serves outbound webhook traffic for the following regions:

The following IP addresses serve traffic for the United States:

  • 104.198.2.151
  • 34.122.142.108
  • 34.122.149.117
  • 34.122.224.78
  • 34.127.109.43
  • 34.135.53.117
  • 34.145.80.163
  • 34.16.24.232
  • 34.168.147.207
  • 34.168.150.81
  • 34.171.52.135
  • 34.173.251.109
  • 34.28.62.245
  • 34.29.130.124
  • 34.29.185.167
  • 34.41.168.213
  • 34.70.121.15
  • 34.82.119.158
  • 34.82.143.37
  • 34.82.179.176
  • 34.82.243.234
  • 34.83.169.174
  • 34.83.7.178
  • 34.83.75.236
  • 35.188.223.136
  • 35.188.42.84
  • 35.197.55.241
  • 35.225.28.124
  • 35.227.141.247
  • 35.230.72.253
  • 35.233.215.68
  • 35.239.112.38

Last updated: 2025.03.31