Project

General

Profile

New feature / Change #8924

Updated by Olivier Bitsch 2 months ago

   ## Summary 
 
   FHIR API integration for Appointment and Encounter resources. 

 

   ## Description 
 
   As an external EMR system, I need FHIR R4 compliant API endpoints to create appointments and retrieve encounters, enabling interoperability with healthcare systems like OpenEMR. 

 

   ## Requirements 

 

   **FHIR Endpoints:** 
 
   POST     /api/fhir/Appointment             → Create appointment (returns FHIR Appointment) 
 
   GET      /api/fhir/Appointment             → List appointments (returns FHIR Bundle) 
 
   GET      /api/fhir/Appointment/:id         → Get appointment (returns FHIR Appointment) 
 
   PUT      /api/fhir/Appointment/:id         → Update appointment 
 
   DELETE /api/fhir/Appointment/:id         → Cancel appointment 

 

   GET      /api/fhir/Encounter               → List encounters (returns FHIR Bundle) 
 
   GET      /api/fhir/Encounter/:id           → Get encounter (returns FHIR Encounter) 

 

   **FHIR → Internal Model Mapping:** 

 

   | FHIR Resource | Internal Model | 
 
   |---------------|----------------| 
 
   | Appointment | Appointment + Consultation | 
 
   | Appointment.participant (Patient) | Participant (user, email, phone) | 
 
   | Appointment.participant (Practitioner) | Participant (doctor) | 
 
   | Encounter | Consultation | 

 

   **Appointment Mapping:** 
 
   | FHIR Field | Internal Field | 
 
   |------------|----------------| 
 
   | Appointment.start | Appointment.scheduled_at | 
 
   | Appointment.end | Appointment.end_expected_at | 
 
   | Appointment.status | Appointment.status | 
 
   | Appointment.serviceType | Type (Online/InPerson) | 
 
   | Appointment.participant[Patient] | Participant (beneficiary) | 
 
   | Appointment.participant[Practitioner] | Participant (doctor) | 
 
   | Appointment.reason | Consultation.description | 
 
   | Appointment.identifier | External reference (store in metadata) | 

 

   **Encounter Mapping:** 
 
   | FHIR Field | Internal Field | 
 
   |------------|----------------| 
 
   | Encounter.status | Consultation status | 
 
   | Encounter.period.start | Consultation.created_at | 
 
   | Encounter.period.end | Consultation.closed_at | 
 
   | Encounter.appointment | Reference to Appointment | 
 
   | Encounter.subject | Consultation.beneficiary | 
 
   | Encounter.participant | Consultation.owned_by (doctor) | 

 

   **Status Mappings:** 

 

   | FHIR Appointment | Internal Status | 
 
   |------------------|-----------------| 
 
   | proposed | - | 
 
   | booked | Scheduled | 
 
   | cancelled | Cancelled | 
 
   | fulfilled | (completed) | 

 

   | FHIR Encounter | Internal Status | 
 
   |----------------|-----------------| 
 
   | planned | pending | 
 
   | in-progress | active | 
 
   | finished | closed | 

 

   **Request Body Example (Create Appointment):** 
 
   ```json 
 
   { 
   
     "resourceType": "Appointment", 
   
     "status": "booked", 
   
     "start": "2025-01-15T10:00:00Z", 
   
     "end": "2025-01-15T10:30:00Z", 
   
     "serviceType": [{"coding": [{"code": "online"}]}], 
   
     "identifier": [{"system": "openemr", "value": "APT-12345"}], 
   
     "participant": [ 
     
       { 
       
         "actor": { 
         
           "reference": "#patient1", 
         
           "type": "Patient" 
       
         }, 
       
         "status": "accepted" 
     
       }, 
     
       { 
       
         "actor": { 
         
           "reference": "#practitioner1", 
         
           "type": "Practitioner" 
       
         }, 
       
         "status": "accepted" 
       } 
     } 
   ], 
   
     "contained": [ 
     
       { 
       
         "resourceType": "Patient", 
       
         "id": "patient1", 
       
         "name": [{"family": "Doe", "given": ["John"]}], 
       
         "telecom": [ 
         
           {"system": "email", "value": "john@example.com"}, 
         
           {"system": "phone", "value": "+1234567890"} 
         ] 
       ] 
     }, 
     
       { 
       
         "resourceType": "Practitioner", 
       
         "id": "practitioner1", 
       
         "name": [{"family": "Smith", "given": ["Dr"]}], 
       
         "telecom": [{"system": "email", "value": "dr.smith@clinic.com"}] 
       } 
     } ] 
   ] 
 } 

 

   Response (FHIR Appointment): 
 
   { 
   
     "resourceType": "Appointment", 
   
     "id": "123", 
   
     "status": "booked", 
   
     "start": "2025-01-15T10:00:00Z", 
   
     "end": "2025-01-15T10:30:00Z", 
     ... 
   ... 
 } 

 

   Validation Rules: 
 
   - Patient participant required with name and contact (email or phone) 
 
   - Practitioner participant required with email (must exist in system) 
 
   - Start date required and must be in future 
 
   - Cannot update after consultation started 

 

   Search Parameters: 
 
   - identifier - Search by external system ID 
 
   - appointment.identifier - Search encounters by appointment ID 

 

   Acceptance Criteria 

 

   - POST /fhir/Appointment creates Consultation + Appointment + Participants 
 
   - POST /fhir/Appointment returns valid FHIR Appointment response 
 
   - GET /fhir/Appointment returns FHIR Appointment or Bundle 
 
   - GET /fhir/Encounter returns FHIR Encounter or Bundle 
 
   - Search by external identifier works 
 
   - Invalid FHIR body returns 400 with validation errors 
 
   - Practitioner not in system returns 400 error 
 
   - Status mappings work bidirectionally 
 
   - Cannot modify appointment with active consultation 

 

   Notes 

 

   - Store original FHIR body for audit/reference 


 


   ---

Back