Back to the build library
Healthcare & clinics
Advanced

Multi-Provider Scheduling

Provider-specific availability, service eligibility rules and load balancing across a roster, so the right patient lands on the right calendar.

Industry
Healthcare & clinics
Build effort
Advanced
Typical time to launch
4–6 weeks
On this page
The problemWhat gets builtHow it runsAutomations in detailWhat changesBefore you start
Want this built for you?

Bring your stack to a call and we will scope it against how your business actually runs.

Book a call
01

The problem

A single-provider clinic can schedule from a paper book. The moment there are four providers, two locations, a nurse practitioner who cannot take new patients, a physician who only does procedures on Tuesdays and Thursdays, and a locum who covers alternate Fridays, the schedule stops being a calendar and becomes a rules engine running inside one receptionist's head. That person is the real scheduling system, and they are a single point of failure who also answers the phone.

The failure modes are predictable. New patients get booked into slots meant for follow-ups, so a thirty-minute visit runs fifty and the rest of the day slips. Patients who needed a specific provider get put with whoever had an opening, then cancel when they find out. Procedure visits land on a day the room is not staffed. One provider finishes at two in the afternoon with gaps while another is triple-booked and behind. New-patient slots sit unsold at the end of the week because nobody looked, and the waitlist is a sticky note.

The money leaks in three places and all three are large. Unfilled slots are revenue that cannot be recovered. A clinical hour not booked is gone, and in a multi-provider practice the unfilled percentage is almost always higher than anyone believes because nobody measures per provider. No-shows and late cancellations are worse, because the slot was blocked and then wasted. And mis-booked visits cost twice: once in the overrun that pushes the schedule, once in the patient experience that produces the complaint. This build moves the rules out of the receptionist's head and into the platform, so eligibility, duration, provider match and load balancing are enforced before a slot is ever held.

02

What gets built

Pipeline and stages

A Scheduling pipeline tracks every booking request from first contact to visit outcome. Routine rebooks skip it; anything that needs qualification, verification or a human decision goes through it.

  • Request Received: inbound booking intent from any channel, not yet qualified.
  • Qualifying: BO or staff is gathering visit type, new-or-established status, location and provider preference.
  • Needs Human Triage: the request does not match a defined service, or a flag fired. Off the automation path.
  • Eligible - Awaiting Slot Choice: qualified, booking link sent, nothing held yet.
  • Booked - Unverified: slot held, insurance or referral not yet confirmed.
  • Booked - Verified: cleared to attend.
  • Confirmed: patient actively confirmed in a reminder.
  • Rescheduled: moved at least once; counted separately so churn is visible.
  • No-Show: did not attend, recovery sequence running.
  • Late Cancel: canceled inside the notice window; triggers waitlist backfill.
  • Completed: attended, handed off to the post-visit systems.
  • Waitlist: wants an earlier slot than currently exists.

Calendars

The calendar architecture is the build. Get this wrong and no amount of automation rescues it.

  • One calendar per provider per location. Dr. Okafor - Main and Dr. Okafor - North are two calendars, each carrying its own hours, buffers and slot grid. Never model a provider across sites on one calendar; travel time and room availability differ.
  • Service calendars layered on top. A service calendar represents what is being booked: New Patient Consult, Established Follow-Up, Annual Exam, Procedure, Injection Visit, Telehealth, Nurse-Only Visit, and carries the duration, the buffers and the eligible provider pool. A patient books a service; the platform resolves which provider calendar can host it.
  • Round-robin and pooled distribution on the services where any eligible provider will do. Pooled on New Patient Consult, specific-provider on Established Follow-Up, because continuity matters for the second and not the first.
  • Blocked resource calendars for anything shared and scarce: Procedure Room 1, Procedure Room 2, Ultrasound, the mobile phlebotomy cart. A procedure service requires both a provider calendar and a room calendar to be open, or the slot does not exist.
  • Provider-controlled exception calendar where each clinician puts their own time off, conference days, admin blocks and academic half-days, synced from their personal Google Calendar or Outlook with busy-only visibility. Providers must be able to block their own time without asking the front desk, or they will stop cooperating with the system entirely.
  • Slot grid rules per service: duration, pre-buffer, post-buffer, minimum notice, maximum booking horizon, daily cap, and per-provider daily cap for high-intensity services.

Custom fields

