Dominique Hallan
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.

      Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Explore these features while you wait
      Complete general settings
      Bookmark and like published notes
      Write a few more notes
      Complete general settings
      Write a few more notes
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Epic FHIR API Mapping Document ## Overview This document maps Epic FHIR R4 API endpoints to the frontend and backend requirements for the Empower Healthcare platform. It provides concrete field mappings, API endpoints, and data flows needed for implementation. **FHIR Version:** R4 **Authentication:** OAuth 2.0 / SMART on FHIR **Base URL Pattern:** `https://{epic-host}/api/FHIR/R4/` ## High-Level Architecture ```mermaid graph TB Frontend[React Frontend] --> Backend[FastAPI Backend] Backend --> FHIR[FHIR Gateway] Backend --> ML[ML Service] Backend --> Cache[Redis Cache] FHIR --> Epic[Epic FHIR Server] Backend --> Snowflake[Snowflake DW] ML --> Snowflake ``` --- ## 1. Patient Demographics and Encounter Data ### Frontend Components: PatientInfo, PatientDetails, PatientClassTimeline #### Patient Demographics Mapping | Frontend Field | Component | FHIR Resource | FHIR Path | API Endpoint | | -------------- | ----------- | ------------- | --------------------------------- | ----------------- | | name | PatientInfo | Patient | name[0].given[0] + name[0].family | GET /Patient/{id} | | gender | PatientInfo | Patient | gender | GET /Patient/{id} | | age | PatientInfo | Patient | (calculated from birthDate) | GET /Patient/{id} | | dateOfBirth | PatientInfo | Patient | birthDate | GET /Patient/{id} | | mrn | PatientInfo | Patient | identifier (type=MR) | GET /Patient/{id} | | har | PatientInfo | Patient | identifier (type=VN or custom) | GET /Patient/{id} | #### Patient Details Mapping | Frontend Field | Component | FHIR Resource | FHIR Path | API Endpoint | | -------------------- | -------------- | ------------- | ----------------------------------------- | ---------------------------------------- | | financialClass | PatientDetails | Coverage | class.display | GET /Coverage?patient={id}&status=active | | primaryPayer | PatientDetails | Coverage | payor[0].display | GET /Coverage?patient={id}&status=active | | plan | PatientDetails | Coverage | subscriberId | GET /Coverage?patient={id}&status=active | | patientClass | PatientDetails | Encounter | class.code | GET /Encounter/{id} | | admissionDate | PatientDetails | Encounter | period.start | GET /Encounter/{id} | | dischargeDate | PatientDetails | Encounter | period.end | GET /Encounter/{id} | | lengthOfStay | PatientDetails | Encounter | (calculated from period) | GET /Encounter/{id} | | dischargeDisposition | PatientDetails | Encounter | hospitalization.dischargeDisposition.text | GET /Encounter/{id} | #### Patient Class Timeline Mapping | Frontend Field | Component | FHIR Resource | FHIR Path | API Endpoint | | ------------------- | -------------------- | ------------- | ------------------------------- | ------------------- | | classHistory | PatientClassTimeline | Encounter | classHistory[].class.display | GET /Encounter/{id} | | classHistory.period | PatientClassTimeline | Encounter | classHistory[].period.start/end | GET /Encounter/{id} | #### API Endpoints Summary ```markdown GET /Patient/{id} - Returns: Patient resource with demographics - Required Scopes: patient/Patient.read or user/Patient.read GET /Patient?identifier={system}|{value} - Search by MRN: identifier=urn:oid:1.2.840.114350.1.13.0.1.7.5.737384.0|{MRN} - Returns: Bundle of Patient resources GET /Encounter/{id} - Returns: Full encounter with admission/discharge details - Required Scopes: patient/Encounter.read GET /Encounter?patient={id}&status=in-progress - Returns: Active encounters for patient - Use: Find current admission GET /Coverage?patient={id}&status=active - Returns: Active insurance coverage - Use: Financial class and payer information ``` ### Resource Relationship Diagram ```mermaid graph LR Patient[Patient Resource] --> Encounter[Encounter Resource] Patient --> Coverage[Coverage Resource] Encounter --> Location[Location] Coverage --> Payor[Organization - Payor] Encounter --> Participant[Practitioner] ``` --- ## 2. Clinical Documentation and Diagnoses ### Frontend Components: ClinicalDocumentationSummary, NewDiagnosisIdentified, ChartChanges #### Diagnosis Mapping | Frontend Field | Component | FHIR Resource | FHIR Path | API Endpoint | | ------------------- | ---------------------------- | --------------------- | ----------------------------- | --------------------------------------------- | | code | ClinicalDocumentationSummary | Condition | code.coding[0].code (ICD-10) | GET /Condition?patient={id}&encounter={encId} | | description | ClinicalDocumentationSummary | Condition | code.coding[0].display | GET /Condition?patient={id}&encounter={encId} | | previousCode | NewDiagnosisIdentified | Condition | (from version history) | GET /Condition/{id}/\_history | | previousDescription | NewDiagnosisIdentified | Condition | (from version history) | GET /Condition/{id}/\_history | | badges (POA) | ClinicalDocumentationSummary | Condition | extension[presentOnAdmission] | GET /Condition?patient={id}&encounter={encId} | | badges (CC/MCC) | ClinicalDocumentationSummary | (Backend calculation) | N/A - calculated from ICD-10 | Backend logic | #### Supporting Documentation Mapping | Frontend Field | Component | FHIR Resource | FHIR Path | API Endpoint | | ---------------------- | ---------------------------- | ----------------- | ------------------------------------ | ------------------------------------------------------ | | type: 'Labs' | ClinicalDocumentationSummary | Observation | category.coding[0].code='laboratory' | GET /Observation?patient={id}&category=laboratory | | type: 'Clinical Notes' | ClinicalDocumentationSummary | DocumentReference | type.coding[0].code | GET /DocumentReference?patient={id}&type=progress-note | | type: 'Medication' | ClinicalDocumentationSummary | MedicationRequest | medicationCodeableConcept | GET /MedicationRequest?patient={id}&encounter={encId} | | author | ClinicalDocumentationSummary | (Any resource) | (resource).author or performer | (varies by resource) | | date | ClinicalDocumentationSummary | (Any resource) | recordedDate or effectiveDateTime | (varies by resource) | | description | ClinicalDocumentationSummary | (Any resource) | text.div or specific field | (varies by resource) | #### Chart Changes Mapping | Frontend Field | Component | FHIR Resource | FHIR Path | API Endpoint | | --------------------- | ------------ | ----------------- | ------------------------ | ------------------------------------- | | type: 'diagnosis' | ChartChanges | Condition | code.coding + versioning | GET /Condition/{id}/\_history | | type: 'clinical-note' | ChartChanges | DocumentReference | content.attachment.data | GET /DocumentReference/{id}/\_history | | type: 'lab' | ChartChanges | Observation | valueQuantity | GET /Observation/{id}/\_history | | previousValue | ChartChanges | (Any) | (from previous version) | GET /{resource}/{id}/\_history | | currentValue | ChartChanges | (Any) | (from current version) | GET /{resource}/{id} | | badges | ChartChanges | (Meta) | meta.tag or custom | Backend calculation | #### API Endpoints Summary ```markdown GET /Condition?patient={id}&encounter={encounterId} - Returns: All diagnoses for specific encounter - Filter: &category=encounter-diagnosis - Required Scopes: patient/Condition.read GET /Condition?patient={id}&clinical-status=active - Returns: Active conditions across all encounters - Use: Current problem list GET /Condition/{id}/\_history - Returns: Version history of condition - Use: Track diagnosis changes over time GET /DocumentReference?patient={id}&type=progress-note - Returns: Clinical notes/progress notes - Types: consultation, discharge-summary, history-and-physical - Required Scopes: patient/DocumentReference.read GET /DocumentReference/{id} - Returns: Single document with content - content.attachment.url → fetch actual document - content.attachment.data → base64 encoded content (if available) GET /DiagnosticReport?patient={id}&category=LAB - Returns: Lab reports with grouped results - Use: Structured lab report summaries - Required Scopes: patient/DiagnosticReport.read ``` #### Epic-Specific Extensions for Conditions | Extension | URL | Purpose | | -------------------- | ----------------------------------------------------------------------- | ----------------------------------- | | Present on Admission | <http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition-poa> | POA indicator | | Diagnosis Rank | <http://fhir.epic.com/StructureDefinition/condition-rank> | Primary/secondary ranking | | Diagnosis Date | (varies) | When diagnosis was made vs recorded | --- ## 3. DRG Analysis and Procedures ### Frontend Components: DRGAnalysisMain, DRGAnalysisTab, DRGAnalysisTracker #### DRG Data Mapping | Frontend Field | Component | FHIR Resource | FHIR Path | API Endpoint | | ----------------------- | --------------- | --------------- | ---------------------------- | ----------------------------------------- | | workingDRG.code | DRGAnalysisMain | Claim | item[0].revenue.coding (DRG) | GET /Claim?patient={id}&encounter={encId} | | workingDRG.description | DRGAnalysisMain | Claim | (lookup from DRG code) | Backend DRG table | | workingDRG.weight | DRGAnalysisMain | (Not in FHIR) | N/A | Backend DRG table | | workingDRG.gmlos | DRGAnalysisMain | (Not in FHIR) | N/A | Backend DRG table | | workingDRG.assignedBy | DRGAnalysisMain | Claim | enterer.display or provider | GET /Claim/{id} | | workingDRG.assignedDate | DRGAnalysisMain | Claim | created | GET /Claim/{id} | | recommendedDRG | DRGAnalysisMain | (ML Prediction) | N/A | Backend ML Service | | aiConfidenceScore | DRGAnalysisMain | (ML Prediction) | N/A | Backend ML Service | | baselineDRG | PatientDetails | Encounter | (Epic extension or Claim) | GET /Encounter/{id} or GET /Claim | #### Procedure Mapping | Frontend Field | Component | FHIR Resource | FHIR Path | API Endpoint | | ---------------- | ---------------------------- | ------------- | -------------------------- | --------------------------------------------- | | cptCode | ClinicalDocumentationSummary | Procedure | code.coding[0].code (CPT) | GET /Procedure?patient={id}&encounter={encId} | | description | Various | Procedure | code.coding[0].display | GET /Procedure?patient={id}&encounter={encId} | | author/performer | Various | Procedure | performer[0].actor.display | GET /Procedure?patient={id}&encounter={encId} | | date | Various | Procedure | performedDateTime | GET /Procedure?patient={id}&encounter={encId} | #### API Endpoints Summary ```markdown GET /Claim?patient={id}&use=claim&encounter={encId} - Returns: Claim resources with DRG assignments - Note: May not be real-time, typically billing cycle - Required Scopes: patient/Claim.read GET /Claim?patient={id}&status=active - Returns: Active claims - Use: Current DRG assignment GET /Procedure?patient={id}&encounter={encounterId} - Returns: Procedures performed during encounter - Filter: &category=procedure for actual procedures - Required Scopes: patient/Procedure.read GET /Procedure?patient={id}&date=ge{date} - Returns: Procedures after specified date - Use: Recent procedures ``` #### Important Notes on DRG Data **DRG data is NOT standard FHIR.** Options for obtaining DRG information: 1. **Epic-Specific Extension on Encounter:** - Epic may include DRG in Encounter.hospitalization extension - URL: `http://fhir.epic.com/StructureDefinition/encounter-drg` 2. **Claim Resource (Post-Billing):** - Claim.item[].revenue.coding with DRG code - May have significant delay (billing cycle) 3. **Epic Proprietary API (if available):** - `GET /api/epic/v1/Encounter/{id}/drg` - Requires Epic customer agreement 4. **Backend Calculation (Recommended):** - Fetch Conditions + Procedures - Use backend DRG grouper logic - Store in Snowflake for historical tracking #### Backend DRG Processing Flow ```mermaid sequenceDiagram participant FE as Frontend participant BE as Backend API participant FHIR as Epic FHIR participant ML as ML Service participant SF as Snowflake FE->>BE: Get DRG Analysis for Encounter BE->>FHIR: GET /Encounter/{id} BE->>FHIR: GET /Condition?encounter={id} BE->>FHIR: GET /Procedure?encounter={id} BE->>SF: Query historical DRG assignments BE->>ML: Request DRG prediction ML->>SF: Fetch training data ML-->>BE: Return predicted DRG + confidence BE-->>FE: Return working DRG + recommended DRG ``` --- ## 4. Labs, Observations, and Vitals ### Frontend Components: ClinicalDocumentationSummary (supporting docs) #### Observation Mapping | Frontend Field | Component | FHIR Resource | FHIR Path | API Endpoint | | ---------------- | ------------------------ | ------------- | --------------------------- | -------------------------------------------------- | | Labs description | Supporting Documentation | Observation | code.coding[0].display | GET /Observation?patient={id}&category=laboratory | | Lab value | Supporting Documentation | Observation | valueQuantity.value + unit | GET /Observation?patient={id}&category=laboratory | | Lab code | Backend | Observation | code.coding[0].code (LOINC) | GET /Observation?patient={id}&category=laboratory | | Vital signs | Supporting Documentation | Observation | valueQuantity | GET /Observation?patient={id}&category=vital-signs | | Lab date | Supporting Documentation | Observation | effectiveDateTime | GET /Observation?patient={id}&category=laboratory | | Lab author | Supporting Documentation | Observation | performer[0].display | GET /Observation?patient={id}&category=laboratory | #### Key LOINC Codes for Common Labs | Lab Test | LOINC Code | Typical Units | | ------------------------ | ---------- | ------------- | | WBC Count | 6690-2 | 10\*3/uL | | Creatinine | 2160-0 | mg/dL | | Lactate | 2524-7 | mmol/L | | Blood Glucose | 2339-0 | mg/dL | | Hemoglobin | 718-7 | g/dL | | Platelets | 777-3 | 10\*3/uL | | Sodium | 2951-2 | mmol/L | | Potassium | 2823-3 | mmol/L | | Temperature | 8310-5 | degF or degC | | Blood Pressure Systolic | 8480-6 | mm[Hg] | | Blood Pressure Diastolic | 8462-4 | mm[Hg] | | Heart Rate | 8867-4 | /min | | Respiratory Rate | 9279-1 | /min | | SpO2 | 2708-6 | % | #### API Endpoints Summary ```markdown GET /Observation?patient={id}&category=laboratory - Returns: Lab results - Add: &date=ge{date} for recent labs - Add: &code={LOINC} for specific test - Required Scopes: patient/Observation.read GET /Observation?patient={id}&category=vital-signs - Returns: Vital signs (BP, temp, HR, RR, SpO2) - Add: &date=ge{date} for recent vitals GET /Observation?patient={id}&code={LOINC} - Returns: Specific lab test results - Example: code=2160-0 for creatinine GET /DiagnosticReport?patient={id}&category=LAB&encounter={encId} - Returns: Grouped lab results - Use: Full lab panels with interpretation ``` --- ## 5. Medications ### Frontend Components: ClinicalDocumentationSummary (supporting docs) #### Medication Mapping | Frontend Field | Component | FHIR Resource | FHIR Path | API Endpoint | | ---------------------- | ------------------------ | ------------------------ | ---------------------------------------- | ------------------------------------------ | | Medication name | Supporting Documentation | MedicationRequest | medicationCodeableConcept.text | GET /MedicationRequest?patient={id} | | Medication code | Backend | MedicationRequest | medicationCodeableConcept.coding[0].code | GET /MedicationRequest?patient={id} | | Medication description | Supporting Documentation | MedicationRequest | dosageInstruction[0].text | GET /MedicationRequest?patient={id} | | Prescriber | Supporting Documentation | MedicationRequest | requester.display | GET /MedicationRequest?patient={id} | | Date prescribed | Supporting Documentation | MedicationRequest | authoredOn | GET /MedicationRequest?patient={id} | | Administration records | Backend | MedicationAdministration | effectiveDateTime + dosage | GET /MedicationAdministration?patient={id} | #### API Endpoints Summary ```markdown GET /MedicationRequest?patient={id}&encounter={encounterId} - Returns: Medications ordered during encounter - Add: &status=active for active orders - Required Scopes: patient/MedicationRequest.read GET /MedicationRequest?patient={id}&status=active - Returns: Current active medications - Use: Medication reconciliation GET /MedicationAdministration?patient={id}&encounter={encId} - Returns: Actual medication administrations - Use: Confirm medications were given - Required Scopes: patient/MedicationAdministration.read ``` --- ## 6. Utilization Review and Queries ### Frontend Components: UtilizationReviewSummary, Queries #### Utilization Review Mapping | Frontend Field | Component | FHIR Resource | FHIR Path | API Endpoint | | --------------------------- | ------------------------ | ------------- | ------------------------- | --------------------------------------------- | | Decision criteria diagnosis | UtilizationReviewSummary | Condition | code.coding + text | GET /Condition?patient={id}&encounter={encId} | | Inpatient-only procedure | UtilizationReviewSummary | Procedure | code.coding[0].code (CPT) | GET /Procedure?patient={id}&encounter={encId} | | Patient class validation | UtilizationReviewSummary | Encounter | class.code | GET /Encounter/{id} | | Procedure description | UtilizationReviewSummary | Procedure | code.text or display | GET /Procedure?patient={id}&encounter={encId} | #### Query Workflow Mapping | Frontend Field | Component | FHIR Resource | FHIR Path | API Endpoint | | ---------------------- | --------- | -------------------- | ------------------------ | --------------------------------------------- | | Query status | Queries | CommunicationRequest | status | GET /CommunicationRequest?subject={patientId} | | Query type | Queries | CommunicationRequest | category.text | GET /CommunicationRequest?subject={patientId} | | Query recipient | Queries | CommunicationRequest | recipient[0].display | GET /CommunicationRequest?subject={patientId} | | Query sentBy | Queries | CommunicationRequest | sender.display | GET /CommunicationRequest?subject={patientId} | | Query sentDate | Queries | CommunicationRequest | authoredOn | GET /CommunicationRequest?subject={patientId} | | Query response | Queries | Communication | payload[0].contentString | GET /Communication?based-on={commReqId} | | Response received date | Queries | Communication | sent | GET /Communication?based-on={commReqId} | #### API Endpoints Summary ```markdown GET /ServiceRequest?patient={id}&status=active&encounter={encId} - Returns: Active service requests/orders - Use: Identify procedures ordered - Required Scopes: patient/ServiceRequest.read GET /CommunicationRequest?subject={patientId} - Returns: Clinical queries sent - Add: &status=active for pending queries - Required Scopes: user/CommunicationRequest.read POST /CommunicationRequest - Creates: New clinical query - Body: CommunicationRequest resource - Required Scopes: user/CommunicationRequest.write GET /Communication?based-on={communicationRequestId} - Returns: Responses to specific query - Use: Track query responses - Required Scopes: user/Communication.read ``` #### Utilization Review Backend Logic **Inpatient-Only Procedures:** Backend must maintain list of inpatient-only CPT codes and validate patient class matches. Not available via FHIR API. **Medicare Short Stay Warning:** Calculate from Encounter.period duration + Encounter.class.code + Coverage.payor (Medicare). --- ## 7. Complete FHIR Resource Quick Reference ### All Required FHIR Resources | FHIR Resource | Frontend Use | Backend Use | API Endpoint Pattern | | ------------------------ | ------------------------- | ----------------------------------- | ------------------------------------------ | | Patient | PatientInfo demographics | Patient search, identity | GET /Patient/{id} | | Encounter | PatientDetails, Timeline | Encounter context, length of stay | GET /Encounter/{id} | | Coverage | Financial class, payer | Authorization, financial validation | GET /Coverage?patient={id} | | Condition | Diagnoses, ICD-10 codes | CDI analysis, DRG grouping | GET /Condition?patient={id} | | Procedure | CPT codes, procedures | DRG grouping, coding validation | GET /Procedure?patient={id} | | Observation | Labs, vitals | Clinical indicators, ML features | GET /Observation?patient={id} | | MedicationRequest | Medication lists | Treatment tracking, CDI support | GET /MedicationRequest?patient={id} | | MedicationAdministration | Med administration | Actual treatments given | GET /MedicationAdministration?patient={id} | | DocumentReference | Clinical notes | NLP, documentation changes | GET /DocumentReference?patient={id} | | DiagnosticReport | Lab reports | Structured lab data | GET /DiagnosticReport?patient={id} | | Claim | DRG assignments (delayed) | DRG history, billing validation | GET /Claim?patient={id} | | ServiceRequest | Orders | Procedure validation | GET /ServiceRequest?patient={id} | | CommunicationRequest | Query workflow | Query tracking | GET /CommunicationRequest | | Communication | Query responses | Response tracking | GET /Communication | | Practitioner | Provider names | Provider identification | GET /Practitioner/{id} | | Organization | Payers, facilities | Reference data | GET /Organization/{id} | | Location | Encounter locations | Department tracking | GET /Location/{id} | --- ## 8. Backend Data Flow for CDI Review ```mermaid sequenceDiagram participant FE as Frontend participant BE as Backend participant FHIR as Epic FHIR participant ML as ML Service participant Cache as Redis FE->>BE: Load patient encounter BE->>Cache: Check cached data alt Cache hit Cache-->>BE: Return cached data else Cache miss BE->>FHIR: GET /Patient/{id} BE->>FHIR: GET /Encounter/{id} BE->>FHIR: GET /Condition?encounter={id} BE->>FHIR: GET /Procedure?encounter={id} BE->>FHIR: GET /Observation?patient={id}&category=laboratory BE->>FHIR: GET /MedicationRequest?encounter={id} BE->>Cache: Cache results (15 min TTL) end BE->>ML: Request DRG prediction + CDI opportunities ML-->>BE: Return AI recommendations BE-->>FE: Return complete CDI review data ``` --- ## 9. Backend Integration Architecture ```mermaid graph TB subgraph Frontend UI[React Components] end subgraph Backend API[FastAPI Endpoints] FHIR_Client[FHIR Client Service] Transform[Data Transform Layer] Auth[JWT Auth Service] Cache[Redis Cache] end subgraph External Epic[Epic FHIR Server] ML[ML Service] Snowflake[Snowflake DW] end UI --> API API --> Auth API --> FHIR_Client FHIR_Client --> Cache FHIR_Client --> Epic API --> Transform Transform --> ML Transform --> Snowflake ML --> Snowflake ``` --- ## 10. OAuth 2.0 Scopes Required ### Patient Context (Patient-Facing Apps) ``` patient/Patient.read patient/Encounter.read patient/Condition.read patient/Observation.read patient/MedicationRequest.read patient/Procedure.read patient/DocumentReference.read patient/DiagnosticReport.read patient/Coverage.read ``` ### User Context (Provider-Facing Apps) - RECOMMENDED ``` user/Patient.read user/Encounter.read user/Condition.read user/Observation.read user/MedicationRequest.read user/MedicationAdministration.read user/Procedure.read user/DocumentReference.read user/DiagnosticReport.read user/Coverage.read user/Claim.read user/ServiceRequest.read user/CommunicationRequest.read user/CommunicationRequest.write user/Communication.read user/Practitioner.read user/Organization.read user/Location.read ``` ### System Context (Backend Service/Bulk Export) ``` system/Patient.read system/Encounter.read system/Condition.read system/Observation.read system/MedicationRequest.read system/Procedure.read ``` --- ## 11. Epic-Specific Considerations ### Error Codes Reference | Error Code | Description | Handling Strategy | | ---------- | -------------------------- | ---------------------------------- | | 4100 | Invalid parameter | Validate parameters before sending | | 4101 | No results found | Return empty array, not error | | 4102 | Invalid resource ID | Validate ID format, return 404 | | 4107 | Patient merged | Follow redirect, update local ID | | 4111 | Required parameter missing | Add required parameters | | 4118 | User not authorized | Check OAuth scopes, return 403 | | 4130 | Break-the-glass required | Implement BTG flow if needed | ### Pagination Strategy Epic returns paginated results in FHIR Bundle format: ```json { "resourceType": "Bundle", "type": "searchset", "total": 150, "link": [ { "relation": "self", "url": "..." }, { "relation": "next", "url": "https://fhir.epic.com/..." } ], "entry": [...] } ``` **Implementation:** - Use `_count` parameter to set page size (default: 50, max: varies) - Follow `link[relation=next].url` for next page - Stop when no `next` link present ### Rate Limiting - Epic rate limits vary by customer and app type - Typical: 100-1000 requests/minute per user - Implement exponential backoff: 1s, 2s, 4s, 8s - Cache frequently accessed data (Patient, Encounter) - Use batch requests where supported ### SMART on FHIR Launch Sequence 1. **EHR-Initiated Launch:** - Epic sends launch request to app with `iss` and `launch` parameters - App redirects to authorization endpoint - User authenticates and authorizes - App receives authorization code - App exchanges code for access token - Token includes patient/encounter context 2. **Standalone Launch:** - App initiates OAuth flow - User selects patient after authentication - No automatic context --- ## 12. Implementation Priorities ### Phase 1: Core Patient Data 1. Patient demographics (Patient resource) 2. Current encounter (Encounter resource) 3. Active diagnoses (Condition resource) 4. Recent labs (Observation resource) ### Phase 2: CDI Features 1. Clinical notes (DocumentReference) 2. Procedures (Procedure resource) 3. Medications (MedicationRequest) 4. DRG data (Claim or backend calculation) ### Phase 3: Advanced Features 1. Query workflow (CommunicationRequest) 2. Chart change tracking (resource versioning) 3. Utilization review logic (backend validation) 4. ML integration (backend service) --- ## Appendix A: Sample FHIR Requests ### Get Patient by ID ``` GET https://fhir.epic.com/api/FHIR/R4/Patient/eM8.8NLHyp7kxdEKE1.WwQ3 Authorization: Bearer {access_token} Accept: application/fhir+json ``` ### Search Conditions for Encounter ``` GET https://fhir.epic.com/api/FHIR/R4/Condition?patient=eM8.8NLHyp7kxdEKE1.WwQ3&encounter=eMTI.cGa2GmBp8N8R6gVy0Bw3 Authorization: Bearer {access_token} Accept: application/fhir+json ``` ### Get Recent Lab Results ``` GET https://fhir.epic.com/api/FHIR/R4/Observation?patient=eM8.8NLHyp7kxdEKE1.WwQ3&category=laboratory&date=ge2024-07-01 Authorization: Bearer {access_token} Accept: application/fhir+json ``` --- ## Appendix B: Non-FHIR Data Requirements These data elements are **not available** via Epic FHIR APIs and must be handled in backend: | Data Element | Source | Implementation | | ----------------------------- | ------------------ | --------------------------- | | DRG Weight | CMS DRG tables | Backend lookup table | | DRG GMLOS | CMS DRG tables | Backend lookup table | | DRG Recommendations | ML predictions | Backend ML service | | AI Confidence Scores | ML predictions | Backend ML service | | ICD-10 CC/MCC classification | CMS CC/MCC lists | Backend validation service | | Inpatient-only procedure list | CMS/Medicare rules | Backend validation tables | | Coding productivity metrics | Internal tracking | Snowflake analytics | | User role permissions | Internal RBAC | Backend auth service | | Historical DRG changes | Internal tracking | Snowflake historical tables | --- ## Summary This document provides comprehensive mapping between your frontend components and Epic FHIR R4 APIs. Key takeaways: 1. **17 FHIR resources** are required for full functionality 2. **DRG data** is not standard FHIR - requires backend calculation or Epic extensions 3. **ML predictions** are backend-only - FHIR provides input data 4. **OAuth scopes** should use `user/*` context for provider-facing app 5. **Caching strategy** is critical - implement Redis for frequently accessed data 6. **Error handling** must account for Epic-specific error codes 7. **Pagination** is required for all list operations The architecture supports both real-time FHIR API calls for active patient reviews and bulk export to Snowflake for historical analytics and ML training.

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully