Seal
SDK reference

verifyWebhook

Verify a signed decision webhook and get back a typed, validated event.

Seal delivers a signed webhook when an approval settles. verifyWebhook() checks the HMAC signature and timestamp, parses the body, and returns a typed WebhookEvent. It throws WebhookVerificationError on any failure — a bad signature, a stale timestamp, malformed JSON, or an unexpected shape.

import { verifyWebhook, WebhookVerificationError } from "@seal-dev/sdk";

Signature

verifyWebhook(
  rawBody: string,
  headers: WebhookHeaders,
  secret: string,
  options?: { toleranceSeconds?: number },
): WebhookEvent
  • rawBody — the exact bytes of the request body. Do not re-serialize a parsed object; the signature is computed over the raw payload.
  • headers — a Headers object, a plain header record, or anything with get(name).
  • secret — your endpoint's signing secret.
  • toleranceSeconds — allowed clock skew; defaults to 300 (5 minutes).

Example — Express

import express from "express";
import { verifyWebhook, WebhookVerificationError } from "@seal-dev/sdk";

const app = express();

app.post("/webhooks/seal", express.raw({ type: "application/json" }), (req, res) => {
  try {
    const event = verifyWebhook(
      req.body.toString("utf8"),
      req.headers,
      process.env.WEBHOOK_SECRET!,
    );

    switch (event.type) {
      case "approval.approved":
        return void res.sendStatus(200);
      case "approval.rejected":
        console.log("rejected:", event.data.feedback);
        return void res.sendStatus(200);
      default:
        return void res.sendStatus(200);
    }
  } catch (err) {
    if (err instanceof WebhookVerificationError) return void res.sendStatus(400);
    throw err;
  }
});

The returned event is a validated WebhookEvent. See the webhooks API for the header names and signature scheme, and error types for WebhookVerificationError.

On this page