On the contact record:

  • patient_status: option: New, Established, Established-Lapsed, Transferred Out.
  • assigned_provider: text or reference, the continuity provider of record.
  • home_location: option.
  • provider_preference: text, what the patient asked for, which is not always what they get.
  • preference_is_hard: switch. True means do not offer another provider; this protects continuity and prevents the "they put me with someone else" cancellation.
  • visit_type_requested: option, mapped one-to-one to service calendars.
  • last_completed_visit and next_due_date: dates, drive recall.
  • insurance_status: option: Not Checked, Verification Requested, Verified, Issue, Self-Pay.
  • insurance_verified_date: date.
  • referral_required and referral_on_file: switches.
  • forms_status: option: Not Sent, Sent, Partially Complete, Complete.
  • noshow_count_12mo and late_cancel_count_12mo: numbers, drive the deposit and double-confirm rules.
  • scheduling_flag: option: None, Requires Front Desk, Deposit Required, Interpreter Needed, Mobility Assistance, Do Not Self-Book.
  • interpreter_language: option.
  • waitlist_window: text, e.g. "weekday mornings, Main only".
  • sms_consent, sms_consent_date, email_consent, preferred_contact_channel, language_preference.

Tags

  • new-patient, established, lapsed-12mo
  • pref-hard, pref-soft, pooled-ok
  • needs-insurance-verify, insurance-issue, self-pay
  • forms-outstanding, forms-complete
  • waitlist-active, waitlist-contacted
  • noshow-1, noshow-2, noshow-3plus, late-cancel
  • deposit-required, do-not-self-book
  • interpreter-needed, mobility-assist
  • triage-human: removes the contact from every scheduling automation until cleared
  • sms-opted-out

Forms

  • Booking Qualifier: the front door. Asks location, whether they have been seen before, which provider if any, reason for visit in non-clinical terms selected from a controlled list (not free text, so no symptom narratives land in the platform), and preferred days and times. Writes visit_type_requested, patient_status, provider_preference and home_location.
  • New Patient Registration: demographics, insurance card capture, consents, and the practice's own notice acknowledgements. This is the one form that legitimately holds sensitive data; it must live behind authentication and inside systems covered by a signed business associate agreement.
  • Insurance Verification Request: internal form the front desk works from, prefilled from the registration.
  • Reschedule and Cancel: a tokenized link in every reminder, so patients can move themselves without a phone call. the most important form in the build.
  • Waitlist Join: captures waitlist_window and consent to be contacted at short notice.
  • Provider Availability Change: internal form clinicians submit to add or remove availability, which creates a task rather than editing the calendar directly, so changes are reviewed against already-booked slots.

BO's role and guardrails

  • Qualifies and routes. BO handles the booking conversation over SMS, web chat and the inbound call path: establishes new-or-established, location, service and provider preference, then hands over the correct booking link.
  • Enforces the eligibility matrix. BO never offers a slot a rule forbids. No new patient into a follow-up slot, no procedure on a day the room calendar is closed, no booking with a provider closed to new patients.
  • Answers logistics only. Hours, locations, parking, what to bring, how long a visit takes, which providers see which age groups.

Guardrails:

  • BO never gives clinical advice, never assesses urgency or severity, and never tells a patient whether a symptom can wait.
  • Any message suggesting urgency: chest pain, difficulty breathing, bleeding, suicidal statements, severe pain, pregnancy complications, injury, overdose, or an explicit "this is an emergency", immediately ends BO's turn, applies triage-human, notifies the clinical phone line, and returns a fixed response naming emergency services and the practice's own after-hours line. No triage, no reassurance, no scheduling.
  • BO never puts clinical detail into an outbound SMS or email. Confirmations say the date, time, location and a neutral service label from an approved list; they do not say why the patient is coming.
  • BO never collects insurance numbers, dates of birth or identifiers over SMS. Those go through the authenticated registration form only.
  • BO cannot override preference_is_hard, cannot book a contact tagged do-not-self-book, and cannot create availability.

Numbers and channels

  • One main inbound number, with an interactive menu that separates appointments from clinical questions from billing, and routes clinical questions to a human path immediately.
  • A dedicated outbound appointment-messaging number so reminders are not mixed with marketing traffic and an opt-out from one does not silence the other.
  • Per-location direct dial numbers for established patients, forwarding to that site's front desk with a whisper naming the location.
  • A public booking page per service, with provider bios and a pooled "first available" option, so patients who do not care who they see take the path that balances the roster.
03

