Webhooks

Webhooks

Get an HTTPS POST the moment an interview starts, finishes or is scored.

Webhooks tell your system when something happens, so you do not have to poll. The most useful one is result.ready: the moment a result exists, Heizen posts it to you.

Set up an endpoint

  1. Add an HTTPS route to your server that accepts POST with a JSON body.
  2. Register it under Developers → Webhooks or with POST /v1/webhook_endpoints. Pick the event types you want.
  3. Store the signing secret (whsec_…) in an environment variable such as HEIZEN_WEBHOOK_SECRET.
  4. Verify the signature on every request.
  5. Reply with any 2xx status within 10 seconds.
  6. Send a test event from the dashboard to check it all works.

Test-mode and live-mode endpoints are separate. Each one receives events from its own mode only.

What a delivery looks like

POST /webhooks/heizen HTTP/1.1
Content-Type: application/json
User-Agent: Heizen-Webhooks/1.0
webhook-id: evt_7d0f…
webhook-timestamp: 1790000000
webhook-signature: v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=

{
  "id": "evt_7d0f…",
  "object": "event",
  "type": "result.ready",
  "api_version": "2026-10-01",
  "livemode": true,
  "created_at": "2026-10-01T09:42:11.000Z",
  "data": { "object": { "id": "res_…", "object": "result", "status": "ready" } }
}

data.object is the full resource at the time of the event, the same shape the API returns.

Handle events well

  • Reply fast. Return 2xx first and do slow work in a background job. Anything over 10 seconds counts as a failure.
  • Expect duplicates. Retries and replays reuse the event id in webhook-id. Record the ids you have processed and skip repeats.
  • Expect any order. A result.updated can arrive before the result.ready it follows if the first delivery was retried. Compare updated_at, or fetch the latest state from the API.
  • Ignore unknown types. New event types may appear; reply 2xx and move on.