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
- Admin registers webhook: Provides webhook URL (e.g.,
https://make.com/...) and picks events to watch - Event fires: Patient books appointment in the platform
- The Core API sends notification: POSTs a signed JSON payload to the webhook URL
- External service receives it: Make.com/Zapier/custom API processes it
- Retry on failure: If endpoint is down, The Core API retries automatically (up to 5 times over 24 hours)
- 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
- Admin registers a subscription — URL, which events to receive, optional description
- The Core API emits events — when domain actions happen (appointment created, form signed, etc.)
- The Core API delivers to subscribers — POST to their URL with a signed JSON payload
- Receiver verifies signature — HMAC-SHA256 with the subscription's signing secret
- 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 byorganization_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
- HTTPS only — Subscription URLs must use HTTPS. HTTP URLs are rejected at creation time.
- No PII in payloads — Hard rule. Receivers call back to the Core API's authenticated API for details.
- HMAC signatures — Every delivery is signed. Receivers should verify before processing.
- No BAA required — Since payloads contain no PHI, no Business Associate Agreement is needed with the receiving platform (Make.com, Zapier, etc.).
- Timeout — Delivery HTTP client has a 10-second timeout. Slow receivers don't block the worker.
- 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:
| Data | Retention | Cleanup |
|---|---|---|
webhook_events (delivered) | 30 days | Automated daily cleanup job |
webhook_events (exhausted/failed) | 90 days | Automated — admins can review failures |
webhook_subscriptions | Until deleted by admin | Soft-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_eventstable 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_logand 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
- API Reference — Webhook subscription management endpoints
- Database Schema — Tables, indexes, and RLS policies
- Event Catalog — Complete list of available events and payload schemas
- Delivery System — Worker architecture, retry logic, debugging
- Signature Verification — HMAC security and implementation
- Integration Examples — Make.com, Zapier, n8n setup guides