Agent skill
TriNet Zenefits Webhooks Skill
Receive and verify TriNet Zenefits webhooks. Use when setting up Zenefits partner-app webhook handlers, debugging the `signature` header HMAC-SHA256 verification, or handling events like people.did_create, people.did_change, employments.did_start, employments.did_terminate, and flow.did_complete.hiring.
Install this skill
npx skills add hookdeck/webhook-skills --skill zenefits-webhooks
When to Use This Skill
- How do I receive TriNet Zenefits webhooks?
- How do I verify the
signatureheader on a Zenefits webhook? - Why is my Zenefits webhook signature verification failing?
- Which secret signs Zenefits webhooks: the OAuth client secret or the webhook shared secret?
- How do I handle
people.did_create,employments.did_start,employments.did_, orterminate flow.did_complete.hiringevents? - How do I run Zenefits webhooks through Hookdeck?
Verification (core)
Zenefits sends a header literally named signature containing the hex HMAC-SHA256 of the raw request body, keyed with your application's webhook shared secret (used as a raw string). This is not the OAuth client secret. There is no timestamp and no official SDK, so verification is manual.
Node:
const crypto = require('crypto');
function verifyZenefitsSignature(rawBody, signatureHeader, secret) {
if (typeof signatureHeader !== 'string' || !secret) return false;
// Buffer.from(x, 'hex') silently truncates invalid hex: check the format first
if (!/^[0-9a-f]{64}$/i.test(signatureHeader)) return false;
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest();
return crypto.timingSafeEqual(Buffer.from(signatureHeader, 'hex'), expected);
}
Python:
import hashlib, hmac
def verify_zenefits_signature(raw_body: bytes, signature_header: str, secret: str) -> bool:
if not signature_header or not secret:
return False
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
# Compare bytes so a non-ASCII header returns False instead of raising
return hmac.compare_digest(signature_header.lower().encode(), expected.encode())
Example from the Zenefits docs (used in the tests): secret lDVtBQnoRcqYv4fUeVD0oyzgsKWHGtqhatjBX5wXRFQzkVUCzBA571E4qUxvR5LE and body {"test":"valid payload"} give signature 219a08ea32f319931dc849badc076323f40367aad859ddba4de82e33135fad31.
In Express, read the raw body with
express.raw({ type: '*/*' })so any content type verifies.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Common Event Types
The event name is the type field in the JSON body (<object>.<action>[.<subtype>]); it is not sent in a header. data matches the REST API shape for that object.
| Event | Description |
|---|---|
companies.did_create / companies.did_change | A company object is created or changes |
people.did_create | A new person is created |
people.did_change | A person object changes |
employments.did_start | A person's first day of work (fires on hire_date) |
employments.did_ | A person's last day of work (fires on termination_date) |
flow.did_complete.hiring | An admin completes a hiring flow for a person |
Many more exist (departments.*, locations.*, vacation_requests.*, time_durations.*, custom_field_values.*, and others). See references/overview.md.
Environment Variables
ZENEFITS_WEBHOOK_SECRET=your_webhook_shared_secret
Setup (Zenefits and Hookdeck)
Use your app's webhook shared secret, not its OAuth client secret. Zenefits generates the shared secret for your application and signs every webhook with it. If you receive webhooks through Hookdeck, paste the same webhook shared secret into the Zenefits source's verification settings. Webhook URLs must be HTTPS and return a 2xx quickly; Zenefits retries failures for up to 1 hour and may deliver a message more than once. See references/setup.md.
Local Development
npx hookdeck-cli listen 3000 zenefits --path /webhooks/zenefits
No account required. The CLI creates a guest account on first run and provides a local tunnel plus a web UI for inspecting requests. Use port 8000 for FastAPI.
Reference Materials
- references/overview.md - What Zenefits webhooks are, event types, payload structure, retries
- references/setup.md - Secret, endpoint requirements, Hookdeck setup
- references/verification.md - Signature details and gotchas