Slot Profile¶
| Canonical | ../StructureDefinition/nexus-emr-core-slot |
|---|---|
| Status | draft · 1.26.0 |
| Base | Slot (constraint) |
| CQL primary code path | serviceType — what this means |
| Source | FSH · JSON |
Minimal Nexus EMR profile for Slot resources — an individual bookable time window owned by a Schedule. Slots are materialised from recurring templates (Phase 1: OscarPro scheduletemplate rows) into concrete date+time instances. Booking clients select a free Slot, create an Appointment referencing it, and the booking system transitions the Slot's status.
TypedFhir API / Pydantic schema
The typed accessor surface Slot exposes for Slot — generated from this IG's compiled profile; each typed accessor has a validating raw-FHIR twin (xRaw) where marked. The three ports are parity-enforced.
The AI-facing shape: from typed_fhir.facade.generated.schemas import SlotSchema — model_json_schema() is a structured-output / tool definition; instantiating validates an extraction. Generated source.
class SlotSchema(BaseModel):
"""AI-facing shape of the Slot profile: the facade's typed accessor
surface (curated + salient fields) as a pydantic model. `model_json_schema()` is a
structured-output / tool schema; instantiating validates an extraction."""
model_config = ConfigDict(extra="forbid")
service_category: Concept | None = Field(
None,
description=(
"Service category with raw code support. A broad categorization of the service "
"offered in this slot. RECOMMENDED: Standard terminology codes when available "
"OPTIONAL: Raw EMR codes for source system preservation. The rawCode slice is `0..*` "
"(not `1..*`) because the OscarPro source converter tolerates missing "
"`scheduletemplatecode` lookups — slots can be emitted without a rawCode mapping. "
"Note: Where this code was mapped from a source system's own vocabulary, carry the "
"raw coding alongside the mapped one, flagged `userSelected = true`. See [Carrying "
"the raw code](../guide/patterns/raw-codes.md). "
"Slot.serviceCategory — 0..*"
),
)
service_type: Concept | None = Field(
None,
description=(
"Service type with raw code support. The specific service offered in this slot. For "
"OscarPro-sourced slots, the rawCode slice is populated from the corresponding "
"`scheduletemplatecode` row (mapped via the single-character timecode value). The "
"rawCode slice is `0..*` (not `1..*`) — see serviceCategory rationale above. Note: "
"Where this code was mapped from a source system's own vocabulary, carry the raw "
"coding alongside the mapped one, flagged `userSelected = true`. See [Carrying the "
"raw code](../guide/patterns/raw-codes.md). Slot.serviceType "
"— 0..*"
),
)
specialty: Concept | None = Field(
None,
description=(
"The specialty of a practitioner that would be required to perform the service "
"requested in this appointment. The specialty of a practitioner that would be "
"required to perform the service requested in this appointment. Slot.specialty — "
"0..*. codes (preferred): 394539006 | 394576009 | 394577000 | 394578005 | 394579002 | "
"394580004 | 394581000 | 394582007 | …"
),
)
appointment_type: Concept | None = Field(
None,
description=(
"Appointment type that fits this slot. The style of appointment this slot is intended "
"for (e.g. routine, walk-in, checkup). Note: `Slot.appointmentType` and "
"`Appointment.appointmentType` are independent in this IG — a booking client MAY "
"create an Appointment with a different appointmentType than the slot it consumed. "
"This supports flexible slot inventory (e.g. a clinic that double-purposes a slot for "
"either routine or walk-in). RECOMMENDED that booking clients copy the slot's "
"appointmentType to the resulting Appointment but not REQUIRED. Note: Where this code "
"was mapped from a source system's own vocabulary, carry the raw coding alongside the "
"mapped one, flagged `userSelected = true`. See [Carrying the raw "
"code](../guide/patterns/raw-codes.md). Slot.appointmentType "
"— 0..1. codes (preferred): CHECKUP | EMERGENCY | FOLLOWUP | ROUTINE | WALKIN"
),
)
schedule: Reference | None = Field(
None,
description=(
"The Schedule this Slot belongs to. The Schedule resource that this Slot is derived "
"from. Required per base FHIR R4 (Slot.schedule cardinality 1..1). Slot.schedule — "
"1..1"
),
)
status: Literal[
"busy",
"busy-tentative",
"busy-unavailable",
"entered-in-error",
"free",
] | None = Field(
None,
description=(
"busy | free | busy-unavailable | busy-tentative | entered-in-error. The free/busy "
"state of the slot. The IG does NOT constrain who writes this field. Phase 1 contract "
"(see profile intro): - Oscar-side converter writes 'free' (default) or 'busy' (when "
"an appointment row overlaps the slot window) or 'busy-unavailable' (within-day "
"blockout from ScheduleDate.available != '1'). - Booking system writes "
"'busy-tentative' during a hold flow, then transitions to 'busy' on confirm or back "
"to 'free' on hold timeout. - The converter NEVER writes 'busy-tentative' — that "
"value is the booking system's exclusively. Slot.status — 1..1"
),
)
start: FuzzyDate | None = Field(
None,
description=(
"Slot start instant (UTC with offset). Date/Time at which this slot starts. "
"Source-system local time is converted to UTC with offset by the converter (Phase 1: "
"province → IANA TZ lookup based on the clinic's Location.address). Slot.start — 1..1"
),
)
end: FuzzyDate | None = Field(
None,
description=(
"Slot end instant (UTC with offset). Date/Time at which this slot ends. For a slot "
"derived from a 15-minute template grid, end = start + 15 minutes. Slot duration is "
"constant within a template (computed as 1440 / timecode.length() minutes per slot). "
"Slot.end — 1..1"
),
)
overbooked: bool | None = Field(
None,
description=(
"Whether the slot is intentionally overbooked. Set by the booking system when more "
"than one appointment is booked into the same slot window (e.g. walk-in over a held "
"slot). Informational; the IG does not enforce a maximum. Slot.overbooked — 0..1"
),
)
comment: str | None = Field(
None,
description=(
"Free-text notes about the slot (e.g. blockout reason). Used to carry the "
"ScheduleDate.reason text when a within-day blockout produces a busy-unavailable "
"Slot. Slot.comment — 0..1"
),
)