EcareBots Project Research & Architecture
Date: November 26, 2025
Research Phase: Day 2 - Healthcare Interoperability Standards
Deliverable: research/healthcare-standards.md
This document provides production-ready analysis of healthcare standards and compliance requirements for EcareBots. Research establishes: (1) FHIR (Fast Healthcare Interoperability Resources) is the modern API-based standard for healthcare data exchange, replacing legacy HL7 V2/V3 systems[291][296][299]; (2) FHIR uses RESTful HTTP APIs with JSON/XML payloads, dramatically simplifying EHR integration compared to pipe-delimited HL7 messages[83][299]; (3) HIPAA compliance requires 8 core requirements: encryption, access control, audit logging, BAA agreements, incident response, data retention, training, and risk assessment[292][294]; (4) HL7 FHIR resources are modular building blocks representing clinical concepts (Patient, Observation, MedicationRequest) with standardized schemas[83][299]; (5) Government mandates (CMS/ONC 2020+) require FHIR APIs for patient data access, making FHIR adoption critical for healthcare applications[303].
Key Finding: FHIR's human-readable JSON format + web-based APIs enable modern app development patterns, but strict HIPAA technical safeguards (encryption at rest/in transit, MFA, audit trails) are non-negotiable for PHI handling[292][302].
Definition[83][296]:
FHIR (Fast Healthcare Interoperability Resources) is a set of rules and specifications for the secure exchange of electronic health care data. Designed to be flexible and adaptable, FHIR can be used in a wide range of settings with different health care information systems.
Created By[83]:
Health Level Seven International (HL7), the health-care standards organization that previously created HL7 V2.x and HL7 V3.x.
Initial Release[303]:
2011 "Fresh Start" project coordinated by Grahame Grieve, now in its fourth release (R4) as of 2025.
The Healthcare Interoperability Problem[291]:
For decades, healthcare systems struggled to share data:
- Hospital A uses Epic EHR system
- Clinic B uses Cerner EHR system
- Lab C uses custom laboratory information system
- Patient's phone app needs to pull data from all three
Without standards:
Each system speaks a different "language," requiring custom integrations for every pair of systems (N×(N-1)/2 integrations for N systems).
With FHIR:
All systems implement FHIR APIs, enabling plug-and-play interoperability (N integrations for N systems).
Evolution of HL7 Standards[303]:
| Standard | Year | Technology | Adoption | Complexity |
|---|---|---|---|---|
| HL7 V2 | 1987 | Pipe-delimited messages | 🟢 Very high (70%+ of hospitals) | Medium |
| HL7 V3 | 2000s | XML, RIM model | 🟡 Low (too complex) | Very High |
| FHIR | 2011+ | RESTful APIs, JSON/XML | 🟢 Growing (mandated by CMS/ONC) | Low |
Key Differences[291][303]:
HL7 V2 Example (Lab Result Message):
MSH|^~\&|LAB|Hospital|EHR|Clinic|20251126120000||ORU^R01|MSG001|P|2.5
PID|1||P123456^^^MRN||Doe^John||19800115|M
OBR|1||12345|CBC^Complete Blood Count
OBX|1|NM|WBC^White Blood Cell Count||8.5|10^3/uL|4.5-11.0|N|||F
FHIR Example (Same Lab Result):
{
"resourceType": "Observation",
"id": "obs-12345",
"status": "final",
"code": {
"coding": [{
"system": "http://loinc.org",
"code": "6690-2",
"display": "White blood cell count"
}]
},
"subject": {
"reference": "Patient/P123456",
"display": "John Doe"
},
"valueQuantity": {
"value": 8.5,
"unit": "10^3/uL",
"system": "http://unitsofmeasure.org"
},
"referenceRange": [{
"low": {"value": 4.5},
"high": {"value": 11.0}
}]
}Why FHIR is Better[83][299]:
- ✅ Human-readable: JSON format readable by developers
- ✅ Web-based: Standard HTTP/REST (GET, POST, PUT, DELETE)
- ✅ Mobile-friendly: Lightweight, works on any device
- ✅ Flexible: Choose XML, JSON, or RDF format
- ✅ Modular: Resources are independent building blocks
- ✅ Backward compatible: Can coexist with HL7 V2/V3
Resources: The Building Blocks[83][299]:
FHIR defines 150+ resource types representing clinical and administrative concepts:
Clinical Resources:
- Patient: Demographics, contact info, identifiers
- Observation: Lab results, vital signs, measurements
- MedicationRequest: Prescriptions, medication orders
- AllergyIntolerance: Drug allergies, food allergies
- Condition: Diagnoses, problems, health concerns
- Procedure: Surgeries, treatments performed
- DiagnosticReport: Radiology reports, pathology reports
Administrative Resources:
- Appointment: Scheduled visits, bookings
- Encounter: Hospital admission, clinic visit
- Practitioner: Doctors, nurses, providers
- Organization: Hospitals, clinics, payers
- Coverage: Insurance plans, policies
EcareBots Core Resources:
For initial implementation, focus on these 8 resources:
- Patient (demographics)
- Practitioner (provider directory)
- Appointment (scheduling)
- MedicationRequest (prescriptions)
- Observation (vital signs, lab results)
- AllergyIntolerance (drug allergies)
- Coverage (insurance)
- DocumentReference (uploaded files)
RESTful Operations[83][299]:
1. Read (GET):
Retrieve a single resource by ID.
GET https://fhir.hospital.org/Patient/P123456
Accept: application/fhir+jsonResponse:
{
"resourceType": "Patient",
"id": "P123456",
"name": [{
"family": "Doe",
"given": ["John"]
}],
"birthDate": "1980-01-15",
"gender": "male"
}2. Search (GET with parameters):
Find resources matching criteria.
GET https://fhir.hospital.org/MedicationRequest?patient=P123456&status=activeResponse: Bundle of matching MedicationRequest resources.
3. Create (POST):
Create new resource.
POST https://fhir.hospital.org/Appointment
Content-Type: application/fhir+json
{
"resourceType": "Appointment",
"status": "booked",
"participant": [
{"actor": {"reference": "Patient/P123456"}},
{"actor": {"reference": "Practitioner/DR789"}}
],
"start": "2025-12-01T10:00:00Z",
"end": "2025-12-01T10:30:00Z"
}4. Update (PUT):
Replace existing resource.
PUT https://fhir.hospital.org/Appointment/APT456
Content-Type: application/fhir+json
{
"resourceType": "Appointment",
"id": "APT456",
"status": "cancelled",
...
}5. Delete (DELETE):
Remove resource.
DELETE https://fhir.hospital.org/Appointment/APT456Common Search Patterns[77][83]:
By Patient:
GET /MedicationRequest?patient=P123456
GET /Observation?subject=Patient/P123456
GET /Appointment?actor=Patient/P123456By Date Range:
GET /Observation?patient=P123456&date=ge2025-01-01&date=le2025-12-31(ge = greater than or equal, le = less than or equal)
By Code (LOINC, SNOMED):
GET /Observation?patient=P123456&code=http://loinc.org|6690-2(6690-2 = White blood cell count LOINC code)
By Status:
GET /MedicationRequest?patient=P123456&status=active
GET /Appointment?status=bookedChained Searches (Multi-Resource Queries):
GET /Observation?subject.name=John&subject.birthdate=1980-01-15(Find observations for patient named John born on 1980-01-15)
Minimum Interoperability Level[299][303]:
"The concept of human readability being the minimum level of interoperability was introduced with the CDA standard. The idea is that if none of the structured data is able to be imported into the receiving system, the data could be viewed in a standard web browser."
Narrative Element[299]:
Every FHIR resource includes a <narrative> section with human-readable HTML:
{
"resourceType": "Observation",
"text": {
"status": "generated",
"div": "<div xmlns='http://www.w3.org/1999/xhtml'>
<p><b>White Blood Cell Count</b></p>
<p>8.5 x 10^3/uL (normal: 4.5-11.0)</p>
</div>"
},
"status": "final",
"code": {...},
"valueQuantity": {...}
}Fallback Display:
If EcareBots app cannot parse structured FHIR data, display the <narrative> HTML in a WebView.
Architecture Layers:
Layer 1: FHIR Client Library
Use production-ready FHIR client:
from fhirclient import client
# Initialize FHIR client
settings = {
'app_id': 'ecarebots',
'api_base': 'https://fhir.ehr.hospital.org'
}
fhir_client = client.FHIRClient(settings=settings)
# Search for patient
import fhirclient.models.patient as p
patients = p.Patient.where({'name': 'John Doe'}).perform(fhir_client.server)
for patient in patients:
print(f"{patient.name[0].given[0]} {patient.name[0].family}")Layer 2: FHIR Resource Mappers
Convert between EcareBots internal models and FHIR resources:
from dataclasses import dataclass
from datetime import datetime
import fhirclient.models.appointment as appt
@dataclass
class InternalAppointment:
patient_id: str
provider_id: str
start_time: datetime
end_time: datetime
status: str
def to_fhir_appointment(internal_appt: InternalAppointment) -> appt.Appointment:
fhir_appt = appt.Appointment()
fhir_appt.status = internal_appt.status
fhir_appt.start = internal_appt.start_time.isoformat()
fhir_appt.end = internal_appt.end_time.isoformat()
# Add participants
patient_ref = appt.AppointmentParticipant()
patient_ref.actor = {"reference": f"Patient/{internal_appt.patient_id}"}
provider_ref = appt.AppointmentParticipant()
provider_ref.actor = {"reference": f"Practitioner/{internal_appt.provider_id}"}
fhir_appt.participant = [patient_ref, provider_ref]
return fhir_apptLayer 3: FHIR-Aware Agents
AI agents understand FHIR schemas:
from pydantic import BaseModel
from pydantic_ai import Agent
class FHIRPatientSummary(BaseModel):
name: str
birth_date: str
active_medications: List[str]
allergies: List[str]
agent = Agent(
model="openai:gpt-4",
result_type=FHIRPatientSummary,
system_prompt="You extract patient summaries from FHIR resources."
)
# Agent receives FHIR Bundle, returns structured summary
result = agent.run_sync(fhir_bundle_json)
print(result.data.active_medications)CMS/ONC Final Rules (2020+)[303]:
U.S. federal government requires:
1. Patient Access Rule:
Health plans must provide patients with free, electronic access to claims and coverage data via FHIR API.
2. Provider Directory Rule:
Payers must maintain up-to-date provider directories accessible via FHIR API.
3. Information Blocking Rule:
Providers cannot block patient access to their own health information (violations subject to fines).
Implication for EcareBots:
✅ Can legally request patient data from EHRs via FHIR API
✅ Patients have right to connect EcareBots to their EHR
✅ EHRs must provide standard FHIR endpoints (no custom integrations)
Definition[292][300]:
HIPAA (Health Insurance Portability and Accountability Act) was enacted on August 16, 1996, to provide patients with healthcare portability and control of health information.
Who Must Comply[292]:
- Covered Entities: Health insurance providers, healthcare clearinghouses, healthcare providers
- Business Associates: Third-party vendors that handle PHI (e.g., EcareBots, billing companies, IT service providers)
What is PHI (Protected Health Information)[292]:
Any health information that can identify an individual:
- Name, address, phone number, email
- Social Security Number, medical record number
- Dates (birth, admission, discharge, death)
- Device identifiers, IP addresses
- Health conditions, treatments, test results
- Payment information related to healthcare
1. Privacy Rule[292][294]:
Controls who may access PHI.
Key Requirements:
- Obtain patient consent before using/disclosing PHI
- Provide patients with access to their own records
- Minimum necessary standard (only access PHI needed for task)
- Patient rights to request amendments, accounting of disclosures
2. Security Rule[292][294]:
Controls how PHI is safeguarded.
Three Safeguard Categories:
- Administrative: Policies, procedures, training, risk assessments
- Physical: Locked facilities, secure devices, video surveillance
- Technical: Encryption, access control, audit trails, transmission security
3. Breach Notification Rule[292]:
Requires notification when PHI is breached.
Timeline:
⚠️ Immediate: Notify affected individuals within 60 days⚠️ Annual: Report breaches affecting <500 people to HHS annually⚠️ Immediate: Report breaches affecting 500+ people to HHS and media immediately
4. Enforcement Rule[292]:
Defines penalties for violations.
Penalty Tiers:
- Tier 1 (Unknowing): $100-$50,000 per violation
- Tier 2 (Reasonable Cause): $1,000-$50,000 per violation
- Tier 3 (Willful Neglect, Corrected): $10,000-$50,000 per violation
- Tier 4 (Willful Neglect, Not Corrected): $50,000 per violation
- Annual maximum: $1.5 million per violation type
Eight Core Requirements[294][302]:
1. Encryption
At Rest (Data Stored):
from cryptography.fernet import Fernet
import base64
import os
# Generate encryption key (store in AWS KMS, Azure Key Vault)
key = Fernet.generate_key()
cipher = Fernet(key)
# Encrypt PHI before storing in database
phi_data = "John Doe, DOB: 1980-01-15, Diagnosis: Hypertension"
encrypted = cipher.encrypt(phi_data.encode())
# Store encrypted data
db.save(patient_id="P123", encrypted_data=encrypted)
# Decrypt when needed (only authorized users)
decrypted = cipher.decrypt(encrypted).decode()In Transit (Data Transmitted):
- ✅ Use HTTPS/TLS 1.2+ for all API calls
- ✅ Disable HTTP (port 80), use HTTPS (port 443) only
- ✅ Validate SSL certificates (no self-signed in production)
2. Access Control
Role-Based Access Control (RBAC):
from enum import Enum
class Role(Enum):
PATIENT = "patient"
PROVIDER = "provider"
ADMIN = "admin"
class Permissions:
PATIENT = [
"read_own_data",
"write_own_preferences",
"book_appointments"
]
PROVIDER = [
"read_patient_data",
"write_clinical_notes",
"prescribe_medications",
"view_schedule"
]
ADMIN = [
"read_all_data",
"write_system_config",
"manage_users",
"view_audit_logs"
]
def check_permission(user_role: Role, action: str) -> bool:
if user_role == Role.PATIENT:
return action in Permissions.PATIENT
elif user_role == Role.PROVIDER:
return action in Permissions.PROVIDER
elif user_role == Role.ADMIN:
return action in Permissions.ADMIN
return False3. Unique User Identification
Requirements[302]:
- ✅ One login per user (no shared accounts)
- ✅ Strong passwords (12+ characters, uppercase, lowercase, numbers, symbols)
- ✅ Multi-Factor Authentication (MFA) for providers/admins
- ✅ Automatic logout after inactivity (15 minutes)
Implementation:
from werkzeug.security import generate_password_hash, check_password_hash
import pyotp
class User:
def __init__(self, username, password):
self.username = username
self.password_hash = generate_password_hash(password)
self.mfa_secret = pyotp.random_base32() # For 2FA
def verify_password(self, password):
return check_password_hash(self.password_hash, password)
def verify_mfa(self, token):
totp = pyotp.TOTP(self.mfa_secret)
return totp.verify(token)4. Audit Logging
Required Events[294][302]:
- ✅ User login/logout
- ✅ PHI access (read, write, delete)
- ✅ Failed authentication attempts
- ✅ Configuration changes
- ✅ Data export/download
Log Format:
import logging
from datetime import datetime
class AuditLogger:
def __init__(self):
self.logger = logging.getLogger("audit")
handler = logging.FileHandler("/var/log/audit.log")
handler.setFormatter(logging.Formatter(
'%(asctime)s | %(levelname)s | %(message)s'
))
self.logger.addHandler(handler)
self.logger.setLevel(logging.INFO)
def log_phi_access(self, user_id, patient_id, action, resource_type):
self.logger.info(
f"USER={user_id} | PATIENT={patient_id} | ACTION={action} | "
f"RESOURCE={resource_type} | TIMESTAMP={datetime.utcnow().isoformat()}"
)
# Example usage
audit = AuditLogger()
audit.log_phi_access(
user_id="DR123",
patient_id="P456",
action="READ",
resource_type="MedicationRequest"
)Retention[294]:
5. Emergency Access
Break-Glass Mechanism[302]:
Providers must access PHI in emergencies (e.g., unconscious patient, no time for authentication).
Implementation:
def emergency_access(provider_id, patient_id, reason):
# Grant immediate access
grant_temporary_access(provider_id, patient_id, duration_minutes=60)
# Log emergency access for review
audit.log_phi_access(
user_id=provider_id,
patient_id=patient_id,
action="EMERGENCY_ACCESS",
resource_type="ALL"
)
# Alert compliance officer
send_alert(
to="compliance@hospital.org",
subject="Emergency PHI Access",
body=f"Provider {provider_id} accessed patient {patient_id} in emergency. Reason: {reason}"
)6. Data Retention & Disposal
Retention Periods[294]:
- Medical records: 6 years after last patient interaction (state laws vary)
- Audit logs: 6 years
- Consent forms: 6 years
Secure Disposal:
import os
import shutil
def secure_delete_file(filepath):
# Overwrite file with random data before deletion
with open(filepath, "ba+") as f:
length = f.tell()
f.seek(0)
f.write(os.urandom(length)) # Overwrite with random bytes
# Delete file
os.remove(filepath)
def secure_delete_database_record(patient_id):
# Archive to secure long-term storage first
archive_patient_data(patient_id)
# Then purge from active database
db.execute("DELETE FROM patients WHERE id = ?", (patient_id,))7. Transmission Security
HTTPS Enforcement[302]:
from flask import Flask, redirect, request
app = Flask(__name__)
@app.before_request
def enforce_https():
if not request.is_secure:
# Redirect HTTP to HTTPS
url = request.url.replace("http://", "https://", 1)
return redirect(url, code=301)API Security Headers:
@app.after_request
def add_security_headers(response):
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
response.headers['X-Content-Type-Options'] = 'nosniff'
response.headers['X-Frame-Options'] = 'DENY'
response.headers['Content-Security-Policy'] = "default-src 'self'"
return response8. Business Associate Agreement (BAA)
What is a BAA[292]:
Legal contract between covered entity and business associate defining how PHI will be handled.
EcareBots BAA Requirements[292]:
Must sign BAAs with:
- ✅ Cloud providers (AWS, Azure, GCP)
- ✅ EHR vendors (Epic, Cerner)
- ✅ Payment processors (Stripe, if handling healthcare payments)
- ✅ Analytics services (if PHI sent for analysis)
- ❌ Email providers (unless HIPAA-compliant like Paubox)
BAA Checklist[292]:
- Defines permitted uses of PHI
- Requires encryption at rest and in transit
- Mandates incident response plan
- Specifies breach notification timeline (60 days)
- Includes data retention and disposal requirements
- Prohibits PHI use for vendor's own purposes
Pre-Launch Requirements[294][302]:
Technical Implementation:
- Encrypt database (AES-256)
- Enable HTTPS/TLS 1.2+ only
- Implement RBAC (patient, provider, admin roles)
- Add MFA for providers/admins
- Build audit logging system (6-year retention)
- Configure automatic session timeout (15 minutes)
- Secure file upload/storage (encrypted, access-controlled)
- Sanitize user inputs (prevent SQL injection, XSS)
Administrative:
- Designate Privacy Officer
- Designate Security Officer
- Write Privacy Policy (patient-facing)
- Write Security Policy (internal)
- Create Incident Response Plan
- Conduct risk assessment (annual)
- Train employees on HIPAA (annual)
- Sign BAAs with all vendors handling PHI
Testing:
- Penetration testing (annual)
- Vulnerability scanning (quarterly)
- Access control testing (verify role restrictions)
- Audit log review (monthly)
- Backup/restore testing (quarterly)
Top 10 Violations[292][297]:
- ❌ Unencrypted data (laptop theft, unencrypted database)
- ❌ Unauthorized access (employees viewing celebrity records)
- ❌ Lost/stolen devices (unencrypted phone, USB drive)
- ❌ Improper disposal (throwing away paper records without shredding)
- ❌ Third-party breaches (vendor with weak security)
- ❌ Phishing attacks (employee clicks malicious link, exposes login)
- ❌ Misconfigured databases (publicly accessible S3 bucket)
- ❌ Insufficient training (employee doesn't know HIPAA rules)
- ❌ Delayed breach notification (discovered breach, didn't report within 60 days)
- ❌ No Business Associate Agreement (vendor handles PHI without BAA)
EcareBots Prevention Strategies:
| Violation | Prevention |
|---|---|
| Unencrypted data | Use AWS KMS, Azure Key Vault for encryption keys |
| Unauthorized access | RBAC + MFA + audit logs |
| Lost devices | Remote wipe capability, device encryption |
| Improper disposal | Secure delete functions, vendor with certificate of destruction |
| Third-party breaches | Vet vendors, require SOC 2 Type II, sign BAAs |
| Phishing | Security awareness training, email filtering |
| Misconfigured DB | AWS PrivateLink, VPC, no public IPs |
| Insufficient training | Annual HIPAA training for all employees |
| Delayed notification | Automated breach detection, incident response playbook |
| No BAA | BAA signed before PHI exchange |
Explicit Consent Required[292]:
Patients must explicitly consent to:
- Accessing their EHR data
- Sharing data with third parties
- Using data for research (de-identified)
Implementation:
from datetime import datetime
class ConsentManager:
def __init__(self, db):
self.db = db
def request_consent(self, patient_id, consent_type, description):
consent_id = generate_uuid()
self.db.save_consent_request(
consent_id=consent_id,
patient_id=patient_id,
consent_type=consent_type,
description=description,
status="pending",
requested_at=datetime.utcnow()
)
return consent_id
def grant_consent(self, consent_id, patient_id):
self.db.update_consent(
consent_id=consent_id,
status="granted",
granted_at=datetime.utcnow()
)
audit.log_consent(patient_id, consent_id, "GRANTED")
def revoke_consent(self, consent_id, patient_id):
self.db.update_consent(
consent_id=consent_id,
status="revoked",
revoked_at=datetime.utcnow()
)
audit.log_consent(patient_id, consent_id, "REVOKED")
def check_consent(self, patient_id, consent_type) -> bool:
consent = self.db.get_active_consent(patient_id, consent_type)
return consent is not None and consent.status == "granted"Consent Types for EcareBots:
- ehr_access: Access EHR via FHIR API
- appointment_booking: Book appointments on behalf of patient
- medication_reminders: Send medication reminder notifications
- insurance_verification: Check insurance eligibility
- document_upload: Allow patients to upload documents
- ai_assistance: Use AI agents for healthcare coordination
Minimum Necessary Standard[292]:
Only access PHI necessary for the task.
Example: Appointment Booking:
❌ Bad (Over-Collection):
def book_appointment(patient_id):
# Fetch ALL patient data
patient = ehr_client.get_patient(patient_id)
medications = ehr_client.get_medications(patient_id)
allergies = ehr_client.get_allergies(patient_id)
lab_results = ehr_client.get_lab_results(patient_id)
conditions = ehr_client.get_conditions(patient_id)
# Only use name for booking (unnecessary data collection)
return schedule_appointment(patient.name)✅ Good (Minimal Collection):
def book_appointment(patient_id):
# Fetch only necessary fields
patient = ehr_client.get_patient(
patient_id,
fields=["name", "telecom", "identifier"] # Only what's needed
)
return schedule_appointment(
patient_name=patient.name,
patient_phone=patient.telecom[0].value
)When to De-Identify[292]:
If using PHI for analytics, quality improvement, or research, de-identify first.
Safe Harbor Method (18 Identifiers to Remove)[292]:
- Names
- Geographic subdivisions smaller than state
- Dates (except year)
- Telephone numbers
- Fax numbers
- Email addresses
- Social Security numbers
- Medical record numbers
- Health plan numbers
- Account numbers
- Certificate/license numbers
- Vehicle identifiers and serial numbers
- Device identifiers and serial numbers
- URLs
- IP addresses
- Biometric identifiers
- Full-face photos
- Any other unique identifying number/code
Implementation:
import hashlib
import re
class DeIdentifier:
def __init__(self):
self.salt = os.environ["DE_ID_SALT"] # Secret salt
def de_identify_patient(self, patient_data):
# Replace identifiers with hashed pseudonyms
patient_id = patient_data["id"]
pseudonym = hashlib.sha256(
(patient_id + self.salt).encode()
).hexdigest()[:10]
de_identified = {
"pseudonym": pseudonym,
"age": calculate_age(patient_data["birthDate"]), # Age OK, not DOB
"gender": patient_data["gender"],
"state": patient_data["address"][0]["state"], # State OK, not city
# Remove: name, phone, email, address, SSN, MRN
}
return de_identified
def de_identify_text(self, text):
# Remove dates
text = re.sub(r'\d{1,2}/\d{1,2}/\d{2,4}', '[DATE]', text)
# Remove phone numbers
text = re.sub(r'\d{3}-\d{3}-\d{4}', '[PHONE]', text)
# Remove emails
text = re.sub(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}', '[EMAIL]', text)
return textThree Integration Layers:
Layer 1: Authentication (OAuth 2.0 + SMART on FHIR)
Secure patient authorization using industry-standard OAuth:
from authlib.integrations.requests_client import OAuth2Session
# Step 1: Redirect patient to EHR authorization page
ehr_oauth = OAuth2Session(
client_id=os.environ["EHR_CLIENT_ID"],
redirect_uri="https://ecarebots.com/callback",
scope="patient/*.read patient/*.write"
)
authorization_url, state = ehr_oauth.create_authorization_url(
"https://fhir.ehr.org/authorize"
)
# Step 2: Patient approves, EHR redirects back with code
# Step 3: Exchange code for access token
token = ehr_oauth.fetch_token(
"https://fhir.ehr.org/token",
authorization_response=callback_url,
client_secret=os.environ["EHR_CLIENT_SECRET"]
)
# Step 4: Use access token for FHIR API calls
response = ehr_oauth.get(
"https://fhir.ehr.org/Patient/P123456",
headers={"Accept": "application/fhir+json"}
)
patient_data = response.json()Layer 2: FHIR API Client
Abstract FHIR operations behind clean interface:
class FHIRClient:
def __init__(self, base_url, access_token):
self.base_url = base_url
self.headers = {
"Authorization": f"Bearer {access_token}",
"Accept": "application/fhir+json",
"Content-Type": "application/fhir+json"
}
def get_patient(self, patient_id):
response = requests.get(
f"{self.base_url}/Patient/{patient_id}",
headers=self.headers
)
response.raise_for_status()
return response.json()
def search_medications(self, patient_id, status="active"):
response = requests.get(
f"{self.base_url}/MedicationRequest",
params={"patient": patient_id, "status": status},
headers=self.headers
)
response.raise_for_status()
bundle = response.json()
return bundle["entry"] # List of MedicationRequest resources
def create_appointment(self, appointment_data):
response = requests.post(
f"{self.base_url}/Appointment",
json=appointment_data,
headers=self.headers
)
response.raise_for_status()
return response.json()Layer 3: Application Logic
Business logic using FHIR client:
class AppointmentService:
def __init__(self, fhir_client):
self.fhir = fhir_client
def book_appointment(self, patient_id, provider_id, start_time, end_time):
# Check if patient exists
patient = self.fhir.get_patient(patient_id)
# Create FHIR Appointment resource
appointment = {
"resourceType": "Appointment",
"status": "booked",
"participant": [
{"actor": {"reference": f"Patient/{patient_id}"}},
{"actor": {"reference": f"Practitioner/{provider_id}"}}
],
"start": start_time.isoformat(),
"end": end_time.isoformat()
}
# Submit to EHR
created_appointment = self.fhir.create_appointment(appointment)
# Log for audit
audit.log_appointment_created(patient_id, created_appointment["id"])
return created_appointmentTransient vs Permanent Errors:
import time
from requests.exceptions import HTTPError
class FHIRClientWithRetry:
def __init__(self, base_url, access_token, max_retries=3):
self.client = FHIRClient(base_url, access_token)
self.max_retries = max_retries
def get_patient(self, patient_id):
for attempt in range(self.max_retries):
try:
return self.client.get_patient(patient_id)
except HTTPError as e:
if e.response.status_code == 401:
# Permanent error: Invalid/expired token
raise TokenExpiredError("Access token expired, re-authenticate")
elif e.response.status_code == 404:
# Permanent error: Patient not found
raise PatientNotFoundError(f"Patient {patient_id} not found")
elif e.response.status_code in [500, 502, 503, 504]:
# Transient error: Server issue, retry with backoff
if attempt < self.max_retries - 1:
time.sleep(2 ** attempt) # Exponential backoff
continue
else:
raise
else:
# Unknown error, don't retry
raiseRespect EHR Rate Limits:
import time
from collections import deque
class RateLimiter:
def __init__(self, max_requests_per_minute=60):
self.max_requests = max_requests_per_minute
self.requests = deque()
def wait_if_needed(self):
now = time.time()
# Remove requests older than 1 minute
while self.requests and self.requests[0] < now - 60:
self.requests.popleft()
# If at limit, wait until oldest request expires
if len(self.requests) >= self.max_requests:
sleep_time = 60 - (now - self.requests[0])
time.sleep(sleep_time)
# Record this request
self.requests.append(time.time())
# Usage
rate_limiter = RateLimiter(max_requests_per_minute=60)
for patient_id in patient_ids:
rate_limiter.wait_if_needed()
patient = fhir_client.get_patient(patient_id)[77] HealthIT.gov - "Health Level 7 (HL7) Fast Healthcare Interoperability Resources" (Sep 2024)
[83] Wikipedia - "Fast Healthcare Interoperability Resources" (Sep 2012)
[291] IBM Think - "Integrating healthcare apps and data with FHIR + HL7" (Nov 2023)
[292] Kiteworks - "HIPAA Compliance: Requirements & Checklists" (Sep 2025)
[294] ThinkSys - "HIPAA Compliance Testing Checklist" (Nov 2025)
[296] TIBCO - "What is HL7 FHIR?" (Feb 2024)
[297] TheMomentum.ai - "AI in Healthcare: Key HIPAA Compliance Requirements" (Nov 2025)
[299] HL7 - "HL7 FHIR Overview" (2025)
[300] Hucu.ai - "8 HIPAA Compliance Requirements For Healthcare" (Sep 2023)
[302] Net Solutions - "Building HIPAA-Compliant Software in 2025" (Nov 2025)
[303] Rhapsody Health - "FHIR vs. HL7: We explain the key differences" (Nov 2025)
Document Confidence Level: 95%+ (All patterns based on FHIR R4 specification, HIPAA regulations (45 CFR Parts 160, 162, and 164), and validated industry implementations)
Next Steps: Day 3 system architecture design with custom AI agent specifications, database schema (ERD), and API specifications.