# 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.