How it runs, step by step

  1. A prospective patient taps the New Patient booking page from a search result. The Booking Qualifier loads: location, new or established, reason from a controlled list, preferred provider if any, preferred days.
  2. They select Main, New, Annual Exam, no provider preference. The platform writes home_location, patient_status New, visit_type_requested Annual Exam, tags new-patient and pooled-ok.
  3. The eligibility engine resolves the service to its provider pool: the two physicians and one nurse practitioner who are open to new patients at Main. The nurse practitioner's calendar is excluded for this service because the practice's rules reserve new annual exams for physicians. Load balancing compares each eligible provider's booked-hours percentage for the target week and sorts slots so the lighter calendar shows first.
  4. The slot grid applies the service rules: 40 minutes, 5-minute pre-buffer, 10-minute post-buffer, minimum 24 hours notice, maximum 90 days horizon, no more than four new-patient visits per provider per day. Only slots satisfying all of it render.
  5. The patient picks Thursday 10:20 with Dr. Okafor. The slot is held, an opportunity is created in Booked - Unverified, and the platform writes the appointment to the provider calendar and to Dr. Okafor's synced personal calendar as busy.
  6. Immediately a confirmation goes out on the patient's chosen channel. It names the date, time, location, parking note, and the neutral service label "annual visit". Nothing clinical. A tokenized reschedule link and an add-to-calendar link ride along.
  7. In parallel, the New Patient Registration link is sent, forms_status is set to Sent, and the contact is tagged forms-outstanding. The registration is where insurance and identifiers are captured, behind authentication, never over SMS.
  8. Registration is submitted. insurance_status flips to Verification Requested, a task lands on the front desk queue with a due date two business days before the visit, and the internal Insurance Verification Request form is prefilled.
  9. The front desk verifies and sets insurance_status to Verified. The opportunity moves to Booked - Verified. Had it come back as an Issue, the contact would have been tagged insurance-issue, the reminder ladder paused, and a call task created, because telling someone about a coverage problem at check-in is how a visit becomes a complaint.
  10. The reminder ladder runs: 7 days out by email with directions and the forms link if still outstanding; 72 hours out by SMS asking for an explicit confirm reply; 24 hours out by SMS with the reschedule link; 2 hours out a short day-of nudge. A YES reply at any rung moves the opportunity to Confirmed and suppresses the remaining confirm asks but not the day-of nudge.
  11. Two days before, a different patient cancels a Tuesday procedure slot. The late-cancel workflow releases the provider calendar and the Procedure Room 1 resource calendar, then queries the waitlist for contacts whose waitlist_window matches Tuesday, Main, and whose visit_type_requested maps to that service. The first three matching contacts get a short offer message, first reply wins, and the other two are told it went.
  12. Thursday arrives. Dr. Okafor's schedule shows the annual exam at the right duration with the right buffers, the room is not needed, and the registration is complete so check-in takes two minutes instead of fifteen.
  13. The appointment is marked Showed. The opportunity moves to Completed, last_completed_visit is stamped, next_due_date is set twelve months out, assigned_provider is set to Dr. Okafor so the next booking defaults to continuity, and the contact is handed to the recall and post-visit survey systems.
  14. Had the patient not attended, the no-show path would have fired instead: noshow_count_12mo incremented, tag noshow-1 applied, a rebooking offer sent within an hour, and (on a second no-show inside twelve months) scheduling_flag set to Requires Front Desk so the third attempt cannot be self-booked without a conversation.
  15. Every morning at 06:45 the daily schedule health report lands: unfilled clinical hours per provider for today and the next five business days, unverified bookings inside 48 hours, outstanding forms, unconfirmed appointments for today, and the waitlist depth. It is a to-do list, not a dashboard.
04

Automations in detail

1. Inbound Booking Qualification and Routing

Trigger: Booking Qualifier submitted, inbound SMS containing booking intent, web chat conversation started, or inbound call captured with no appointment booked.

Conditions and branches, evaluated in this order:

  1. Urgency screen first, always. If the inbound text matches the urgency lexicon. Chest pain, cannot breathe, shortness of breath, bleeding, severe pain, fainted, overdose, suicidal, self-harm, labor, contractions, water broke, head injury, stroke, numbness, emergency, 911. Stop everything: apply triage-human, move to Needs Human Triage, notify the clinical line, and send the fixed response: "I am not able to help with medical questions or urgent symptoms. If this is an emergency, call 911 or go to your nearest emergency room now. For an urgent clinical question, call us on {{custom_values.clinical_line}} and a member of our clinical team will speak with you." End the workflow. BO does not assess, reassure, or offer an appointment.
  2. If scheduling_flag is Do Not Self-Book, or tag do-not-self-book is present, route to Needs Human Triage with a call-back task and send "Thanks {{contact.first_name}}, I will have someone from our front desk call you to get this booked."
  3. BO collects, in this sequence: location, new-or-established, service from the controlled list, provider preference, and whether that preference is firm. Writes home_location, patient_status, visit_type_requested, provider_preference and preference_is_hard. If BO cannot map the stated reason to a defined service in two attempts, route to Needs Human Triage rather than guessing.
  4. Apply tags: new-patient or established; pref-hard or pref-soft or pooled-ok.
  5. Move to Eligible - Awaiting Slot Choice and send the service-specific booking link: "Here is the live schedule for {{contact.visit_type_requested}} at our {{contact.home_location}} office: {{booking_link}}. Pick anything that works. It books instantly. Reply STOP to opt out of texts."
  6. Wait 2 hours. If no booking, send one nudge with the link. Wait 22 hours. If still no booking, create a front-desk call task and end.

