Skip to content

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

  1. GET Schedule?actor=PractitionerRole/<id>&active=true — find the provider's calendar(s)
  2. GET Slot?schedule=Schedule/<id>&status=free&start=ge<date> — find free slots in a window
  3. User picks a slot in the UI; booking client PATCHes Slot.status = busy-tentative
  4. User confirms; booking client POSTs an Appointment with .slot[] = [Slot/<id>], then PATCHes Slot.status = busy
  5. (If user abandons) a hold-timeout job downgrades stale busy-tentative slots back to free

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 calendar
  • Location 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