When ServerVisor fires a webhook, it sends an HTTP POST to whatever URL you configured. Without a signing secret, your endpoint has no way to know whether that request really came from ServerVisor. Anyone who discovers your URL could send fake payloads and trigger your automation. A signing secret fixes that. It lets your endpoint verify every delivery is genuine before doing anything with it.
Step 1: Generate a signing secret
A signing secret is a long random string that only you and ServerVisor know. You create it, give it to ServerVisor, and store it on your server. The two copies never need to meet in transit — they just both exist, privately, in each place. A quick way to generate a strong one:
openssl rand -hex 32Copy the output. You will paste it into ServerVisor in the next step and store it on your server in the step after. Do not lose it — if you regenerate a new one later, you will need to update it in both places at the same time, or deliveries will fail verification until you do.
Step 2: Add the secret to your webhook in ServerVisor
Go to Settings, then Integrations, then Webhooks. Open the endpoint you want to secure and paste your secret into the signing secret field. Save the endpoint. From that point on, every delivery ServerVisor makes to that URL will include a signature header computed from the payload.
Step 3: Store the secret on your server
Your endpoint needs access to the secret at request time. Store it as an environment variable rather than pasting it into source code. Secrets in source code end up in version control, deployment logs, and error reports — all places they should not be.
export SERVERVISOR_WEBHOOK_SECRET="your-secret-here"On a production server, set this in your web server config, a .env file outside the webroot, or your hosting platform's environment settings panel. The goal is that only your application process can read it.
Step 4: Verify the signature in your endpoint
When ServerVisor delivers a webhook, it runs a calculation on the raw request body using your secret and sends the result in an X-SV-Signature header. Your endpoint runs the same calculation on the body it received and compares the two results. A match means the payload is genuine and unchanged. A mismatch means something is wrong — reject it.
Here is a complete PHP handler that verifies the signature, then handles each event type:
<?php
$secret = getenv('SERVERVISOR_WEBHOOK_SECRET');
$payload = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_SV_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($expected, $sig)) {
http_response_code(401);
exit;
}
$event = json_decode($payload, true);
switch ($event['event']) {
case 'site_down':
$domain = $event['data']['domain'];
// your logic here
break;
case 'site_up':
$secs = $event['data']['duration_seconds'];
break;
case 'heartbeat_missed':
$name = $event['data']['name'];
break;
}
http_response_code(200);Once the signature check passes, everything below it can run with confidence. Your code is only processing payloads that ServerVisor actually sent.