Stop and exit conditions: appointment booked; triage-human applied; sms-opted-out; urgency match at any point in the conversation, including mid-way, which terminates BO's turn immediately.

2. Provider Match, Eligibility Enforcement and Load Balancing

Trigger: a booking page is loaded, or BO requests available slots.

Conditions and branches:

  1. Resolve the service. Pull duration, pre-buffer, post-buffer, minimum notice, horizon, daily cap, per-provider daily cap, and the required resource calendars.
  2. Build the eligible provider pool. Start from every provider calendar at the requested location, then remove: providers not credentialled for the service; providers closed to new patients when patient_status is New; providers outside the service's age or scope rules; providers whose per-provider daily cap for this service is already met; providers on the exception calendar for that date.
  3. Hard preference branch. If preference_is_hard is true, reduce the pool to that one provider. If the result is empty inside the horizon, do not substitute. Send "Dr. {{contact.provider_preference}} has nothing open in the next {{horizon}} days. I can add you to the list for the first cancellation, or book you with another clinician, which would you prefer?" and branch on the reply. Silently substituting a provider is the single most reliable way to manufacture a late cancellation.
  4. Soft or pooled branch. Keep the full pool and order it by load balancing: for each provider, compute booked clinical minutes divided by available clinical minutes for the target week, then sort ascending so the least-loaded calendar surfaces first. Break ties by assigned_provider match, then by continuity with the patient's last three visits, then round-robin by last-assigned timestamp so the same name does not always win.
  5. Resource intersection. For any service requiring a room, device or assistant, intersect the provider's open slots with the resource calendar's open slots. A slot that exists on only one of the two is not offered.
  6. Render only legal slots. Apply minimum notice, horizon, buffers and the clinic-wide daily cap last. If fewer than three slots survive inside 14 days, append the Waitlist Join link to the page.

Stop and exit conditions: no eligible provider at all, which routes to Needs Human Triage with a notification rather than showing an empty calendar; resource calendar unavailable, which hides the service entirely rather than offering an unfulfillable slot.

3. Booking Confirmation, Registration and Verification Chain

Trigger: appointment created on any provider calendar.

Actions in order:

  1. Immediately, create or update the opportunity in Booked - Unverified. Write the provider, location, service and start time to the opportunity, never a clinical reason.
  2. Immediately, send confirmation on preferred_contact_channel. SMS: "You are booked, {{contact.first_name}}. {{appointment.date}} at {{appointment.time}}, {{appointment.location}}, with {{appointment.provider}}. Add to your calendar: {{calendar_link}}. Need to change it? {{reschedule_link}}. Reply STOP to opt out." Note what is absent: no reason for visit, no clinical label beyond the neutral service name.
  3. Wait 5 minutes. Branch on patient_status. New: send the registration link: "Two things to do before {{appointment.date}}, {{contact.first_name}}: your registration and insurance details take about 6 minutes and save you fifteen at the desk. Secure link: {{registration_link}}." Set forms_status Sent, tag forms-outstanding. Established: send the short demographics-confirmation form instead.
  4. Wait 48 hours. If forms_status is not Complete, send one reminder on the same channel and one on the alternate channel if consent exists. If still incomplete 5 days before the visit, create a front-desk task "Collect registration by phone."
  5. On registration submission: set insurance_status to Verification Requested, tag needs-insurance-verify, create a front-desk task due 2 business days before the visit, and prefill the internal verification form.
  6. Branch on the verification outcome. Verified: move to Booked - Verified, remove needs-insurance-verify, continue to the reminder ladder. Issue: tag insurance-issue, pause the reminder ladder, create an urgent call task, and notify the front-desk lead: "Coverage issue on a booked visit {{appointment.date}}. Call before the reminder ladder resumes." Self-Pay: tag self-pay, send the practice's self-pay information page, and continue.
  7. Branch on referral_required. If true and referral_on_file is false, create a task and send "Your insurer needs a referral from your primary care doctor before this visit. Here is what to ask them for: {{referral_info_link}}."

