Project

General

Profile

Actions

New feature / Change #8924

open

Epics #8706: Bootstrap project and recover all feature we have so far (milestone #1)

Implement Fhir for external connectivity with health ecosystems

Added by Olivier Bitsch about 2 months ago. Updated about 1 month ago.

Status:
In Study
Priority:
Normal
Assignee:
Category:
-
Start date:
11/24/2025
Due date:
% Done:

0%

Estimated time:
80:00 h

Description

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):

{
  "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

Actions

Also available in: Atom PDF