Completion webhook
When an interview ends, ZenHire's interview backend reports the outcome to the platform via a completion webhook. The platform marks the session terminal and, on a completed session, deducts credits.
This is an internal server-to-server contract. Unlike CV DeepMatch's outbound webhook (which calls your endpoint), the interview completion webhook is called by the interview backend on the platform, not on you. You do not register a URL, you do not receive this call, and you are never given its signing secret. It is documented here so you understand exactly how and when a session reaches
completed/failedand when credits are charged.
When it fires
Step ⑧ of the verify-and-fetch lifecycle: the interview backend POSTs to the platform when the live conversation ends. The platform then:
- marks the session
completed(orfailed), - on
completed, deducts credits at the per-minute interview rate (rounded up to the next minute), - on
failed, charges nothing.
Delivery is idempotent — a duplicate delivery for an already-terminal
session is a safe no-op (returns the existing status with charged: 0). This
means a retried webhook never double-charges.
Signature
The webhook is HMAC-signed, not session-authenticated. It reuses the same scheme as ZenHire's outbound CV DeepMatch webhooks:
X-Interview-Signature: t=<unix-ts>,v1=<hex hmac-sha256 of "<ts>.<rawBody>">
X-Interview-Signature-Timestamp: <unix-ts>
The HMAC input is "<timestamp>.<raw-request-body>" over the raw bytes, and
the timestamp bounds replay (a 5-minute tolerance). The signing secret is held
only by the platform and the interview backend.
Payload
{
"status": "completed",
"duration_sec": 742,
"recording_s3_key": "recordings/ses_a1b2c3d4e5f6/audio.wav",
"transcript_s3_key": "transcripts/ses_a1b2c3d4e5f6/transcript.json",
"interview_svc_session_id": "ses_a1b2c3d4e5f6",
"delivery_id": "wh_2026_05_29_001"
}
| Field | Notes |
|---|---|
status | completed or failed. |
duration_sec | Required on completed. Billed rounded up to the next minute. |
recording_s3_key / transcript_s3_key | Storage references, surfaced to you via the Results endpoints. |
interview_svc_session_id | The interview backend's own session id. |
delivery_id | Optional idempotency id (logged). |
What you do instead
You don't consume this webhook. To know when a session finishes, poll the session:
curl "https://platform.zenhire.ai/api/v1/interview/sessions/{sessionId}" \
-H "X-API-Key: zh_api_YOUR_KEY"
Watch for status reaching completed (or failed), then fetch results.