Stop and exit conditions: appointment canceled or rescheduled, which restarts the chain from step 1 with the new slot; triage-human applied; opt-out, which switches the chain to email if email_consent is Granted and otherwise to a front-desk call task.

4. Reminder Ladder with Confirm and Reschedule Branches

Trigger: opportunity enters Booked - Verified, or 7 days before start time, whichever is later.

Conditions: not tagged insurance-issue; not tagged triage-human; appointment still active.

Actions in order:

  1. 7 days out, email. Subject "Your {{appointment.date}} visit at {{custom_values.practice_name}}." Body carries date, time, location, provider, directions, parking, what to bring, and the forms link if forms_status is not Complete.
  2. 72 hours out, SMS, quiet-hours gated. "Hi {{contact.first_name}}, confirming {{appointment.date}} at {{appointment.time}} with {{appointment.provider}}, {{appointment.location}}. Reply YES to confirm or use {{reschedule_link}} to move it."
  3. Branch on the reply. YES or C: move to Confirmed, suppress rungs 4 and 5 but keep the day-of nudge. NO or CANCEL: run workflow 6 immediately. Anything else: hand the conversation to BO, which re-runs the urgency screen before answering anything.
  4. 24 hours out, SMS if not yet confirmed. "Tomorrow at {{appointment.time}}, {{contact.first_name}}. Reply YES to confirm, or {{reschedule_link}} if you need a different time. If we do not hear back we will hold your slot but a confirmation really helps us plan."
  5. Double-confirm branch. If noshow_count_12mo is 2 or more, add a rung at 4 hours out and require an explicit YES. If no YES by 2 hours out, release the slot to the waitlist and notify the front desk: "Unconfirmed high-risk slot released, {{appointment.time}}." This rule must be a written practice policy and disclosed at booking, not a surprise.
  6. 2 hours out, SMS. "See you at {{appointment.time}} today, {{contact.first_name}}. {{appointment.location}}, {{directions_link}}. Running late? Reply here and we will tell the team."
  7. On any inbound "late" or "running behind", notify the front desk with the record and the appointment time and reply "Thanks: I have let the front desk know." BO does not promise the slot will be held; only a human can make that call.

Stop and exit conditions: appointment canceled, rescheduled or marked Showed; sms-opted-out, which drops the ladder to email only; insurance-issue applied mid-ladder, which pauses it; triage-human applied, which ends it. Hard cap of five appointment messages per visit, four for confirmed patients.

5. No-Show and Late-Cancel Recovery

Trigger: appointment status set to No-Show, or cancellation received inside the notice window defined per service.

Actions in order:

  1. Move the opportunity to No-Show or Late Cancel. Increment noshow_count_12mo or late_cancel_count_12mo. Apply noshow-1, noshow-2 or noshow-3plus by the new count.
  2. Immediately release the provider slot and any linked resource calendar, then start workflow 6 so the slot has a chance of being refilled today.
  3. Wait 1 hour, then send a non-judgemental rebooking offer. "We missed you today, {{contact.first_name}}, no problem at all. Here is the live schedule to pick a new time: {{booking_link}}. If something is getting in the way of getting here, reply and tell me; we may be able to help with timing or a telehealth slot."
  4. Wait 48 hours. If no rebooking, send one more on the alternate channel.
  5. Wait 5 days. If still no rebooking, create a front-desk call task and move the opportunity to the recall system rather than leaving it open.
  6. Branch on the new count. 1: nothing further. 2: set scheduling_flag to Requires Front Desk, tag do-not-self-book, and notify the front-desk lead so the next booking happens in conversation. 3 or more: additionally set scheduling_flag to Deposit Required if the practice operates a deposit policy, tag deposit-required, and create a task for the practice manager to review under the written attendance policy. Never apply a deposit or a booking restriction that is not in a disclosed, consistently applied policy; have the practice's own counsel review it before it goes live.
  7. If the no-show was on a service with a scarce resource (procedure room, device, interpreter) notify the resource owner separately so the resource is re-offered, not just the provider slot.

Stop and exit conditions: patient rebooks, which ends the sequence and starts workflow 3 on the new appointment; opt-out; triage-human.

6. Waitlist Backfill on Cancellation

