Skip to main content

Quick Start

Two paths depending on whether you have an Epic developer account:

SMART Health IT sandboxEpic non-production sandbox
Account neededNoneFree โ€” fhir.epic.com
Real Epic dataNo โ€” synthetic Synthea patientsYes โ€” Epic's own sandbox patients
Time to first launch~5 minutes~75 minutes (includes 1-hour sync)
Maven profile-Psmart-Pepic

Start with the SMART Health IT sandbox โ€” it requires nothing and proves the full flow works.


1. Clone the repositoryโ€‹

git clone https://github.com/your-org/smart-fhir-client.git
cd smart-fhir-client

2. Start the appโ€‹

mvn spring-boot:run -Dspring-boot.run.profiles=smart

You should see:

INFO  SmartFhirApplication - Started SmartFhirApplication in 4.2 seconds
INFO FhirClientFactory - FhirClientFactory ready โ€” socketTimeout=30000ms, connectTimeout=10000ms

3. Verify the health endpointโ€‹

curl http://localhost:8080/health
{"status":"UP","app":"smart-fhir-client","epicClientId":"growth_ch..."}

4. Launch from SMART Health ITโ€‹

  1. Open launch.smarthealthit.org in your browser
  2. Set App Launch URL to http://localhost:8080/launch
  3. Set FHIR Version to R4
  4. Choose Launch Type โ†’ Provider EHR Launch
  5. Select any patient from the list
  6. Click Launch

Your browser redirects through the SMART handshake and lands on the dashboard at http://localhost:8080/.

What you should see
  • Blue patient banner with the selected patient's name
  • Dashboard with stat cards showing condition and medication counts
  • Navigation links to Patient, Conditions, Medications pages
  • Clinician profile card (if openid scope was granted)

Option B โ€” Epic non-production sandboxโ€‹

1. Register with Epic and get a client IDโ€‹

Follow the Epic Registration guide โ†’. This takes about 15 minutes plus a 1-hour sync wait.

2. Export your client IDโ€‹

export EPIC_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

3. Start the app with the Epic profileโ€‹

mvn spring-boot:run -Dspring-boot.run.profiles=epic

4. Launch from Epic LaunchPadโ€‹

  1. Open open.epic.com/launchpad
  2. Select SMART on FHIR App Launch
  3. Set Launch URL to http://localhost:8080/launch
  4. Pick a test patient (e.g. Camila Lopez)
  5. Click Launch

What happens during a launchโ€‹

Here is what the logs show for a successful EHR launch:

INFO  SmartLaunchController  - EHR launch received โ€” iss=https://launch.smarthealthit.org/v/r4/fhir
INFO SmartDiscoveryService - Fetching SMART configuration from ISS: https://...
INFO SmartDiscoveryService - SMART configuration cached โ€” authEndpoint=..., tokenEndpoint=...
DEBUG SmartAuthRequestBuilder - PKCE generated and stored in session โ€” challenge method: S256
INFO SmartLaunchController - Redirecting to authorize endpoint โ€” mode=ehr, state=abc123...
INFO SmartCallbackController - SMART EHR launch complete โ€” patient=eXXXX, encounter=eYYYY, scope=...
INFO IdTokenValidator - id_token validated โ€” subject=eProvider123
INFO UiController - Fetching Patient/eXXXX

Each log line maps to a class and package in the codebase:

Log lineClassPackage
EHR launch receivedSmartLaunchControllerlaunch/
Fetching SMART configurationSmartDiscoveryServicediscovery/
PKCE generatedSmartAuthRequestBuilderauth/
Redirecting to authorizeSmartLaunchControllerlaunch/
SMART EHR launch completeSmartCallbackControllertoken/
id_token validatedIdTokenValidatoroidc/
Fetching Patient/UiControllerui/

Exploring the APIโ€‹

After a successful launch, the session is authenticated. Use curl or your browser to explore all API endpoints:

Session infoโ€‹

Always safe โ€” works before patient is selected (standalone launch).

    curl http://localhost:8080/api/session
    {
"launchMode": "ehr",
"patientId": "erXuFYUfucBZaryVksYEcMg3",
"encounterId": "eEnc-789",
"needPatientBanner": true,
"grantedScopes": "launch openid fhirUser patient/Patient.rs ...",
"hasUserProfile": true,
"tokenExpiresAt": "2025-01-15T10:30:00Z"
}

Clinician profileโ€‹

Requires openid scope.

    curl http://localhost:8080/api/me
    {
"subject": "eProvider-ABC123",
"displayName": "Dr. Jane Smith",
"fhirUser": "Practitioner/eProvider-ABC123",
"issuer": "https://fhir.epic.com/..."
}

Patientโ€‹

Requires patient/Patient.rs scope.

    curl http://localhost:8080/api/patient
    {
"id": "erXuFYUfucBZaryVksYEcMg3",
"name": "Camila Lopez",
"birthDate": "1985-03-12",
"gender": "female",
"patientBanner": true
}

Conditionsโ€‹

Requires patient/Condition.rs scope.

    curl http://localhost:8080/api/conditions
    [
\{
"id": "eCond-001",
"code": "44054006",
"display": "Type 2 diabetes mellitus",
"status": "active"
\}
]

Summaryโ€‹

Combines all available data in one call.

    curl http://localhost:8080/api/summary

Running the testsโ€‹

Unit tests only (fast, no network)โ€‹

mvn test

Runs 140+ unit tests with WireMock stubs โ€” no internet access required. Typically completes in 15โ€“30 seconds.

SMART Health IT integration testsโ€‹

mvn verify -Psmart

Runs SmartHealthSandboxIT โ€” fetches the real discovery document from launch.smarthealthit.org and reads a known synthetic patient. Requires internet access.

Epic sandbox integration testsโ€‹

export EPIC_CLIENT_ID=your-non-production-client-id
mvn verify -Pepic

Runs EpicSandboxIT โ€” validates Epic's discovery document, builds an authorize URL with all Epic-required parameters, and reads a known Epic sandbox patient.


Common issuesโ€‹

Port 8080 is already in use

Change the port in application.yml:

server:
port: 8081

Update your redirect URI accordingly and re-register it in your Epic app if using the Epic profile.

The app starts but the session endpoint returns 401

You haven't completed a launch yet โ€” the session has no SmartLaunchContext. Run a launch from LaunchPad or SMART Health IT first.

Launch redirects to an error page in the browser

Check the app logs. The most common cause is a mismatched redirect URI โ€” what you registered in Epic or SMART Health IT must exactly match smart.epic.redirect-uri in application.yml.

Conditions or medications return an empty array

The selected patient may not have active conditions or medications in the sandbox. Try a different patient, or check that the relevant scopes are in application.yml.

id_token validation warning in the logs
WARN  IdTokenValidator - JWKS fetch failed โ€” skipping signature check

This is non-fatal. FHIR data access works normally. Full cryptographic RS256 signature verification requires adding nimbus-jose-jwt โ€” see the OIDC guide.


Next stepsโ€‹