Agent skill

Vanta Webhooks Skill

Receive and verify Vanta webhooks (delivered via Svix). Use when setting up Vanta webhook handlers, debugging svix-signature verification, or handling compliance events like v1.questionnaire.status-changed, v1.vendor.decision.created, v1.trust-center.access-request.approved, and v1.evidence.status-changed.

Install this skill

npx skills add hookdeck/webhook-skills --skill vanta-webhooks


Vanta (compliance automation) sends webhooks through Svix. Every delivery is an HTTP POST with a JSON body and three signature headers: svix-id, svix-timestamp, and svix-signature.

When to Use This Skill

  • How do I receive Vanta webhooks?
  • How do I verify Vanta webhook signatures (svix-signature)?
  • How do I handle v1.questionnaire.status-changed or v1.vendor.decision.created events?
  • How do I react to Trust Center access requests (v1.trust-center.access-request.received)?
  • Why is my Vanta webhook signature verification failing?

Verification (core)

Signed content is {svix-id}.{svix-timestamp}.{raw body}. Vanta signs it with HMAC-SHA256 using the base64-decoded secret (the part after whsec_), base64-encodes the result, and sends one or more space-delimited v1,<signature> entries. Vanta recommends the official svix library, which also enforces the 5-minute timestamp window and compares signatures in constant time.

import { Webhook } from 'svix'; // svix 2.x is ESM-only

const wh = new Webhook(process.env.VANTA_WEBHOOK_SECRET); // "whsec_..."
// rawBody: the raw Buffer/string, never re-serialized JSON
wh.verify(rawBody, {
  'svix-id': req.headers['svix-id'],
  'svix-timestamp': req.headers['svix-timestamp'],
  'svix-signature': req.headers['svix-signature'],
}); // throws WebhookVerificationError on a bad signature or stale timestamp
const body = JSON.parse(rawBody.toString('utf8')); // parse only after verify passes
from svix.webhooks import Webhook, WebhookVerificationError

wh = Webhook(os.environ["VANTA_WEBHOOK_SECRET"])
wh.verify(raw_body, {"svix-id": msg_id, "svix-timestamp": ts, "svix-signature": sig})

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Common Event Types

Event types follow v1.<domain>.<entity>.<action>. The event reference documents each event's payload (for example {"questionnaire": {"id": "123", "status": "COMPLETE"}}); it does not document a type field in the body. The examples read type from an envelope if one is present and otherwise fall back to the payload's top-level key.

EventTriggered When
v1.questionnaire.status-changedA questionnaire's status changes (e.g. COMPLETE, APPROVED)
v1.questionnaire.export-completedA requested questionnaire export is ready
v1.vendor.decision.createdA vendor risk decision is recorded
v1.trust-center.access-request.receivedSomeone requests access to your Trust Center
v1.trust-center.access-request.approvedA Trust Center access request is approved
v1.evidence.status-changedAudit evidence status changes (Audit Partner accounts only)

See references/overview.md for all 25 events.

Environment Variables

# Settings → Webhooks → your endpoint → Signing Secret (starts with whsec_)
VANTA_WEBHOOK_SECRET=whsec_xxxxx

Local Development

# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 vanta --path /webhooks/vanta

Register the tunnel URL in Vanta under Settings → Webhooks → Add Endpoint, then use the endpoint's Testing tab to Send Example events.

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Oct 28, 2026

View on GitHub →