ediverse Explore the platform

Spotlight PEPPOL BIS Billing 3.0 The EU e-invoicing mandate is here — France Sept 2026, Belgium Jan 2026, Germany 2025.

Slot — Booking slot

The atomic building block of FHIR scheduling. A Slot is a time window inside a Schedule with a free / busy status, ready to be consumed by an Appointment.

Purpose of the resource

Slot represents a time interval within a Schedule that may be booked as an Appointment. It's the minimum granularity in the FHIR model: a Slot carries a startend range, a status, and a reference to the parent Schedule. An Appointment can consume a single Slot (a 15-minute visit) or multiple consecutive Slots (a 90-minute procedure consumes six 15-minute Slots).

Slot mirrors Schedule (its container) and Appointment (the booking that consumes it). The crucial consistency rule: as soon as an Appointment flips to booked, every Slot it references must flip to busy. If the Appointment is cancelled, the Slot(s) revert to free.

Key fields

The R5 StructureDefinition lists eleven top-level elements:

FieldTypeCardinalityRole
identifierIdentifier[]0..*External identifiers of the slot.
serviceCategoryCodeableConcept[]0..*Broad category of service offered on this Slot. Typically inherits from the parent Schedule.
serviceTypeCodeableReference[]0..*Specific service type (first visit, follow-up, urgent care…).
specialtyCodeableConcept[]0..*Medical specialty (SNOMED CT).
appointmentTypeCodeableConcept[]0..*Eligible Appointment type (WALKIN, ROUTINE, EMERGENCY… — v2-0276).
scheduleReference(Schedule)1..1Mandatory reference to the parent Schedule.
statuscode1..1Slot state. Modifier.
startinstant1..1Slot start datetime (second precision + mandatory timezone).
endinstant1..1Slot end datetime.
overbookedboolean0..1Indicates a Slot allows overbooking (two Appointments may reference the same Slot).
commentstring0..1Human-readable notes for the front desk / app.

Slot statuses

The status code is mandatory. Official ValueSet SlotStatus, Required binding:

CodeMeaning
busyThe slot is taken: already booked by one or more Appointments.
freeThe slot is open: the client app may propose it to the patient.
busy-unavailableThe slot cannot be booked — time off, lunch break, exceptional closure. Distinct from busy (which implies there is an Appointment).
busy-tentativeThe slot has a tentative booking — an Appointment in pending or proposed.
entered-in-errorSlot created in error. Skip.

JSON example

A free 15-minute slot in Dr Adam Careful's Schedule on 22 May 2026 at 09:15 Paris time. Category "General Practice", type "Walk-in".

json slot-example.json
{
  "resourceType": "Slot",
  "id": "example",
  "identifier": [{
    "system": "http://example.org/identifiers/slots",
    "value": "123"
  }],
  "serviceCategory": [{
    "coding": [{
      "system": "http://terminology.hl7.org/CodeSystem/service-category",
      "code": "17",
      "display": "General Practice"
    }]
  }],
  "serviceType": [{
    "concept": {
      "coding": [{
        "system": "http://example.org/service-type",
        "code": "57",
        "display": "Immunization"
      }]
    }
  }],
  "appointmentType": [{
    "coding": [{
      "system": "http://terminology.hl7.org/CodeSystem/v2-0276",
      "code": "WALKIN",
      "display": "A previously unscheduled walk-in visit"
    }]
  }],
  "schedule": { "reference": "Schedule/example" },
  "status": "free",
  "start": "2026-05-22T09:15:00+02:00",
  "end": "2026-05-22T09:30:00+02:00",
  "comment": "15-minute slot — first appointment of the morning."
}

Worth pointing out in this example:

  • schedule is 1..1 — an orphan Slot doesn't exist: it always belongs to a Schedule.
  • The serviceCategory, serviceType, specialty fields duplicate the parent Schedule — their presence here enables fine-grained indexing (e.g. a "General Practice" Schedule with a few "Vaccination"-purpose Slots).
  • appointmentType constrains which Appointment type may consume this Slot — useful to reserve a band for new patients.
  • status is free: the patient app may propose it.

Searching slots

Typical queries from a booking app:

  • GET /Slot?schedule=Schedule/example&status=free&start=ge2026-05-22 — free slots in a given Schedule from a date.
  • GET /Slot?schedule.actor=Practitioner/example&status=free — free slots across all Schedules for a practitioner (FHIR chained search).
  • GET /Slot?service-type=57&specialty=394814009&status=free — search by service type and specialty, practitioner-agnostic.
  • GET /Slot?_count=20&_sort=start&status=free&start=ge2026-05-22&start=lt2026-05-29 — pagination + sort + one-week window.

The Argonaut Scheduling and US Core Scheduling profiles encapsulate those queries in a $find operation exposed on the server root or on Schedule.

Common pitfalls

  • Slot without schedule1..1 cardinality. Rejected by the validator.
  • Slot where end < start — invariant slt-1: end must be later than start. Silent error on some servers.
  • Slot and Appointment out of sync — a booked Appointment referencing a free Slot is a business inconsistency. Synchronization is the server's responsibility — typically a database trigger or a FHIR PreCreate hook.
  • Slot busy without an Appointment — the inverse: a slot marked busy with no Appointment referencing it. Only legitimate with status=busy-unavailable (break, time off).
  • Slot overlaps — FHIR does not forbid two overlapping Slots. Legitimate to model a pairing ("two clinicians on the same hour") but to avoid in a single-practitioner agenda.
  • Missing timezone — the FHIR instant type requires an offset. 2026-05-22T09:15:00 is rejected.
  • overbooked=true but status=busy — semantic inconsistency. An overbooked Slot should not flip to busy while it still accepts additional bookings.

See also: the FHIR R5 index.