Scheduling — Overview¶
The Polaris scheduling feature lets booking UIs discover bookable time windows for a clinic/provider and create FHIR Appointment resources that link back to the slot consumed. It complements the existing PolarisCoreAppointment profile (which models the booked appointment) by introducing two new profiles for availability: PolarisCoreSchedule and PolarisCoreSlot.
Why this exists¶
Before this feature, a booking UI had no FHIR-native way to ask:
- "What time windows are open on this provider's calendar next week?"
- "What's the duration of each available slot, and what service type does it support?"
- "Is this slot bookable now, or held tentatively?"
The only options were to (a) reach into the source EMR's REST API directly (bypassing the FHIR layer), or (b) infer availability by querying for the absence of Appointment resources — which can't distinguish "no booking yet" from "no slot exists." Both are bad.
PolarisCoreSchedule + PolarisCoreSlot close that gap with a profile-level, queryable model.
Resources at a glance¶
| Resource | Profile | Purpose |
|---|---|---|
Schedule |
PolarisCoreSchedule |
The container — a provider's, room's, or service line's calendar |
Slot |
PolarisCoreSlot |
An individual bookable time window with status (free / busy / busy-tentative / busy-unavailable) |
Appointment |
PolarisCoreAppointment |
The booked appointment. As of IG 1.10.0, includes Appointment.slot 0..* MS → PolarisCoreSlot |
Typical booking flow¶
GET Schedule?actor=PractitionerRole/<id>&active=true— find the provider's calendar(s)GET Slot?schedule=Schedule/<id>&status=free&start=ge<date>— find free slots in a window- User picks a slot in the UI; booking client PATCHes
Slot.status = busy-tentative - User confirms; booking client POSTs an
Appointmentwith.slot[] = [Slot/<id>], then PATCHesSlot.status = busy - (If user abandons) a hold-timeout job downgrades stale
busy-tentativeslots back tofree
See Booking Flow Design for the full sequence + the writer-ownership contract.
Source data¶
Phase 1 source: OscarPro scheduletemplate family.
OscarPro represents recurring availability as templates: one scheduletemplate row per (provider, template_name) carries a timecode string where each character is a single-character code that maps to a duration via scheduletemplatecode. The Oscar-side converter materialises these templates into concrete daily Slot instances. See Oscar → FHIR Mapping for the detailed mapping.
Other EMRs (Juno, etc.) are explicitly out of scope for Phase 1 — see "Out of scope" below.
Design highlights¶
Flexible Schedule.actor¶
The actor element is sliced into three optional slices with an at-least-one invariant:
PractitionerRole 0..1 MS— most common; provider-owned calendarLocation 0..1 MS— room / equipment schedules (e.g. MRI bookings)HealthcareService 0..1 MS— service-line schedules (e.g. walk-in clinic, telephone triage)
This avoids baking provider-only assumptions into the model and lets later EMR integrations represent room or service-line booking without a profile change.
Slot identifier strategy¶
Slots are materialised, not stored. To make them cacheable by reference, Slot.id and Slot.identifier[polarisId].value use a deterministic pattern: <provider_no>-<yyyyMMdd>-<slot-index>. Re-running the converter for the same (provider, date) produces identical resources.
Slot.status writer ownership¶
The IG documents — but does NOT enforce — a writer-ownership contract:
- Converter writes
free/busy/busy-unavailable - Booking system writes
busy-tentative(during holds) - Converter never writes
busy-tentative
The contract lives in the published profile intro markdown so it ships with the IG, not just internal docs. If race conditions appear in production, If-Match optimistic concurrency on the booking system is the IG-level mitigation (not currently profile-enforced).
Out of scope (Phase 1)¶
| Item | Rationale |
|---|---|
| Juno scheduling | OscarPro is the only source in Phase 1, matching the Phase 1 billing IG scope. The Juno device example already published in the IG is a billing-side artifact unrelated to this work. |
| Schedule recurrence | FHIR R4 Schedule has no native recurrence element. Recurring weekly templates are materialised by the converter into concrete daily Slots — a series, not a recurrence rule. A recurrence extension is follow-up scope. |
| AppointmentResponse | Models patient acceptance/decline of a proposed slot. Useful for a formal confirmation step in a busy-tentative → busy flow; tentative future scope. Phase 1 represents confirmation via Appointment status transitions. |
Custom slot-window SearchParameter |
A composite range search (find slots overlapping a window) is deferred until a booking client confirms need. Base FHIR search params cover the MVP. |
| Patient-facing booking app implementation | The IG is the spec; the patient/booking app is a separate effort. This IG provides the contract. |
Implementation guide¶
- Booking Flow Design — sequence diagram + status-transition contract
- Oscar → FHIR Mapping —
scheduletemplate/scheduletemplatecode/scheduledate→Schedule+Slot - FHIR → Oscar Mapping — reverse mapping; what's read-only on the IG side
- Converter Migration Spec — the 10 deltas required on the existing OscarPro converter
- OscarPro Schema Notes — FHIR-19 spike findings on the source schema