Monitoring

Receive signed webhooks

Webhooks deliver incident and monitoring events to your own HTTPS endpoint. Every generic webhook can be verified before your application accepts it.

Last updated
August 1, 2026
Reading time
9 minutes

Create a webhook channel

  1. 1

    Prepare a public HTTPS endpoint

    Use a valid certificate on port 443. Private, loopback, reserved, and unsafe destinations are rejected.

  2. 2

    Add the channel

    From Alerting, choose Webhook, enter the endpoint, choose the message language, and save.

  3. 3

    Store the signing secret

    The secret is shown when the channel is created. Put it in your secret manager before leaving the page.

  4. 4

    Send a test

    Use the channel test and confirm that your endpoint verifies the signature and returns a successful response.

Request headers

HeaderMeaning
X-Flux-Event The event type, such as an incident or test event.
X-Flux-Delivery A unique delivery identifier for deduplication and logging.
X-Flux-Timestamp Unix timestamp used in the signed value.
X-Flux-Signature Lowercase hexadecimal HMAC-SHA256 signature.
Content-Type The payload media type; generic webhooks use JSON.

Verify a signature

Read the timestamp and signature headers, keep the raw body bytes, and compute HMAC-SHA256 with your channel secret over timestamp + "." + raw body. Compare signatures with a timing-safe function.

Reject missing or malformed headers. Also reject timestamps outside the replay window your application chooses; five minutes is a practical starting point for most integrations.

PHP verification examplePHP
<?php
$timestamp = $_SERVER['HTTP_X_FLUX_TIMESTAMP'] ?? '';
$received = $_SERVER['HTTP_X_FLUX_SIGNATURE'] ?? '';
$body = file_get_contents('php://input');
$secret = getenv('FLUX_WEBHOOK_SECRET');

if (!ctype_digit($timestamp) || abs(time() - (int) $timestamp) > 300) {
    http_response_code(401);
    exit;
}

$expected = hash_hmac('sha256', $timestamp.'.'.$body, $secret);
if (!hash_equals($expected, $received)) {
    http_response_code(401);
    exit;
}

$event = json_decode($body, true, flags: JSON_THROW_ON_ERROR);
http_response_code(204);

Acknowledge deliveries safely

Return a 2xx response only after the event is safely accepted. If processing takes longer than a few seconds, validate and enqueue the event, then respond. The delivery request has a limited timeout and response size.

Use X-Flux-Delivery as an idempotency key. If the same delivery arrives again, acknowledge it without applying the business action twice. Redirect responses are not followed.

Retries and failures

Network failures, timeouts, HTTP 408, 409, 425, 429, and server errors can be retried. The service attempts delivery up to five times with increasing delays of approximately 1, 5, 15, and 30 minutes. Other client errors are treated as final because repeating the same request would not normally fix them.

After the final failed attempt, the delivery is marked for review in the dashboard. Return a stable 2xx response for accepted duplicates and use 429 with an appropriate server policy when you genuinely need backpressure.

Endpoint security checklist

  • Accept only HTTPS requests on the intended path and method.
  • Verify timestamp and signature before parsing or acting on the body.
  • Use a timing-safe comparison and a replay window.
  • Deduplicate with X-Flux-Delivery.
  • Keep the endpoint fast; queue longer work.
  • Rotate the channel if its secret may have been exposed.
  • Restrict payload logging and monitor repeated verification failures.

Configure a signed channel.

Create a webhook from Alerting, save its secret safely, and use the test delivery before enabling it for incidents.

Open alerting