Concepts
Sync EHR availability
Mirror doctor shifts from a 3rd-party EHR into a Cal.com schedule with a small sync microservice and the schedules API.
3rd-party
EHR systemEpic, Cerner, Athena, etc. Source of truth for shifts and PTO.
Pull shifts (cron / webhook)
Yours
Your sync microserviceGET https://ehr.example.com/api/shifts/:doctorId
Diff against current Cal.com schedule
Yours
Compute date overridesOff-duty days → { date, startTime: '00:00', endTime: '00:00' }
PATCH /v2/schedules/:scheduleId
Cal.com
Cal.com scheduleOverrides applied — blocked dates roll out instantly.
Bookers see updated availability
Cal.com
Booker UIOff-duty days are greyed out for patients.
Sync microserviceruns on cron — every 15 min
// Pull shifts from the EHR and mirror them into a Cal.com schedule
async function syncDoctorAvailability(doctorId, scheduleId) {
// 1. Pull shifts from the EHR
const shifts = await ehrFetch(`/api/shifts/${doctorId}`);
// → [{ date: "2026-05-12", offDuty: true }, …]
// 2. Off-duty days → zero-length availability windows
const overrides = shifts
.filter((s) => s.offDuty)
.map((s) => ({
date: s.date,
startTime: "00:00",
endTime: "00:00",
}));
// 3. Push overrides to Cal.com — partial PATCH, only sends what changed
await fetch(`https://api.cal.com/v2/schedules/${scheduleId}`, {
method: "PATCH",
headers: {
"Authorization": `Bearer ${CAL_API_KEY}`,
"cal-api-version": "2024-06-11",
"Content-Type": "application/json",
},
body: JSON.stringify({ overrides }),
});
}GET /v2/schedules/:id reads the current schedule so you can diff before writing. PATCH /v2/schedules/:id accepts a partial body — send just overrides to mark days off without touching the recurring weekly availability.