
Hey, HealthTech Builders!
In the rapidly evolving world of healthcare IT, the ability to securely access Electronic Health Records (EHRs) is a game-changer. EPIC, one of the most widely adopted EHR systems, offers this capability through SMART on FHIR APIs — enabling developers to build powerful applications around patient data.
In this guide, we’ll walk through how to integrate with EPIC using Python, leveraging OAuth 2.0’s Client Credentials flow to build a secure Backend Services App. This type of app is ideal for system-to-system communication where no user login is required.

What You’ll Learn
- How to register an app on the EPIC Developer Portal
- Set up a simple Python backend project
- Authenticate using JWT
- Pull patient data from the EPIC FHIR API
Step 1: Register Your App on the EPIC Developer Portal
Start by visiting the EPIC developer site: https://fhir.epic.com/
- Log in or create an account.
- Navigate to My Apps > Create New App.
- Select Backend Services App.
- Enter:
- App Name
- Description
- FHIR API Version: R4
- Under Scopes, select:
- Upload your public key (explained in Step 2).
- Save the Client ID and FHIR base URL provided.
Step 2: Generate Your Key Pair
You’ll need a private-public RSA key pair to sign your JWT and authenticate with EPIC.
Run the following in your terminal:
bash
# Generate private key
openssl genrsa -out private_key.pem 2048
# Generate public key
openssl rsa -in private_key.pem -pubout -out public_key.pem
Upload public_key.pem to the EPIC Developer Portal.
Keep private_key.pem safe — this stays on your backend only.
Step 3: Create Your Python Project Structure
Here’s a clean and minimal project setup:
epic_ehr_integration/
├── auth.py # Handles authentication logic
├── fhir.py # Fetches patient data
├── private_key.pem # Your private RSA key
├── main.py # Entry point
└── requirements.txt
Step 4: Set Up Python Environment
Create requirements.txt with the following dependencies:
nginx
requests
PyJWT
cryptography
Then install them:
bash
CopyEdit
pip install -r requirements.txt
Step 5: Authenticate Using JWT (auth.py)
# auth.py
import time
import jwt
import requests
CLIENT_ID = "your-epic-client-id"
TOKEN_URL = "https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token"
PRIVATE_KEY_PATH = "private_key.pem"
def get_access_token():
with open(PRIVATE_KEY_PATH, "r") as key_file:
private_key = key_file.read()
now = int(time.time())
payload = {
"iss": CLIENT_ID,
"sub": CLIENT_ID,
"aud": TOKEN_URL,
"jti": str(now),
"exp": now + 300 # Token valid for 5 minutes
}
jwt_token = jwt.encode(payload, private_key, algorithm="RS384")
headers = { "Content-Type": "application/x-www-form-urlencoded" }
data = {
"grant_type": "client_credentials",
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
"client_assertion": jwt_token,
"scope": "system/Patient.read"
}
response = requests.post(TOKEN_URL, data=data, headers=headers)
response.raise_for_status()
return response.json()["access_token"]
Step 6: Fetch Patient Data (fhir.py)
# fhir.py
import requests
def get_patient_list(access_token, base_url):
headers = {"Authorization": f"Bearer {access_token}"}
url = f"{base_url}/Patient?_count=10" # Retrieve 10 patients
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()
Step 7: Run the Application (main.py)
# main.py
from auth import get_access_token
from fhir import get_patient_list
FHIR_BASE_URL = "https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4"
def main():
token = get_access_token()
patients = get_patient_list(token, FHIR_BASE_URL)
for entry in patients.get("entry", []):
patient = entry["resource"]
name = patient.get("name", [{}])[0]
full_name = f"{name.get('given', [''])[0]} {name.get('family', '')}"
print(f"Patient ID: {patient['id']}, Name: {full_name}")
if __name__ == "__main__":
main()
Conclusion
You now have a fully working Python backend integrated with EPIC’s FHIR API using secure OAuth 2.0 authentication. This setup allows you to fetch patient records programmatically — a powerful foundation for building EHR-connected healthcare apps.
You can extend this project to include:
- Encounter details
- Clinical notes
- Lab results
- Write-back functionality (with appropriate permissions)
Keeping the initial implementation simple ensures security and scalability as your app evolves. Whether you’re creating a clinical dashboard, analytics tool, or health monitoring service, this pattern is a proven, production-ready approach.