Agent skill

Ashby Webhooks Skill

Receive and verify Ashby webhooks. Use when setting up Ashby webhook handlers, debugging Ashby-Signature verification, or handling recruiting events like applicationSubmit, candidateHire, candidateStageChange, or interviewScheduleCreate.

Install this skill

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


When to Use This Skill

  • How do I receive Ashby webhooks?
  • How do I verify the Ashby-Signature header?
  • How do I handle applicationSubmit, candidateHire, or interviewScheduleCreate events?
  • Why is my Ashby webhook signature verification failing?

Verification (core)

Ashby signs the raw request body with HMAC-SHA256 keyed on your per-webhook secret token and sends the digest in the Ashby-Signature header formatted as sha256=<hex>. There is no official SDK, so verify manually: compute the HMAC over the raw body (before JSON parsing) and compare the hex digest timing-safe.

The event name is in the body, not a header — every payload is { "action": "<eventName>", "data": {...} }.

Node:

const crypto = require('crypto');

function verifyAshbyWebhook(rawBody, signatureHeader, secret) {
  const [algo, sig] = (signatureHeader || '').split('=');
  if (algo !== 'sha256' || !sig) return false;
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  try {
    return crypto.timingSafeEqual(Buffer.from(sig, 'hex'), Buffer.from(expected, 'hex'));
  } catch {
    return false;
  }
}

Python:

import hmac, hashlib

def verify_ashby_webhook(raw_body: bytes, signature_header: str, secret: str) -> bool:
    algo, _, sig = (signature_header or "").partition("=")
    if algo != "sha256" or not sig:
        return False
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(sig, expected)

For complete handlers with route wiring, event dispatch, and tests, see:

Common Event Types

The action field carries the event name (camelCase, no dot notation).

Event (action)Triggered When
pingTest event sent when a webhook is created or edited
applicationSubmitA candidate submits an application
applicationUpdateAn application changes (stage, status, fields)
candidateHireA candidate is marked hired
candidateStageChangeA candidate moves to a new interview stage
interviewScheduleCreateAn interview schedule is created
offerCreateAn offer is created

Fan-out: some events trigger others. For example, candidateHire also fires applicationUpdate and candidateStageChange. Make handlers idempotent.

For the full event reference, see Ashby webhook docs.

Important Headers

HeaderDescription
Ashby-SignatureHMAC SHA-256 signature as sha256=<hex> — use this to verify
Ashby-Webhook (User-Agent)Identifies Ashby requests. Do not use for auth

Environment Variables

ASHBY_WEBHOOK_SECRET=your_webhook_secret   # Secret token set per-webhook in Ashby

Local Development

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

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Aug 4, 2026

View on GitHub →