Scheduling
Fanoni Scheduling is currently in alpha.
Welcome to the Fanoni Scheduling documentation. We currently support a range of scheduling operations that are available via the FHIR API. The following sections walk through the FHIR resources that are used to model scheduling and how the operations interact with them.
We like to separate scheduling into four main steps:
Step 1: Defining Service Types
Decide what types of appointments you would like to offer. Create a HealthcareService resource for each type. Set a SchedulingParameters extension on each to define attributes like the length of the visit.
Mark which Schedule resources should be able to schedule appointments of that type by setting a reference to the HealthcareService in the Schedule.serviceType attribute.
Referencing a HealthcareService
In future FHIR revisions, Schedule.serviceType will have type CodeableReference(HealthcareService). In Fanoni's R4 implementation, this is achieved by including an extension on a CodeableConcept in that attribute.
{
resourceType: 'Schedule',
actor: [
{
reference: 'Practitioner/dr-alice-smith',
},
],
serviceType: [
{
coding: [{ code: 'office-visit' }],
extension: [
{
url: 'https://medplum.com/fhir/service-type-reference',
valueReference: {
reference: 'HealthcareService/5d02acfd-fbe8-4537-84e4-31f5116be105',
display: 'Office Visit',
},
},
],
},
],
};
Step 2: Defining Availability
The resources used to model availability for a provider, location, or device and the different service-specific scheduling parameters that can be defined.
The simplest version is a single schedule with a single practitioner and a single service type:
- Defining availability at the actor level — When a provider, location, or device is available via Schedule.
- Defining availability at the service level — Default duration, buffers, and alignment per appointment type via HealthcareService.
Step 2: Matching Availability
Based on the availability defined in the previous step, we can now find available appointment slots. This is done via the $find operation.
| Operation | Description | Status |
|---|---|---|
$find | Find available appointment slots | Alpha |
Step 3: Consuming Availability
Once a desired slot has been found, the appointment booking process can be handled in several steps.
| Operation | Description | Status |
|---|---|---|
$book | Book an appointment | Alpha |
$hold | Temporarily hold a slot | In Development |
$cancel | Cancel an appointment | In Development |
Key FHIR Resources
| Resource | Purpose |
|---|---|
Schedule | Represents a provider's, room's, or device's availability. Each Schedule belongs to exactly one actor. |
Slot | A specific time block on a Schedule. Only exists in the datastore for booked or blocked time — free slots are computed on demand. |
Appointment | A confirmed booking linking one or more Slots to a patient and provider. |
HealthcareService | Defines default scheduling parameters (duration, buffers, alignment) for a service type, shared across multiple providers. |
Fanoni Scheduling FHIR Model Design Decisions
Scheduling can be built in FHIR in many different ways. The key design decisions in Meduplum's specific scheduling FHIR model are:
- Recurring availability does not require pre-generated slots: Synthetic
Slotresources are computed on-demand by$findas drafted resources that are not persisted in the datastore until an Appointment is booked. This means you don't need to maintain a bulk set of Slot resources across a planning horizon.
Available Slots can still be persisted for one time availability.
-
One-to-one actor–Schedule relationship: Fanoni's scheduling system requires each
Scheduleto have exactly one actor. While the FHIR spec allowsSchedule.actorto hold multiple references, Fanoni enforces a single-actor constraint so that availability can be unambiguously resolved per resource. See Defining Availability for the full model. -
Actors must have a timezone: Every actor referenced by a Schedule — whether a
Practitioner,PractitionerRole,Location, orDevicemust have a timezone set via the FHIR timezone extension:
{
url: 'http://hl7.org/fhir/StructureDefinition/timezone',
valueCode: 'America/New_York'
}