Webhooks - Custom Event Handling
Real-time infrastructure monitoring for DevOps
Guide for integrating custom logic.
Sidebar
Navigate the webhook integration workflow.
1. Endpoint Configuration
Register your HTTPS listener in the StatusPulse dashboard under Integrations > Webhooks. Ensure TLS 1.2+ and valid certificates.
2. Payload Structure
Understand the JSON schema, field types, and event types (status_change, latency_spike, maintenance_window).
3. Security & Signing
Implement HMAC-SHA256 verification, timestamp drift checks, and secret rotation procedures.
Payload Example
Every webhook POST includes a standardized JSON body. StatusPulse sends events for status_change, latency_spike, and certificate_expiry.
Standard Event Schema
{
"event_id": "evt_9f82b1c4d5e6",
"timestamp": "2024-05-14T09:32:11Z",
"event_type": "status_change",
"check_id": "chk_us_east_1_api",
"endpoint": "https://api.example.com/v2/health",
"previous_status": "operational",
"current_status": "degraded",
"response_time_ms": 1420,
"region": "us-east-1",
"error_code": 503,
"retry_count": 0
}
Security
Protect your ingestion endpoint by verifying the X-StatusPulse-Signature header. We sign the raw request body using HMAC-SHA256 with your webhook secret.
Node.js Handler
const crypto = require('crypto');
const express = require('express');
const app = express();
app.use(express.raw({ type: 'application/json' }));
const WEBHOOK_SECRET = 'whsec_a8f3k29d4m1p7q';
app.post('/webhook/statuspulse', (req, res) => {
const sigHeader = req.headers['x-statuspulse-signature'];
const timestamp = req.headers['x-statuspulse-timestamp'];
const payload = req.body.toString();
const expectedSig = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(`${timestamp}.${payload}`)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(sigHeader), Buffer.from(expectedSig))) {
return res.status(401).send('Invalid signature');
}
res.status(200).send('OK');
});
Go Handler
package main
import (
"crypto/hmac"
"crypto/sha256"
"io"
"net/http"
)
const secret = "whsec_a8f3k29d4m1p7q"
func webhookHandler(w http.ResponseWriter, r *http.Request) {
sigHeader := r.Header.Get("X-StatusPulse-Signature")
tsHeader := r.Header.Get("X-StatusPulse-Timestamp")
body, _ := io.ReadAll(r.Body)
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(tsHeader + "." + string(body)))
expectedSig := mac.Sum(nil)
if !hmac.Equal([]byte(sigHeader), expectedSig) {
http.Error(w, "Invalid signature", http.StatusUnauthorized)
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
}