DocsAPIs & ObservabilityWebhook Signatures & Payloads
HMACUpdated 2026-08-22

Webhook Signatures & Payloads

Verify HMAC-SHA256 signatures and process automated incident notification payloads.

When configuring custom Webhook channels, SteadyStack sends cryptographically signed HTTP POST requests to your endpoint.


Verifying Signatures

Every webhook delivery includes an X-SteadyStack-Signature header containing a computed HMAC-SHA256 signature using your channel's webhook secret.

Verification Example (Node.js / TypeScript)

TYPESCRIPT
import crypto from "node:crypto";

export function verifySteadyStackWebhook(
  rawBody: string,
  signatureHeader: string,
  secret: string
): boolean {
  const expectedSignature = crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signatureHeader),
    Buffer.from(expectedSignature)
  );
}

Verification Example (Go)

GO
package webhook

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
)

func VerifySignature(rawPayload []byte, signature string, secret string) bool {
	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write(rawPayload)
	expectedMAC := hex.EncodeToString(mac.Sum(nil))
	return hmac.Equal([]byte(signature), []byte(expectedMAC))
}

Webhook Payload Schema

JSON
{
  "event": "incident.triggered",
  "timestamp": "2026-08-22T21:00:00.000Z",
  "incident": {
    "id": "inc_9a8b7c6d5e",
    "status": "DOWN",
    "cause": "HTTP_STATUS_500",
    "severity": "CRITICAL",
    "runbook_url": "https://wiki.company.com/runbooks/api-500"
  },
  "monitor": {
    "id": "mon_123456",
    "name": "Production API Gateway",
    "url": "https://api.example.com/health",
    "type": "HTTP"
  },
  "quorum": {
    "total_regions": 7,
    "failing_regions": 6,
    "breakdown": {
      "wnam": { "status": 500, "latency_ms": 142 },
      "enam": { "status": 500, "latency_ms": 98 },
      "weur": { "status": 500, "latency_ms": 112 },
      "apac": { "status": 500, "latency_ms": 230 }
    }
  }
}