webhook-id, keep the highest version, and answer with a 2xx status quickly.
Last reviewed: 2026-11-04
Events follow the statuses described in Consultation lifecycle and the prescription data described in Prescriptions.
Register an endpoint
Manage endpoints in the Business portal or with the API. Scopes:webhooks:manage, plus consultations:read and prescriptions:read, because events carry full consultation and prescription data; every webhook endpoint and delivery route needs all three. Endpoints belong to one mode: test events go only to test endpoints, live events only to live endpoints.
Endpoint URLs must use
https on port 443, with a public host name. Redirects are not followed.
Event types
Accept event types you do not know and ignore them: new types can be added at any time.
Event envelope
data object above is shortened. In real events data is the complete consultation resource, exactly as GET /v1/partner/consultations/{id} returns it at that version, including every prescription. Prescription events add prescription_id naming the prescription that changed.
Ordering: keep the highest version
Events can arrive late, more than once, or out of order. Prescription events in particular come from a periodic reconciliation and can arrive after a later consultation event. Do not apply events as partial updates. Instead:- Read
data.id(the consultation) andversion. - If you already stored a snapshot for that consultation with an equal or higher
version, ignore the event. - Otherwise replace your stored consultation wholesale with
data.
Headers
Deliveries follow the Standard Webhooks specification.
Header names are case-insensitive: read them case-insensitively, as your framework normally does.
Verify the signature
Your endpoint’s signing secret looks likewhsec_ followed by standard base64 (A-Z, a-z, 0-9, +, /, = padding). The HMAC key is the decoded bytes of the part after whsec_, not the secret string. The signature is the base64-encoded HMAC-SHA256 of {webhook-id}.{webhook-timestamp}.{body}, where body is the raw request body bytes: verify before parsing JSON, because re-serialising changes the bytes.
- Read
webhook-id,webhook-timestampandwebhook-signature. Reject the request ifwebhook-idorwebhook-signatureis missing or empty, or ifwebhook-timestamp, trimmed, is not only the digits0-9. - Reject the request if the timestamp is more than 300 seconds away from your clock, in either direction, both counted in whole seconds (drop the fraction of your clock). Exactly 300 seconds is accepted.
- Decode your secret: strip
whsec_and base64-decode the rest strictly. Hi Doctor secrets decode to 32 bytes; a secret that is not valid standard base64 of 24 to 64 bytes never verifies. - Compute the HMAC-SHA256 of
{webhook-id}.{timestamp}.followed by the raw body, writing the timestamp as an integer without leading zeros, and base64-encode it with padding. - Split
webhook-signatureon single spaces. In each entry, the version is the text before the first,and the signature is everything after it. Ignore entries whose version is not exactlyv1or whose signature is empty. - Accept if your value equals any
v1signature, using a constant-time comparison.
standardwebhooks packages exist for Node.js, Python and other languages, and some webhook platforms ship compatible verifiers. Pass the secret with its whsec_ prefix and the raw body. The samples below implement the same steps with only the standard library.
Process events safely
The consumer below applies the three rules together: verify, dedupe onwebhook-id, keep the highest version. Replace the in-memory maps with your database.
How are failed deliveries retried?
- Answer with any
2xxstatus as soon as you have stored the event. Process it afterwards. Anything else, a timeout or a connection error counts as a failure. Hi Doctor waits up to 10 seconds for a response and reads at most 64 KB of it. - A failed delivery is retried on this schedule after the previous attempt: 1 minute, 5 minutes, 30 minutes, 2 hours, 8 hours, 24 hours, 24 hours. That is the first attempt plus 7 retries, 8 attempts in total, after which the delivery is marked exhausted.
- The same event can be delivered more than once, for example when a delivery succeeded but the acknowledgement was lost. Deduplicate on
webhook-id: it is the eventid, identical on every attempt and replay. Each attempt is signed again with a freshwebhook-timestamp, so the signature changes between attempts. - Hi Doctor disables an endpoint automatically when 50 deliveries in a row have failed, or when it has kept failing for more than 3 days. It then emails your partner contact and shows a banner in the Business portal. Pending deliveries are kept; re-enable the endpoint once it is fixed and they resume.
Replay
POST /v1/partner/webhook-deliveries/{id}/replay resets the existing delivery for immediate delivery, with the same delivery id, event id and body: its status returns to pending, attempt_count to 0 and the retry schedule starts again. It does not create a second delivery. A pending delivery that a worker is sending at that moment is left as it is. Replaying is itself safe to repeat. Use it after fixing an endpoint, or replay from the deliveries list in the Business portal.
Secret rotation
POST /v1/partner/webhook-endpoints/{id}/rotate-secret returns a new whsec_ secret once. For the next 24 hours every delivery is signed with both secrets, newest first, so webhook-signature carries two space-separated entries:
Test events
POST /v1/partner/webhook-endpoints/{id}/test sends an endpoint.test event with a fixed sample body, signed like any other event. Use it to check your URL, TLS and signature code. To test real consultation events, use test mode.
Retention
Events and delivery records are deleted after about 30 days by a periodic cleanup. A delivery is kept longer while it was created or replayed within the last 30 days or is being sent, and an event is kept while it still has a delivery; a few older events can be kept longer. Do not rely on any record outliving 30 days: store what you need on your side. Endpoint errors, such as an invalid URL or event list, are listed in Partner API errors.Frequently asked questions
Do I need webhooks, or can I poll?
You can read consultations by polling the consultation list, but webhooks tell you about every change without polling. Each event carries the full consultation, so one event is enough to update your records.Why do events arrive out of order or twice?
Deliveries can be late, retried or replayed, and prescription events come from a periodic reconciliation. Deduplicate on the webhook-id header and keep the snapshot with the highest version number.How many times is a failed delivery retried?
Up to 8 attempts in total: the first attempt plus 7 retries, spread from 1 minute to 24 hours apart. After that the delivery is marked exhausted, and you can replay it.When is an endpoint disabled automatically?
When 50 deliveries in a row have failed, or when the endpoint has kept failing for more than 3 days. Hi Doctor emails your partner contact, and pending deliveries resume once you re-enable it.Can I use a Standard Webhooks library to verify signatures?
Yes. Any Standard Webhooks library verifies Hi Doctor deliveries. Pass the secret with its whsec_ prefix and the raw request body.What happens to signatures when I rotate the secret?
For 24 hours every delivery is signed with both the new and the old secret, so a verifier holding either one keeps working while you deploy.How long are events kept?
About 30 days. Store what you need on your side.Next steps
Test mode
Trigger real consultation events against your test endpoint.
Business portal
Manage endpoints, deliveries and replays.
Go-live checklist
What must be in place before live mode.