Trigger: any appointment canceled, released or marked No-Show, freeing a slot inside the next 10 business days.

Conditions: the freed slot is at least 2 hours in the future; the service is one the practice allows short-notice booking on; at least one contact is tagged waitlist-active.

Actions in order:

  1. Query waitlist contacts matching all of: service equal to the freed slot's service; home_location equal to the slot's location; waitlist_window overlapping the slot's day and time band; provider eligible under preference_is_hard; no triage-human; consent on at least one channel.
  2. Rank the matches: hard-preference matches for this exact provider first, then longest time on the waitlist, then clinical priority where the practice maintains one set by a clinician: never set by BO.
  3. Send a single offer to the top three simultaneously, framed as first-come. "Good news {{contact.first_name}}, a slot just opened at {{custom_values.practice_name}}: {{slot.date}} at {{slot.time}} with {{slot.provider}}, {{slot.location}}. Reply TAKE to claim it. First reply gets it. Reply STOP to leave the short-notice list."
  4. First TAKE reply wins: book the slot, tag waitlist-contacted, remove waitlist-active, and start workflow 3.
  5. Send the other two "That one went, {{contact.first_name}}, you are still on the list and I will message you the moment the next one opens."
  6. Wait 45 minutes. If nobody claimed it, offer to the next three. Repeat up to three rounds, then publish the slot to the public booking page and notify the front desk: "Unfilled slot {{slot.date}} {{slot.time}}, {{slot.provider}}, waitlist exhausted."
  7. Every Friday, prune: remove waitlist-active from anyone who has since been seen, has declined three offers, or has been on the list beyond the practice's agreed maximum.

Stop and exit conditions: slot filled; slot now inside 2 hours; three offer rounds exhausted. Never message the same contact about more than two freed slots in one day: short-notice offers go stale fast and over-offering burns the list.

7. Availability Change Propagation and Overbook Guard

Trigger: Provider Availability Change form submitted, or a busy event appears on a provider's synced personal calendar that overlaps already-booked clinical time.

Actions in order:

  1. Query every booked appointment inside the affected window. Branch on the count.
  2. Zero affected: apply the change to the provider calendar, recalculate the load-balancing weights for that week, notify the front desk: "Availability updated: {{provider}}, {{window}}. No bookings affected." End.
  3. One or more affected: do not change the calendar. Create a high-priority task on the front-desk lead listing each affected appointment with patient record identifier, time and service (identifiers only, no clinical detail) and notify the provider: "{{count}} patients are booked in the time you have blocked. The front desk will contact them before the change is applied."
  4. For each affected appointment, offer a move rather than a cancellation: run workflow 2 restricted to the same service and location, find the three nearest alternative slots, and send "{{contact.first_name}}, we need to move your {{appointment.date}} visit. Here are the closest options: {{reschedule_link}}. Sorry for the disruption: call us on {{custom_values.front_desk}} if none of these work."
  5. Move each opportunity to Rescheduled on rebooking. After all affected appointments are resolved, apply the availability change and confirm to the provider.
  6. Overbook guard, running continuously: if any provider calendar ever shows two clinical appointments overlapping, or a service booked without its required resource calendar, raise an immediate alert to the front-desk lead and the practice manager and create a task "Double-booking detected. Resolve before end of day." Log every occurrence; a rising count means a rule is wrong, not that staff are careless.

Stop and exit conditions: change applied and provider notified; change withdrawn by the provider; task closed by the front desk. The calendar is never modified under booked patients without a human in the loop.

8. Recall and Next-Due Rebooking

Trigger: next_due_date minus 45 days, evaluated nightly.

Conditions: no future appointment for the service; patient_status is not Transferred Out; no triage-human; consent on at least one channel.

Actions in order:

  1. Day 0: email with a continuity-first booking link scoped to assigned_provider: "It has been about a year, {{contact.first_name}}. Dr. {{contact.assigned_provider}}'s schedule is open: {{booking_link}}." No clinical reason stated.
  2. Wait 7 days. If unbooked, SMS: "Time to book your next visit, {{contact.first_name}}? Here is Dr. {{contact.assigned_provider}}'s schedule: {{booking_link}}. Reply STOP to opt out."
  3. Wait 10 days. If unbooked, widen: send a pooled link covering every eligible provider at the home location, since continuity is worth less than attendance at this point.
  4. Wait 14 days. If unbooked, create a front-desk call task. After the call task is closed unbooked, tag lapsed-12mo and hand to the longer-cycle nurture list, capped at one message per quarter.

Stop and exit conditions: appointment booked; opt-out; Transferred Out. Maximum three recall messages per cycle.

