Create a webhook channel
- 1
Prepare a public HTTPS endpoint
Use a valid certificate on port 443. Private, loopback, reserved, and unsafe destinations are rejected.
- 2
Add the channel
From Alerting, choose Webhook, enter the endpoint, choose the message language, and save.
- 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
Send a test
Use the channel test and confirm that your endpoint verifies the signature and returns a successful response.
Request headers
| Header | Meaning |
|---|---|
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
$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.