Back to Developers & API

How do webhooks work?

Register an endpoint and pick events; ASHR sends a signed POST when they happen. Verify the X-Demystify-Signature HMAC with the secret shown once, and reject stale or unsigned requests.

~3 min read · For admin · Updated 4 Aug 2026

Quick answer

Register an endpoint in Admin → Settings → Developer & API, choose the events you want, and ASHR sends a signed POST when they happen. Verify the X-Demystify-Signature header with the secret (shown once) so you can trust the payload.

The payload

{ "event": "leave.created", "created": 1725448800, "data": { "id": "…", "employee_id": "…" } }

Headers: X-Demystify-Event: leave.created and X-Demystify-Signature: t=1725448800,v1=<hex>.

Verify the signature

The signed string is `${t}.${rawBody}` and the signature is HMAC-SHA256 of it with your endpoint secret. Recompute and compare in constant time; reject if it doesn't match or t is more than a few minutes old.

import crypto from 'node:crypto'

function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')))
  const expected = crypto.createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex')
  const ok = crypto.timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(parts.v1, 'hex'))
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300
  return ok && fresh
}

Return a 2xx fast and process asynchronously; treat delivery as at-least-once, so make your handler idempotent.

Frequently asked questions

Which events can I subscribe to?
Today — leave.created, leave.approved, leave.rejected and leave.cancelled. Pick specific events or subscribe to everything.
How do I know a webhook really came from ASHR?
Every request carries X-Demystify-Signature — an HMAC-SHA256 of "<timestamp>.<rawBody>" using your endpoint secret. Recompute it and compare; reject if it doesn't match or the timestamp is too old.
What if my endpoint is down?
Delivery is best-effort and each attempt is recorded. Build your handler to be idempotent (the same event may arrive more than once) and return a 2xx quickly.