WPOrchestrix / Documentation

Webhooks

Webhooks deliver real-time event notifications to your application via HTTP POST requests. Each delivery is HMAC-signed for verification.

Setup

  1. Navigate to Settings → Webhooks or visit your webhook endpoints
  2. Click New Webhook Endpoint
  3. Enter your endpoint URL (must be HTTPS in production)
  4. Select the events you want to subscribe to
  5. Save — a signing secret will be generated automatically

Events

EventDescription
site.down A monitored site is unreachable or returning errors
site.recovered A previously down site is back online
site.connected A new site has been connected and verified
site.disconnected A site's connection has been lost
security.vulnerability_found A new vulnerability has been detected
security.scan_completed A security scan has finished
performance.degraded Site performance has dropped below thresholds
performance.check_completed A performance check has finished
dns.changed DNS records for a site have changed
upgrade.started An upgrade pipeline has started running
upgrade.completed An upgrade pipeline has completed successfully
upgrade.failed An upgrade pipeline has failed
upgrade.rolled_back An upgrade has been rolled back
snapshot.created A new site snapshot has been created
snapshot.expired A snapshot has expired and been cleaned up

Payload Format

All webhook deliveries are JSON POST requests with the following structure:

{
  "event": "site.down",
  "timestamp": "2026-03-17T12:00:00Z",
  "site": {
    "id": "site_abc123",
    "name": "My Site",
    "url": "https://example.com"
  },
  "data": {
    // Event-specific data
  }
}

Signature Verification

Every webhook includes an X-WPSentinel-Signature header containing an HMAC-SHA256 signature of the request body. Always verify this signature before processing the payload.

Ruby

require "openssl"

def verify_webhook(payload_body, signature_header, secret)
  expected = OpenSSL::HMAC.hexdigest("SHA256", secret, payload_body)
  Rack::Utils.secure_compare(expected, signature_header)
end

# In your controller:
payload = request.body.read
signature = request.headers["X-WPSentinel-Signature"]
secret = ENV["WPSENTINEL_WEBHOOK_SECRET"]

unless verify_webhook(payload, signature, secret)
  head :unauthorized
  return
end

event = JSON.parse(payload)

Python

import hmac
import hashlib
import json

def verify_webhook(payload_body, signature, secret):
    expected = hmac.new(
        secret.encode(),
        payload_body.encode(),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

# In your Flask/Django handler:
signature = request.headers.get("X-WPSentinel-Signature")
if not verify_webhook(request.data, signature, WEBHOOK_SECRET):
    abort(401)

JavaScript (Node.js)

const crypto = require("crypto");

function verifyWebhook(payloadBody, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(payloadBody)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

// In your Express handler:
const signature = req.headers["x-wpsentinel-signature"];
if (!verifyWebhook(req.rawBody, signature, process.env.WEBHOOK_SECRET)) {
  return res.status(401).send("Invalid signature");
}

Retry Policy

If your endpoint returns a non-2xx status code, WPSentinel will retry the delivery. Failed deliveries can be viewed in the webhook endpoint's delivery history.

Best Practices

  • Always verify signatures before processing webhooks
  • Return 200 quickly and process the event asynchronously
  • Handle duplicate deliveries — use the event timestamp for idempotency
  • Use HTTPS endpoints to protect the payload in transit