Webhooks - Custom Event Handling

Real-time infrastructure monitoring for DevOps

Guide for integrating custom logic.

View Payload Specs Verify Signatures

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"))
}