Skip to main content
Anyone who knows your webhook URL could send a forged POST request that looks like a real ByDoctor event. Without signature verification, your application might process fraudulent payloads — cancelling real appointments, crediting fake payments, or leaking patient data. Verifying the signature on every delivery is the single most important security step in your webhook integration.

The Signature Header

Every delivery from ByDoctor includes the following HTTP header:
The value is always prefixed with sha256= followed by a lowercase hex-encoded HMAC-SHA256 digest. The digest is computed over the raw request body using the webhook secret you received when you registered the endpoint.

How to Verify Incoming Signatures

1

Capture the raw request body before parsing

You must compute the HMAC over the exact bytes that arrived over the wire. If you parse the JSON first and then re-serialize it, whitespace or key ordering differences can cause the digest to mismatch. In most frameworks, this means reading the raw body buffer before it reaches your JSON middleware.
2

Retrieve your webhook secret

Load the webhook secret you stored when you registered the endpoint — the value that started with whsec_. Never hardcode it in your source code; read it from an environment variable or secrets manager.
3

Compute HMAC-SHA256 of the raw body

Using your secret as the key and the raw body bytes as the message, compute an HMAC-SHA256 digest and hex-encode it. Prepend sha256= to match the header format.
4

Compare using a constant-time equality check

Compare the computed value against the X-ByDoctor-Signature header value using a constant-time string comparison function. If the two values match, the payload is authentic. If they do not match, reject the request with a 400 or 401 status and do not process it.
Never use a regular equality operator (==, ===, eq) for this comparison. Standard string comparison short-circuits on the first differing byte, leaking timing information that an attacker can use to forge signatures incrementally. Always use a constant-time function such as crypto.timingSafeEqual (Node.js), hmac.compare_digest (Python), or hash_equals (PHP).

Code Examples

Replay Attack Protection

A valid signature only proves the payload came from ByDoctor — it does not prove the payload is fresh. An attacker who intercepts a legitimate delivery could replay it minutes or hours later. To guard against replays, check the created_at timestamp inside the event envelope and reject any event older than 5 minutes:
Node.js
Make sure your server clock is synchronized via NTP. A significant clock skew between your server and ByDoctor’s servers can cause legitimate events to be incorrectly rejected.

Rotating Your Webhook Secret

If your secret is ever compromised, you should rotate it immediately. ByDoctor does not offer in-place secret rotation — to get a new secret, delete the existing webhook and create a new one:
cURL
Update your environment variables with the new secret before deleting the old webhook to avoid dropping events during the transition.