Developers

Webhooks

Receive signed appointment and consultation-document updates at an HTTPS endpoint configured by Doctronic.

Doctronic can send signed HTTP POST requests when selected appointment or consultation-document events occur. Webhooks are configured manually. Provide your HTTPS endpoint and event subscriptions to your Doctronic implementation contact. Doctronic will provide the signing secret through the agreed secure channel.

Webhook configuration is managed by Doctronic

There is no public endpoint or dashboard for registering a webhook, rotating its secret, viewing deliveries, or replaying an event. Coordinate those actions with your implementation contact.

Event envelope

Every request uses this camelCase envelope:

{
  "eventId": "0f8fad5b-d9cb-469f-a165-70867728950e",
  "event": "appointment.waiting_room_ready",
  "occurredAt": "2026-08-25T18:30:00Z",
  "data": {
    "appointmentId": "appointment-id",
    "userId": "doctronic-user-id",
    "waitingRoomUrl": "https://dctd.co/r/example/"
  }
}

eventId remains the same across delivery attempts. Use it as the idempotency key for processing. occurredAt records when the event occurred, not when a particular attempt reached your endpoint.

Available events

Eventdata fieldsMeaning
appointment.waiting_room_readyappointmentId, userId, waitingRoomUrlA join URL is ready. The URL currently expires one hour after issuance and can rotate when reissued.
appointment.practitioner_joinedappointmentId, userIdA practitioner joined the appointment.
appointment.call_endedappointmentId, userIdThe appointment call ended.
artifact.readyartifactId, artifactType, chatId, userIdA consultation document is ready for retrieval. userId can be null.

Only events enabled for your integration are sent. Ignore unknown event names so additive changes do not break your receiver.

Verify the signature

The X-Doctronic-Signature header contains a lowercase hexadecimal HMAC-SHA256 digest of the exact request body bytes, signed with your webhook secret.

Verify the signature before parsing or processing the JSON. Do not reserialize the body first.

Node.js signature verification
import { createHmac, timingSafeEqual } from 'node:crypto';

export async function verifyDoctronicWebhook(
  request: Request,
  secret: string,
) {
  const body = Buffer.from(await request.arrayBuffer());
  const supplied = request.headers.get('x-doctronic-signature') ?? '';
  const expected = createHmac('sha256', secret).update(body).digest('hex');

  const suppliedBytes = Buffer.from(supplied, 'utf8');
  const expectedBytes = Buffer.from(expected, 'utf8');
  const valid =
    suppliedBytes.length === expectedBytes.length &&
    timingSafeEqual(suppliedBytes, expectedBytes);

  if (!valid) throw new Error('Invalid Doctronic webhook signature');
  return JSON.parse(body.toString('utf8'));
}
Python signature verification
import hashlib
import hmac
import json

def verify_doctronic_webhook(body: bytes, supplied: str, secret: str) -> dict:
    expected = hmac.new(secret.encode("utf-8"), body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(supplied, expected):
        raise ValueError("Invalid Doctronic webhook signature")
    return json.loads(body)

Process deliveries safely

  1. Read and preserve the raw request body.
  2. Verify X-Doctronic-Signature with a constant-time comparison.
  3. Validate the event envelope and expected data fields.
  4. Insert eventId into a durable uniqueness store.
  5. If it was already processed, return a success response without applying the change again.
  6. Queue the work and return any 2xx response promptly.
  7. Apply the event only to the matching organization and user records in your system.

The current signature has no separate delivery timestamp header. The signed occurredAt value can support a workflow-specific freshness check, but it may be several hours old during retries. Do not use freshness alone as replay protection. Signature verification and durable eventId deduplication are both required.

Delivery behavior

  • Network failures, 429, and 5xx responses are retried with exponential backoff.
  • Other 4xx responses are treated as permanent failures and are not retried.
  • The general retry window is up to six hours.
  • appointment.waiting_room_ready has a shorter retry window of up to five minutes and stops when the event is no longer useful for the appointment.
  • Appointment lifecycle retries can stop when the appointment has ended.

Do not rely on a specific number of attempts. Keep the receiver available, idempotent, and fast.

Rotate a webhook secret

Secret rotation is coordinated with Doctronic. Plan a short maintenance procedure that can accept the agreed secret at the agreed cutover point, verify a signed test delivery, and remove the prior secret from your systems. Do not send the secret in email or an unapproved messaging channel.

Test before production

Ask your implementation contact to enable the required events in staging. Verify:

  • Valid signatures succeed and changed bodies fail verification.
  • Duplicate eventId values do not repeat side effects.
  • Unknown event names return success without blocking other events.
  • Your endpoint responds correctly to retries and out-of-order events.
  • A waiting-room URL replaces an older URL rather than becoming a permanent identifier.
  • Processing failures are visible to your on-call team without logging secrets or unrestricted patient content.

On this page