9. Daily Schedule Health Report and Weekly Utilization Rollup

Trigger: scheduled daily 06:45 local, plus Monday 07:15 for the weekly rollup.

Actions in order:

  1. Compute, per provider per location: unfilled clinical hours today and for the next 5 business days; appointments unconfirmed for today; bookings in Booked - Unverified starting inside 48 hours; contacts tagged forms-outstanding with a visit inside 72 hours; waitlist depth by service; and any double-booking alerts open.
  2. Email the front-desk lead and practice manager, ordered as a work queue: unverified first, unconfirmed second, unfilled third. Aggregate figures and record identifiers only. No clinical content in a routine internal report.
  3. Branch: if any provider's unfilled clinical hours for today exceed the practice's threshold, add "ACTION: run a same-day waitlist sweep for {{provider}}" and fire workflow 6 manually across that provider's open slots.
  4. Branch: if any booking inside 24 hours is still unverified, add "ACTION: verify now or call the patient" and escalate to the practice manager.
  5. Monday rollup: utilization percentage per provider per location, no-show rate per provider and per service, late-cancel rate, reschedule churn count, waitlist fill rate, average days-to-third-available-slot per service, and new-patient slots offered versus filled. Create a task on the practice manager: "Review the two services with the worst days-to-third-available and decide whether to add capacity or change the rules."

Stop and exit conditions: none. If the report stops arriving, treat it as an outage. This report is how the practice knows the rules engine is still right.

05

What changes

The scheduling rules stop living in one person's memory. A new receptionist can run the desk in a week because the platform refuses the bookings that used to require experience to avoid. Providers get days that match what they actually do. The right duration, the right buffers, the room available when the procedure is booked, so the two-thirty slip stops being structural. Patients self-serve, which means bookings happen at nine at night and on Sunday, outside the hours the phone is answered.

The more valuable change is that capacity becomes visible. Before this build, nobody can tell you which provider is underbooked on a Tuesday or how many new-patient slots went unsold last month. Afterwards it arrives in an email every morning, which turns scheduling from a clerical function into a capacity-management function.

Metrics to watch:

  • Utilization per provider per location: booked clinical minutes over available clinical minutes. Watch the spread across the roster, not just the average; a tight spread is the load balancer working.
  • Unfilled clinical hours per week, and what share the waitlist recovered.
  • No-show rate by provider, by service and by lead time. Lead time is usually the dominant variable and it is the one you can act on.
  • Late-cancel rate and waitlist fill rate: a late cancel that gets backfilled is an inconvenience; one that does not is lost revenue.
  • Confirmation rate by reminder rung. If the 72-hour rung carries most confirmations, the 24-hour rung may be noise you can cut.
  • Days to third-available slot per service, the standard access measure, tracked weekly. It tells you about capacity in a way utilization does not.
  • Share of bookings self-served versus phone-booked, and the trend. This is the staff-time dividend.
  • Mis-booking count: visits that had to be re-typed, re-timed or moved to a different provider after booking. This should fall to near zero; if it does not, the eligibility matrix has a gap.
  • Reschedule churn: appointments moved more than once, which correlates strongly with eventual no-show.
  • Double-booking alerts per month. Target zero. Any non-zero count is a rules defect.
06

Before you start

Prerequisites

  • A written eligibility matrix, signed off by the clinicians, before any calendar is built. For each service: duration, buffers, which providers can deliver it, whether new patients are eligible, required rooms or devices, daily caps, minimum notice and booking horizon. This document is the build. Expect it to take two or three meetings and expect the providers to disagree with each other; resolve it on paper, not in the platform.
  • Provider-level decisions recorded explicitly: who is open to new patients, who has age or scope limits, who refuses pooled booking, who needs an admin block protected.
  • Agreed written policies for attendance, deposits where used, late arrival, and the notice window per service. These must be disclosed to patients at booking and applied consistently; have the practice's own counsel review them.
  • A named owner for the eligibility matrix. Rules drift (a provider changes their procedure day and tells nobody) and someone has to own keeping the platform true.

Integrations

  • Practice management system or EHR for appointment status, patient status and ideally bidirectional appointment sync. If two-way sync is not available, pick one system as the source of truth for slot availability and never let staff book in the other.
  • Google Calendar or Outlook per provider for personal time-off sync, configured busy-only so clinical detail never leaves the clinical system.
  • Insurance eligibility checking, through whatever clearinghouse or verification service the practice already uses, if an API path exists; otherwise the internal verification task is the manual bridge.
  • An internal notification channel such as Slack or Microsoft Teams for staff alerts, used only if it sits inside the practice's covered systems.
  • Telehealth platform, if telehealth is one of the services, so the join link is issued on booking rather than by hand.

