Agent skill
Workable Webhooks Skill
Receive and verify Workable webhooks. Use when setting up Workable webhook handlers, debugging X-Workable-Signature verification, or handling recruiting events like candidate_created, candidate_moved, employee_created, employee_updated, or employee_published.
Install this skill
npx skills add hookdeck/webhook-skills --skill workable-webhooks
When to Use This Skill
- How do I receive Workable webhooks?
- How do I verify the
X-Workable-Signatureheader? - What key signs Workable webhooks (there is no webhook secret)?
- How do I handle
candidate_createdorcandidate_movedevents? - Why is my Workable webhook signature verification failing?
Verification (core)
Workable signs the raw request body with HMAC-SHA256 and sends the digest in X-Workable-Signature. The key is not a dedicated webhook secret: it is the account API token that created the subscription, or the OAuth application secret for OAuth apps, used as a plain string.
Workable's docs don't state the digest encoding. Lowercase hex is what the maintained n8n and Botpress integrations use, and what these examples use. If your deliveries never match, compare against the base64 digest too.
Node:
const crypto = require('crypto');
function verify(rawBody, signatureHeader, key) {
if (!signatureHeader) return false;
const expected = crypto.createHmac('sha256', key).update(rawBody).digest('hex');
try {
return crypto.timingSafeEqual(Buffer.from(signatureHeader.toLowerCase()), Buffer.from(expected));
} catch {
return false;
}
}
Python:
import hmac, hashlib
def verify(raw_body: bytes, signature_header: str, key: str) -> bool:
expected = hmac.new(key.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest((signature_header or "").lower().encode(), expected.encode())
Read the raw body regardless of content type (Express: express.raw({ type: '*/*' })). There is no timestamp header, so make handlers idempotent.
For complete handlers with route wiring, event dispatch, and tests, see:
Common Event Types
| Event | Description |
|---|---|
candidate_created | A candidate was added to a job |
candidate_moved | A candidate moved to another pipeline stage |
employee_created | An employee record was created |
employee_updated | An employee record was updated |
employee_published | An employee record was published |
Workable also documents candidate_deleted, job_deleted, onboarding_completed and timeoff_updated. See references/overview.md.
Important Headers
| Header | Description |
|---|---|
X-Workable-Signature | HMAC-SHA256 of the raw body (hex), keyed with the API token or OAuth app secret |
Environment Variables
WORKABLE_SIGNING_KEY=your_api_token_or_oauth_app_secret # The token that created the subscription
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 workable --path /webhooks/workable
Reference Materials
- references/overview.md - Workable webhook concepts and events
- references/setup.md - Creating a subscription
- references/verification.md - Signature verification details