Clinic-Aware Sync for GoHighLevel and OpenDental

Ayomide

Ayomide Ganiyu

Clinic-Aware OpenDental → GoHighLevel Appointment Sync

No double-entry. No duplicates. Correct calendar & user—every time. Faster front desk, cleaner data, fewer mistakes—backed by a full audit trail.

What I deliver

Accurate syncing – Creates new GHL appointments or updates existing ones using your OpenDental AptNum map. No duplicates.
Clinic-aware routing – Per-clinic calendarId + assignedUserId, with strict operatory filtering.
Smart contact upsert – Phone-first lookup; auto-creates contact with first/last name, DOB, email, phone, address, gender, and a Clinic custom field (or clinic tag).
Real reschedule logic – If a patient already has an event that day on the same calendar, the most recent event (by updatedAt) is updated instead of creating a new one.
Status fidelity – True mapping: Broken → cancelled, Complete → showed, Scheduled → confirmed.
Front-desk safeignoreFreeSlotValidation=true so valid updates don’t fail when slots look “taken.”
Audit & reliability – Local-first state mirrored to Google Drive, dead-letter queue for safe retries, gentle rate-limits for OpenDental, and crisp logs for compliance.

How it works (under the hood)

Pulls OD appointments for selected clinics & operatories (configurable).
Ensures a matching GHL Contact (phone-first upsert, fallbacks applied).
Appointment sync decision tree:
Update exact mapped event (if AptNum known), else
Update the latest same-day event on the same calendar, else
Create a fresh event.
Tags contacts with fromopendental on every create/update.
Persists mappings & state (ghl_appointments_map.json, ghl_contacts_map.json, last_sync_state.json, etc.) so runs are idempotent and recoverable.

Why clinics love this

Zero double-entry → fewer keystrokes, fewer errors, happier front desk.
No duplicates → updates beat re-creates; calendars stay clean.
Right person, right calendar → workload is routed to the correct user/clinic.
Recoverable by design → failed events land in a queue; nothing is silently lost.
Auditable → state files + logs make issues easy to trace and prove.

What I need from you (I’ll guide you)

OpenDental developer/customer keys (test + prod).
GoHighLevel API token and locationId.
Your clinic → calendarId and clinic → assignedUserId mapping.
A Google Service Account JSON + a Drive folder for state mirroring.
Clinics/operatories list, and any Broken-type allow-lists or custom rules.

Add-ons (optional)

Pipeline/webhook wiring for confirmations & reminders.
Data-quality monitors and alerting (failed updates, drift, mismatch).
Cost/performance audit: DB indexing, caching, infra right-sizing.

Implementation process

Discovery (free): goals, calendars, users, operatories, edge cases.
Mapping & spec: clinic/user/calendar map; status rules; error contracts.
Build & validate: contact upsert, appointment sync, reschedule logic, status mapping.
Dry run (sandbox): mirror to test; verify no-duplicate behavior and routing.
Go-live: production keys, rate-limits enabled, Drive mirroring, dead-letter queue.
Handover: runbook, rollback recipe, and a 30-minute walkthrough.

Deliverables

Production-ready sync service (Python) with retries and rate-limit handling
Config files + mapping templates (clinics, calendars, users, operatories)
State & logs: ghl_appointments_map.json, ghl_contacts_map.json, last_sync_state.json
Google Drive mirroring for state & audit artifacts
Runbook (install, operate, troubleshoot, rollback)
Optional: CI job or schedule for ongoing sync

Tech & safeguards

Python 3.11 • Resilient HTTP with retry/backoff • OpenDental & GHL APIs • Time-zone safe scheduling • Local-first state + Drive versioning • Idempotent writes • Dead-letter queue • Structured logging • Principle-of-least-privilege keys
Like this project

Posted Sep 17, 2025

Built a resilient API/data pipeline: OpenDental → GoHighLevel. Clinic-aware calendars, idempotent updates, no duplicates, auditable logs.