FHIR → Oscar Mapping (Schedule + Slot + Appointment)¶
This page describes how FHIR-side writes (booking actions taken against the FHIR server) flow back to OscarPro. The structured mapping is in fhir-to-oscar.yaml; this page narrates the write paths + their limitations.
TL;DR — most of Schedule/Slot is read-only¶
Schedule and Slot resources are materialised by the Oscar-side converter from templates and appointment data. They are not first-class records in OscarPro. As a result, most fields are read-only from the FHIR side — the source system of record is OscarPro, and the converter is the sole writer.
The exceptions are:
Slot.status— booking system PATCHes to manage the busy/busy-tentative/free lifecycleSlot.overbooked— booking system sets on intentional overbookAppointment.*— full write path (this is the primary booking flow)
The write paths that matter¶
1. Booking an appointment from a free Slot¶
POST /Appointment
{
"resourceType": "Appointment",
"status": "booked",
"slot": [{ "reference": "Slot/42-20260601-36" }],
"start": "2026-06-01T09:00:00-04:00",
"end": "2026-06-01T09:15:00-04:00",
"participant": [ ... Patient, PractitionerRole, Location ... ]
}
What happens behind the scenes:
- The FHIR server creates the Appointment resource
- The Oscar-side write-back process inserts a row into the OscarPro
appointmenttable (start_time, end_time, provider_no, demographic_no, etc.) - The booking client typically follows up with
PATCH Slot.status = busy(next section) - On the next converter re-emission,
Slot.statusis recomputed from the appointment-overlay logic — it'll showbusybased on the new row, regardless of whether the booking system PATCHed it
Note: the Appointment.slot linkage is not persisted back to OscarPro in Phase 1. OscarPro's appointment table has no Slot reference column; the linkage exists only in the FHIR layer. This is acceptable because the linkage can be reconstructed at re-emission time from the overlay logic.
2. Slot status PATCH lifecycle¶
The booking system PATCHes Slot.status as part of the booking flow:
| When | PATCH | Notes |
|---|---|---|
| User starts a hold | Slot.status = busy-tentative |
Booking-system-only; converter never writes this value |
| User confirms | Slot.status = busy + POST Appointment |
Effectively recomputed on next converter run too |
| User abandons / hold times out | Slot.status = free (via reconciler job) |
Booking-system-owned |
| Appointment cancelled | Slot.status = free (or wait for converter re-emission) |
Either path works |
These PATCHes live only in the FHIR layer between converter re-emissions. OscarPro has no busy-tentative analogue.
3. Cancelling an Appointment¶
PATCH /Appointment/<id>
{ "op": "replace", "path": "/status", "value": "cancelled" }
What happens:
- Appointment.status flips to
cancelledin the FHIR server - Oscar-side write-back updates the
appointmentrow's status flag (e.g. 'C') - On the next converter re-emission, the appointment-overlay logic no longer treats this slot as busy → Slot.status reverts to
free
What you CANNOT do¶
| Action | Why |
|---|---|
Edit Slot.start / Slot.end |
Slot windows are fixed by the template. Change the template in OscarPro instead. |
Edit Schedule.actor |
Provider/location assignment is a source-system concern (Phase 1). |
| Create a Slot directly via the FHIR server | Slots are materialised; the converter is the sole writer. Creating one manually will be overwritten on next re-emission. |
Persist Slot.status = busy-tentative durably |
The converter doesn't write this status, and OscarPro has no analogue. If a booking system needs hold state to survive converter re-emissions, store it out-of-band. |
Concurrency¶
The main race condition is converter re-emission vs booking-system status writes. Mitigation:
- Booking system SHOULD use
If-Matchagainst the Slot's ETag before PATCHing - If the PATCH conflicts (the converter overwrote), the booking system re-reads and retries
- Phase 1 does NOT enforce optimistic concurrency at the profile level — it's a recommended practice, not a profile invariant
Worked examples¶
- Booking flow → with-slot Appointment — references the busy Slot
- Walk-in Appointment — no Slot reference
Related¶
oscar-to-fhir.md— forward mapping (template tables → FHIR)booking-flow-design.md— full status state machine + writer ownershipconverter-contracts.md— what the migrated converter does on re-emission