Receive webhooks
Return to the full receiver flow and follow-up pattern.
Guide
Validate ChartHero webhook headers, timestamps, and HMAC signatures.
Verify webhook signatures before parsing trusted business fields or fetching clinical follow-up resources. The check proves the delivery was signed with the endpoint signing secret and that the timestamp is within the documented tolerance.
This page covers verification only. For the full receiver workflow, see Receive webhooks.
Signature verification does not use ChartHero API-key scopes. It requires the endpoint signing secret and these webhook headers:
| Header | Purpose |
|---|---|
ChartHero-Event-Id |
Business idempotency key that must match body id. |
ChartHero-Delivery-Id |
Stable delivery identifier for support/debug metadata and retry correlation. |
ChartHero-Timestamp |
Decimal Unix epoch seconds used in the signature input. |
ChartHero-Signature |
v1= HMAC-SHA256 digest for the delivery. |
ChartHero-Webhook-Version |
Webhook version that must match body api_version. |
Reject requests with missing headers, malformed timestamps, unsupported signature versions, or timestamps outside the allowed tolerance.
Example signed delivery inputs:
curl -X POST "https://partner.example.test/chart-hero/webhooks" \
-H "Content-Type: application/json" \
-H "ChartHero-Event-Id: evt_recording_transcript_ready_01" \
-H "ChartHero-Delivery-Id: whd_recording_transcript_ready_01" \
-H "ChartHero-Timestamp: 1777649400" \
-H "ChartHero-Signature: v1=a3cc6cb77b21da521f106cc32f59c3d119181f533faef8c7ff3e44f906053701" \
-H "ChartHero-Webhook-Version: 2026-05-01" \
--data-raw '{"id":"evt_recording_transcript_ready_01","type":"recording.transcript_ready","api_version":"2026-05-01","occurred_at":"2026-05-01T15:29:55Z","organization_id":"org_123","resources":{"encounter_id":"enc_123","document_id":"doc_123"}}'
Build the signed payload as {timestamp}.{raw_request_body}. Use the exact body bytes received by the HTTP server, before JSON reserialization or whitespace normalization.
1777649400.{"id":"evt_recording_transcript_ready_01","type":"recording.transcript_ready","api_version":"2026-05-01","occurred_at":"2026-05-01T15:29:55Z","organization_id":"org_123","resources":{"encounter_id":"enc_123","document_id":"doc_123"}}
Compute the HMAC-SHA256 digest with the endpoint signing secret and compare it to the v1 value in ChartHero-Signature using a constant-time comparison.
Language-neutral verification steps:
ChartHero-Timestamp and reject it if it is not decimal Unix epoch seconds.300 seconds from your server clock.{timestamp}.{raw_request_body}.ChartHero-Signature and require the supported v1= value.ChartHero-Event-Id equals body id.ChartHero-Webhook-Version equals body api_version.If verification and lightweight validation succeed, return any HTTP 2xx response. No JSON acknowledgement body is required.
HTTP/1.1 204 No Content
If verification fails, do not process clinical follow-up work. Return a non-2xx response according to your receiver policy.
After the signature is valid, parse the JSON body and verify these consistency checks:
| Header | Body field |
|---|---|
ChartHero-Event-Id |
id |
ChartHero-Webhook-Version |
api_version |
Do not process clinical follow-up work when either check fails.
Other common verification failures include missing headers, unsupported signature versions, non-decimal timestamps, stale timestamps outside the 300 second tolerance, and comparing against a JSON-reserialized body instead of the raw request body.
Return to Receive webhooks to complete the receiver flow and follow-up fetch pattern. See recording.transcript_ready in the API Reference for the generated webhook contract.
Return to the full receiver flow and follow-up pattern.
Confirm the webhook headers and retry contract.
Inspect the generated webhook operation.