Skip to content

Appointment Profile

Canonical../StructureDefinition/nexus-emr-core-appointment
Statusdraft · 1.26.0
BaseAppointment (constraint)
SourceFSH · JSON

Minimal Nexus EMR profile for Appointment resources, primarily for mapping status, start date (Last Visit Date), and required patient/practitioner participants. Assumes filtering for status='fulfilled' happens during data retrieval/processing. Contains embedded aliases and invariants.

TypedFhir API / Pydantic schema

The typed accessor surface Appointment exposes for Appointment — 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 AppointmentSchemamodel_json_schema() is a structured-output / tool definition; instantiating validates an extraction. Generated source.

class AppointmentSchema(BaseModel):
    """AI-facing shape of the Appointment 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")

    status: Literal[
        "arrived",
        "booked",
        "cancelled",
        "checked-in",
        "entered-in-error",
        "fulfilled",
        "noshow",
        "pending",
        "proposed",
        "waitlist",
    ] | None = Field(
        None,
        description=(
            "Where the appointment is in its lifecycle. The overall status of the Appointment. "
            "Indicates confirmation status and attendance. Note: Not all EMRs support a "
            "'fulfilled' status. In those cases we will only have a 'booked', 'arrived' or "
            "'checked in' status. For those consumers of FHIR data that are depending on this "
            "(including CPAR), a reasonable workaround is checking for `fulfilled || ((booked || "
            "arrived || checked in) && before yesterday)`. Appointment.status — 1..1"
        ),
    )
    cancelation_reason: Concept | None = Field(
        None,
        description=(
            "The coded reason for the appointment being cancelled. The coded reason for the "
            "appointment being cancelled. This is often used in reporting/billing/futher "
            "processing to determine if further actions are required, or specific fees apply. "
            "Appointment.cancelationReason — 0..1"
        ),
    )
    service_category: Concept | None = Field(
        None,
        description=(
            "Service category with raw code support. A broad categorization of the service that "
            "is to be performed during this appointment. RECOMMENDED: Standard terminology codes "
            "when available OPTIONAL: Raw EMR codes for source system preservation. 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). "
            "Appointment.serviceCategory — 0..*"
        ),
    )
    service_type: Concept | None = Field(
        None,
        description=(
            "Service type with raw code support. The specific service that is to be performed "
            "during this appointment. RECOMMENDED: Standard terminology codes when available "
            "OPTIONAL: Raw EMR codes for source system preservation 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). Note: For a provider "
            "to provider appointment the code \"FOLLOWUP\" may be appropriate, as this is expected "
            "to be discussing some patient that was seen in the past. Appointment.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. Appointment.specialty "
            "— 0..*. codes (preferred): 394539006 | 394576009 | 394577000 | 394578005 | 394579002 "
            "| 394580004 | 394581000 | 394582007 | …"
        ),
    )
    appointment_type: Concept | None = Field(
        None,
        description=(
            "Appointment type with raw code support. The style of appointment or patient that has "
            "been booked (e.g., routine, walk-in, checkup). RECOMMENDED: v2 Appointment Reason "
            "Codes or other standard terminology when available OPTIONAL: Raw EMR codes for "
            "source system preservation. 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). "
            "Appointment.appointmentType — 0..1. codes (preferred): CHECKUP | EMERGENCY | "
            "FOLLOWUP | ROUTINE | WALKIN"
        ),
    )
    reason_code: Concept | None = Field(
        None,
        description=(
            "Appointment reason with raw code support. Coded reason this appointment is "
            "scheduled. RECOMMENDED: Encounter Reason Codes or other standard terminology when "
            "available OPTIONAL: Raw EMR codes for source system preservation. 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). "
            "Appointment.reasonCode — 0..*"
        ),
    )
    start: FuzzyDate | None = Field(
        None,
        description=(
            "When appointment is to take place - Maps to A12_Last Visit Date. Date/Time that the "
            "appointment is scheduled to start. Note: This is the scheduled start time, not "
            "necessarily when the patient was actually seen. Appointment.start — 1..1"
        ),
    )
    slot: Reference | None = Field(
        None,
        description=(
            "Slot(s) this appointment was booked into. The Slot resource(s) that this appointment "
            "was created from. When a booking client creates an Appointment in response to a user "
            "selecting a free Slot, it SHOULD populate this reference. The booking system is "
            "responsible for transitioning the referenced Slot's status from 'free' to 'busy'. "
            "Walk-in and historical appointments (imported from EMRs predating the Slot model) "
            "will not have a Slot reference — `.slot` is therefore `0..*`, not `1..*`. "
            "Appointment.slot — 0..*"
        ),
    )
    created: FuzzyDate | None = Field(
        None,
        description=(
            "When the appointment record was initially created. The date/time the appointment "
            "record was initially created (native R4 Appointment.created). Pairs with the "
            "createdBy extension, which carries the authoring agent. Note: This property is "
            "required for many use cases where the age of an appointment is considered in "
            "processing workflows for scheduling and billing of appointments. Appointment.created "
            "— 0..1"
        ),
    )
    participant: dict | None = Field(
        None,
        description=(
            "Participants involved in appointment. List of participants involved in the "
            "appointment: the patient, the provider, and the location. The provider participant "
            "references a **Practitioner** -- the primary provider identity in this IG. A "
            "**PractitionerRole** reference is also permitted for the cases where the clinic/role "
            "binding is what is being asserted (multi-org providers, role-scoped booking), but "
            "Practitioner is the expected default and the shape primary-care writers should emit. "
            "An actor may also be identifier-only (no `reference`), per the Nexus EMR "
            "logical-reference model. Consumers must handle that: see the `-example` and "
            "`-telephone-example` instances. Note: Must include exactly one location. Can contain "
            "zero or one patient and zero or one provider (Practitioner, or PractitionerRole "
            "where the role binding matters). Appointment.participant — 1..*"
        ),
    )
    end: FuzzyDate | None = Field(
        None,
        description=(
            "When appointment is to conclude. Date/Time that the appointment is to conclude. "
            "Salient field — end"
        ),
    )
    description: str | None = Field(
        None,
        description=(
            "Shown on a subject line in a meeting request, or appointment list. The brief "
            "description of the appointment as would be shown on a subject line in a meeting "
            "request, or appointment list. Detailed or expanded information should be put in the "
            "comment field. Salient field — description"
        ),
    )