Numbers and provisioning

  • Provision a dedicated appointment-messaging number, separate from marketing and separate from the clinical line. Per-location direct dials if the practice has more than two sites.
  • Complete A2P 10DLC brand and campaign registration before go-live. Register appointment reminders as their own campaign with accurate sample messages: use the reminder copy in this guide. Filtered reminders cause no-shows, and the symptom looks like a patient problem rather than a registration problem.
  • Opt-out handling: STOP, STOPALL, UNSUBSCRIBE, CANCEL, END and QUIT all write sms-opted-out and halt SMS immediately. Note the collision between CANCEL as an opt-out keyword and CANCEL as a scheduling intent. Treat it as an opt-out, as the carriers require, and handle appointment cancellation through the tokenized link and the word CHANGE instead. Route opted-out patients to email plus a front-desk call task so they do not silently stop receiving reminders.
  • Quiet hours 08:00-20:00 in the contact's timezone for appointment messaging, with the day-of nudge permitted from 07:00 where the practice opens early. No Sunday sends except a same-day Monday reminder. Confirm applicable state calling and texting windows with the practice's own counsel.
  • Authenticate the sending domain with SPF, DKIM and DMARC before the first reminder email.

Protected health information: operational practice

Scheduling sits right against clinical data, which makes it the easiest place to leak. What follows is operational practice, not legal advice; confirm what applies to your practice with its own compliance counsel or privacy officer.

  • What stays out of SMS and unencrypted email: reason for visit, symptoms, diagnoses, medications, test results, specialty or clinic name where the name itself discloses a condition, and any insurance or identification number. A reminder may say date, time, location, provider name and a neutral service label from an approved list. It may not say "your oncology follow-up" or "your HIV PrEP injection". Review every approved service label with your privacy officer specifically for this reason. Some practice names and service names are themselves disclosures.
  • Minimum necessary, applied to the message body. Put the detail behind an authenticated link rather than in the message. "Your visit details and forms are here: {{secure_link}}" is almost always the safer construction, and it is also better practice because the link can carry more than 160 characters.
  • Identifiers are never collected conversationally. No dates of birth, member IDs, policy numbers, card images or government identifiers over SMS or web chat. Those go only through the authenticated registration form. BO is prompted to refuse and redirect: "I cannot take that over text. Here is a secure link to enter it: {{registration_link}}."
  • Consent, captured and evidenced. Record sms_consent, email_consent, the date and the method of capture. Keep appointment-reminder consent separate from marketing consent, because a patient who unsubscribes from a newsletter must not lose their appointment reminders. Where the practice relies on an exception for treatment-related messaging, have counsel confirm how that interacts with the carrier rules, which apply regardless.
  • A signed business associate agreement must be in place with every vendor that touches patient information on the practice's behalf: the platform, the messaging path, the email sender, calendar sync where appointment data is exposed, the telehealth tool, any middleware such as Zapier or Make if it carries patient data, the chat tool used for internal alerts, and any analytics layer. Walk the data diagram once before go-live and point at each box. If a box has no agreement, keep patient information out of that box, which in practice usually means sending a record identifier and a link rather than content.
  • Calendar sync is a disclosure risk. Sync provider calendars busy-only. An appointment title pushed into a personal calendar can expose a patient name and reason to anyone with shared visibility on that calendar, including a spouse on a family plan.
  • Internal alerts carry identifiers, not charts. Staff notifications should reference a record and an appointment, not a clinical narrative. The person who needs the detail opens the record.
  • Access control. Named accounts, no shared logins, two-factor authentication, role-based restriction so a front-desk user cannot export the full contact database, and confirmation that the platform's audit log records who viewed and changed what. Agree a retention period for scheduling records and conversation transcripts with the privacy officer.
  • Interpreter and accessibility requirements are operational obligations, not nice-to-haves. The interpreter_language field and the interpreter-needed tag exist so the need is attached to the booking and visible on the day. Confirm the practice's specific obligations with counsel.

Scoping

This is an advanced build, and the time goes into the eligibility matrix and the practice management integration rather than the automations. The number of providers, locations, services and shared resources drives the effort more than patient volume does. To scope it against your own roster, book a call at bookings.appbo.io.

Field notes

Build it with us.

Every build on this page is something we configure, test and hand over with the SOPs your team needs to run it.

Book a call