Skip to content

Webhooks

Send real-time notifications to external services (Make.com, Zapier, custom APIs) when appointments book, forms sign, patients register.

What this enables

External automation: Patient books appointment → trigger Zapier → create Slack message, add to spreadsheet, send SMS to staff.

EHR sync: Form completed → POST to your EHR system to sync patient data, appointment notes, treatment plans.

CRM integration: New patient registers → automatically add to CRM, pull data back from CRM to prefill forms.

Compliance: Events signed and timestamped for audit trail—you can prove who triggered what and when.

Custom integrations: Configure any HTTPS endpoint—Make.com, Zapier, your custom API, anything that accepts webhooks.

How it works

  1. Admin registers webhook: Provides webhook URL (e.g., https://make.com/...) and picks events to watch
  2. Event fires: Patient books appointment in the platform
  3. The Core API sends notification: POSTs a signed JSON payload to the webhook URL
  4. External service receives it: Make.com/Zapier/custom API processes it
  5. Retry on failure: If endpoint is down, The Core API retries automatically (up to 5 times over 24 hours)
  6. Debugging: Admin can view delivery history and logs

Technical Reference

Overview

Webhooks enable real-time event notifications for domain actions in your organization. When significant events occur (appointments created, forms signed, patients onboarded, etc.), The Core API can automatically notify your configured endpoints.

                    ┌─────────────────────────────┐
  Domain action     │         Core API            │
  (e.g. form.signed)│                             │
        │           │  1. Write audit_log (sync)  │
        ▼           │  2. Emit webhook event      │
   ─────────────    │     ▼                       │
                    │  webhook_events table        │
                    │     ▼                        │
                    │  Delivery worker (async)     │
                    │     ▼                        │
                    │  POST to subscriber URLs     │
                    └──────────┬──────────────────┘

              ┌────────────────┼────────────────┐
              ▼                ▼                 ▼
         Make.com          Zapier          Custom API
         scenario          zap             (customer)

How It Works

  1. Admin registers a subscription — URL, which events to receive, optional description
  2. The Core API emits events — when domain actions happen (appointment created, form signed, etc.)
  3. The Core API delivers to subscribers — POST to their URL with a signed JSON payload
  4. Receiver verifies signature — HMAC-SHA256 with the subscription's signing secret
  5. Retry on failure — exponential backoff, up to 5 attempts over ~24 hours

Key Features

  • Org-scoped isolation — Each subscription belongs to one organization
  • Event filtering — Subscribe to specific events or all events with {"*"}
  • Security — HMAC-SHA256 signatures, HTTPS-only endpoints
  • Reliability — Automatic retries with exponential backoff
  • Privacy — No PII in payloads (IDs only)
  • Debugging — Full delivery history and retry logs

Organization Isolation

  • Each subscription belongs to one organization (enforced by RLS)
  • Events are only delivered to subscriptions within the same org
  • Signing secrets are unique per subscription — one org cannot forge events for another
  • No shared webhook URLs between orgs (each org registers its own)
  • The Emitter.Emit() query filters by organization_id — an event in org A never reaches org B's subscriptions

PII Policy

Webhook payloads contain NO personally identifiable information. Only entity IDs, event types, status values, and timestamps are included. This is a hard rule.

Why: Webhook URLs are customer-controlled. We cannot guarantee the receiver's security posture. By sending only IDs, we:

  • Eliminate the need for BAAs with every automation platform
  • Prevent PII leaks if a webhook URL is misconfigured or compromised
  • Let receivers call back to the Core API's authenticated API if they need details

What's included: *_id fields, status, event, timestamp, enum values.

What's never included: Names, emails, phone numbers, addresses, medical data, form values, custom field values, document content.

Security Considerations

  1. HTTPS only — Subscription URLs must use HTTPS. HTTP URLs are rejected at creation time.
  2. No PII in payloads — Hard rule. Receivers call back to the Core API's authenticated API for details.
  3. HMAC signatures — Every delivery is signed. Receivers should verify before processing.
  4. No BAA required — Since payloads contain no PHI, no Business Associate Agreement is needed with the receiving platform (Make.com, Zapier, etc.).
  5. Timeout — Delivery HTTP client has a 10-second timeout. Slow receivers don't block the worker.
  6. Rate limiting — Worker processes max 50 events per tick (5 seconds). Prevents thundering herd on bulk operations.

Data Retention

Webhook events are operational data, not medical records. Retention:

DataRetentionCleanup
webhook_events (delivered)30 daysAutomated daily cleanup job
webhook_events (exhausted/failed)90 daysAutomated — admins can review failures
webhook_subscriptionsUntil deleted by adminSoft-disable via is_active = false

Monitoring & Telemetry

Webhook delivery metrics referenced in ../../reference/monitoring.md (delivery success rate, retry queue depth, delivery latency) are collected from two sources:

  • Core API PostgreSQL: The webhook_events table tracks delivery status, attempt count, and timestamps. The monitoring dashboard queries this directly for operational metrics.
  • Audit middleware: All webhook delivery attempts (emit, deliver, retry, exhaust) are automatically captured in the local audit_log and forwarded to Telemetry PostgreSQL for compliance.

No analytics events are sent to ClickHouse for webhook delivery — this is operational data that lives in the main database and the audit trail.

Documentation