🚀 JamEMR v1.0 — 16 clinical modules, FHIR R4 native, Apache License 2.0.  Deploy with one command →
Open source · FHIR R4 native · Apache License 2.0

The complete open source
FHIR-native EMR

The only open source Java EMR that stores patient data natively as FHIR R4 — not translated, not wrapped, not exported. 16 clinical modules, SMART on FHIR v2.0, DHIS2 national reporting, and a complete insurance revenue cycle. One command to deploy.

Aligned with HL7 FHIR R4 SMART App Launch v2.0 HAPI FHIR 7 WHO DHIS2 PEPFAR DATIM FHIR AuditEvent Spring Modulith
200+Java source files
120+Thymeleaf templates
16Clinical modules
27FHIR R4 resource types
138Audit call sites
Apache 2.0Open source

The JamEMR difference

Built FHIR-first — not FHIR-adapted

Every other open source EMR stores data in a proprietary schema and bolts FHIR on top. JamEMR uses HAPI FHIR JPA as its only database — zero translation overhead, full interoperability from day one.

FHIR-native storage Patients are Patient resources. Prescriptions are MedicationRequest resources. Invoices are Invoice resources. :8090/fhir →
27
FHIR R4 resource types — all native storage
From Patient and Encounter to Coverage, Claim, ClaimResponse, and AuditEvent. Any FHIR-capable system integrates directly. No custom adapter work, ever.
:8090/fhir — standard FHIR search
16
Spring Modulith modules — verified every build
Declared allowedDependencies verified by ModularStructureTest on every Maven build. Feature-flagged with @ConditionalOnProperty — zero startup cost for unused modules.
@ApplicationModule
7
Spring application events — modules never couple
VitalsSavedEvent triggers NEWS2. MedicationSavedEvent triggers drug-allergy. StdDiagnosisConfirmedEvent triggers contact tracing. Each is a typed Java record.
@ApplicationModuleListener
60s
Caffeine-cached dashboard — instant page loads
Nine HAPI queries fire in parallel via CompletableFuture, cached for 60 seconds with a 200-entry maximum. Always fast — even on large datasets.
Caffeine + CompletableFuture
PDF
iText 7 PDF generation — stored as FHIR DocumentReference
Prescription PDFs and patient summaries stored as DocumentReference resources with LOINC codes 57833-6 (prescription) and 34133-9 (summary of episode note).
LOINC 57833-6 · 34133-9
QR
FHIR Questionnaire forms engine — zero code
Build intake forms using Questionnaire + QuestionnaireResponse with group nesting, conditional logic, LOINC codes per item, and all FHIR item types.
enableWhen · LOINC items

Clinical modules

Everything your clinic needs.
Only what you turn on.

Ready to deploy now Patient Registry · Appointments · Billing · IPD · CDS · HIV · Paediatrics · Reporting · Imaging · SMART docker compose up →

Feature flags via @ConditionalOnProperty mean unused modules never start. Configure once in Docker Compose; override any flag per environment with a single environment variable.

Patient Registry + Full Clinical Record
Always active
Active

Complete clinical timeline: encounters, allergies, ICD-10 conditions, LOINC-coded vitals, MedicationRequest prescriptions, CVX-coded immunisations, diagnostic reports, procedures, family history, documents. MRN and blood group as FHIR extensions.

Patient Encounter Condition MedicationRequest Observation
8310-5 · 8867-4 · 85354-9 · 29463-7 · 8302-2 · 2708-6
Appointments + Practice Queue
Always active
Active

7-day calendar view, per-practitioner queues with sequential token assignment, receptionist check-in / call / no-show / undo flow, and a public TV display at /queue/display/ — no auth required, designed for lobby screens.

Appointment Queue tokens TV display
Lifecycle: proposed → booked → arrived → fulfilled
Billing + Full Insurance Revenue Cycle
emr.modules.billing · insurance
Optional

FHIR-native revenue cycle, three phases complete. Phase 1: Coverage + InsurancePlan. Phase 2: Claim generation from Invoice — pre-tax lines, duplicate-claim guard. Phase 3: ClaimResponse adjudication, automatic Invoice reconciliation with gap invoicing.

Coverage Claim ClaimResponse Invoice
5 claim-tracking extensions keep modules decoupled
Clinical Decision Support
emr.modules.cds
Optional

Drug-allergy checker with three-level matching (exact SNOMED → display overlap → drug class cross-reactivity). NEWS2 (0–20) fires on every vitals save, stored as FHIR RiskAssessment. Persistent DetectedIssue alerts on the patient chart.

DetectedIssue RiskAssessment NEWS2 (0–20) 3-level allergy
Zero config — activates on any vitals or prescription save
HIV / ART Programme
emr.modules.hiv
Optional

Complete ART programme: enrolment (EpisodeOfCare), viral load and CD4 trend observations, WHO clinical staging, regimen prescribing and switching. All routes require ROLE_HIV_PROVIDER via @PreAuthorize — enforced at the service layer.

ART regimens Viral load trends WHO staging Role-gated
Paediatrics + WHO Growth Monitoring
emr.modules.paediatrics
Optional

WHO growth monitoring with z-scores: WAZ, HAZ, WHZ, MUAC. Interactive Chart.js growth charts. WHO EPI vaccination schedule with due/overdue/given status per antigen. Weight-based dosing calculator with dose capping and age-band validation.

WAZ/HAZ/WHZ WHO EPI schedule Dosing calculator
National Reporting + DHIS2 / DATIM Export
Always active
Active

FHIR-to-analytics ETL (nightly 2 AM or manual trigger), 7 operational reports. Aggregates OPD, malaria (ICD-10 B50–B54), TB, NCDs, EPI vaccine doses by CVX code. Exports as DHIS2 dataValueSet JSON, PEPFAR DATIM, or HMIS CSV.

DHIS2 dataValueSet PEPFAR DATIM HMIS CSV
TX_CURR · TX_NEW · HTS_TST · HTS_POS — pre-configured
SMART on FHIR App Launch v2.0
emr.security.mode=smart
Optional

Complete SMART App Launch v2.0: PKCE S256 with 128-character code_verifier at RFC 7636 maximum length, RS256 id_token validation via Nimbus JOSE+JWT against RemoteJWKSet, proactive token refresh 120s before expiry, session fixation protection. Launches from Epic, Cerner.

PKCE S256 RS256 JWT Token refresh Epic · Cerner
Inpatient (IPD) — Ward, Rounds & Discharge
emr.modules.ipd
Optional

Live ward dashboard with FHIR Location-based bed grid, admissions via EpisodeOfCare, SOAP ward-round notes with inline vitals, patient transfer, and discharge with disposition coding. Bed lifecycle: Available → Occupied → Housekeeping → Available.

EpisodeOfCare Location SOAP rounds Discharge
Bed lifecycle: Available → Occupied → Housekeeping → Available
Radiology + PACS Integration
emr.modules.imaging
Optional

FHIR ImagingStudy resources, radiology order workflow, Orthanc PACS integration via DICOMweb (WADO-RS, STOW-RS, QIDO-RS), and OHIF Viewer 3 launch links for browser-based DICOM viewing.

ImagingStudy Orthanc PACS OHIF Viewer 3

How it works

From patient registration to national report —
every step in FHIR

JamEMR's clinical workflow is a continuous chain of FHIR resources. Every action creates or updates a resource that is immediately queryable, auditable, and interoperable.

01
Patient arrives — FHIR Patient resource created
Receptionist registers the patient. Creates a Patient resource with demographics, MRN as identifier, blood group and emergency contacts as extensions. Instantly searchable by name, MRN, or any FHIR search parameter.
FHIR: Patient · Identifier · AuditEvent
02
Appointment booked — queue updated live
An Appointment resource is created and a token assigned. Check-in sets status to arrived. The TV display at /queue/display/ updates in real time — no auth required, for lobby screens.
FHIR: Appointment · status lifecycle
03
Vitals saved — NEWS2 fires automatically
Vitals stored as FHIR Observation resources with LOINC codes. VitalsSavedEvent fires asynchronously. NEWS2Calculator computes the NEWS2 score (0–20) and stores a RiskAssessment.
FHIR: Observation · RiskAssessment
04
Prescription written — drug-allergy check runs
A MedicationRequest is created. MedicationSavedEvent fires. DrugAllergyChecker runs three-level matching. A DetectedIssue is stored and shown as a banner on the chart if a conflict is found.
FHIR: MedicationRequest · DetectedIssue
05
Invoice generated — claim submitted and reconciled
FHIR Invoice with ChargeItemDefinition line items. A Claim is generated with pre-tax values. The insurer's remittance creates a ClaimResponse. reconcileInvoice() marks the invoice balanced.
FHIR: Invoice · Claim · ClaimResponse
06
ETL runs — indicators submitted to DHIS2
The ETL reads FHIR resources and populates the analytics database. Aggregates OPD, malaria, TB, EPI, and PEPFAR HIV indicators. Dhis2ExportService POSTs a dataValueSet JSON to your DHIS2 instance.
DHIS2 dataValueSet · DATIM · HMIS CSV

Technical architecture

Every design decision has a documented reason

Every architectural choice in JamEMR is deliberate and traceable — from storage layer to event bus to security model. Here are the decisions that matter most in a clinical system.

FHIR storage layer

HAPI FHIR 7
  • HAPI FHIR JPA R4 backed by PostgreSQL 15-alpine — no secondary schema
  • Full FHIR search indexing on every resource type from day one
  • Version history preserved on all resources — no hard deletes in the clinical workflow
  • Configurable HAPI HTTP client connection pool — tunable per-route and total limits with connect and socket timeouts
  • Reporting ETL writes to an isolated reporting schema via @Qualifier("reportingTx") — zero contention with the clinical FHIR server under load

Spring Modulith

Build-time verified
  • 16 packages each with package-info.java declaring allowedDependencies
  • ModularStructureTest.verifiesModularStructure() fails the Maven build on any boundary violation — no silent coupling
  • Internal DTOs live in internal/ sub-packages — structurally inaccessible across module boundaries
  • All cross-module communication via typed Spring application events only
  • @ConditionalOnProperty on every feature-flagged module — unused modules add zero startup cost

Insurance revenue cycle

FHIR-native
  • Coverage.payor[] references an Organization resource — no separate insurer entity or custom table
  • Claim.item[].net stores pre-tax subtotals — insurers don't pay VAT or GST
  • 5 claim-tracking extensions written back to the Invoice keep billing and insurance modules fully decoupled
  • ClaimResponseService.reconcileInvoice() is idempotent — safe to call more than once without side effects
  • Gap invoicing: if patientOwes > 0 after adjudication, the Invoice remains issued for cash collection

Security hardening

Production-ready
  • HTTP security headers on every response: CSP, X-Frame-Options: DENY, Referrer-Policy: strict-origin
  • HSTS enabled in smart mode only — skipped in development so plain-HTTP local setups work normally
  • Global @ControllerAdvice strips HAPI server URLs and JDBC strings from all error responses before they reach the browser
  • Patient deactivation is POST-only and CSRF-protected — prevents link-based or crawled data loss
  • Spring Boot Actuator restricted to /health and /info only — all introspection endpoints are inaccessible

7 typed application events — modules that communicate without coupling

CriticalResultEvent, VitalsSavedEvent (triggers NEWS2 calculator), MedicationSavedEvent (triggers drug-allergy checker), StdDiagnosisConfirmedEvent (triggers contact tracing), PregnancyRegisteredEvent, EncounterCreatedEvent, PatientCreatedEvent. Each is a typed Java record — no stringly-typed payloads, no runtime class-cast surprises.

VitalsSavedEvent
NEWS2Calculator
RiskAssessment stored
MedicationSavedEvent
DrugAllergyChecker
DetectedIssue stored
StdDiagnosisConfirmedEvent
ContactTracingService
RelatedPerson stored

Quick start

A fully configured clinical environment
in under two minutes

Docker Compose launches HAPI FHIR JPA, Orthanc PACS, OHIF Viewer 3, and the JamEMR app — all networked, all configured, all ready.

Terminal
# Clone and start git clone https://github.com/vedpr625/FHIR-Electronic-Medical-Records cd FHIR-Electronic-Medical-Records docker compose up -d # Wait ~45s for HAPI to initialise, then open open http://localhost:8080 # JamEMR open http://localhost:8090/fhir # HAPI FHIR R4 API open http://localhost:8042 # Orthanc PACS open http://localhost:3000 # OHIF Viewer 3 # Configure via environment variables — no config files to edit FHIR_SERVER_URL=http://your-hapi/fhir EMR_MODULES_HIV=true DHIS2_URL=https://hmis.health.gov.ke SPRING_SECURITY_USER_PASSWORD=your-secure-password
JamEMR
:8080 · Spring Boot 3.2 · Java 17
HAPI FHIR JPA R4
:8090 · PostgreSQL 15-alpine
Orthanc PACS
:8042 · DICOMweb · DICOM :4242
OHIF Viewer 3
:3000 · React · WADO-RS
01 — CONFIGURE
Set environment variables
Override FHIR_SERVER_URL, security credentials, and DHIS2 UID mappings via env vars. No YAML to edit.
02 — ACTIVATE
Enable the modules you need
EMR_MODULES_HIV=true, EMR_MODULES_PAEDIATRICS=true per deployment. Unused modules add zero startup cost.
03 — REPORT
Connect to national HMIS
Set DHIS2_URL and your facility's data element UIDs. OPD, malaria, TB, EPI, and PEPFAR indicators automatically.
04 — INTEGRATE
Launch from any SMART EHR
Set emr.security.mode=smart and register with Epic, Cerner, or any SMART v2.0-compliant EHR. PKCE launch flow in under 10 minutes.

SMART on FHIR

Full SMART App Launch v2.0 —
every control, no shortcuts

Not a subset, not "mostly compliant." Every PKCE parameter, every RS256 claim, every token-refresh rule — implemented to spec.

1
EHR initiates the launch
Epic, Cerner, or any SMART EHR calls GET /smart/launch?iss=&launch=. The EMR validates ISS against the SMART discovery document (cached per-ISS), builds a PKCE pair with a 128-character code_verifier at RFC 7636 maximum length (derived from 96 bytes of secure random input) and S256 challenge, then redirects to the EHR authorize endpoint with a state nonce for CSRF protection.
2
Identity verified with RS256 — no trust-on-first-use
After code exchange, the id_token is validated using Nimbus JOSE+JWT DefaultJWTProcessor with RemoteJWKSet against the EHR's JWKS endpoint. Signature, expiry, issuer, audience, and nonce all verified. Full RFC 7517 key rotation support.
3
Session secured, tokens proactively refreshed
SmartSecurityFilter populates the Spring SecurityContext on every request. TokenRefreshFilter proactively refreshes tokens on /api/** routes 120 seconds before expiry — no expired-token errors surfacing to clinicians mid-workflow.
PKCE
128-char code_verifier
RFC 7636 max · 96-byte entropy
ID token
RS256 · RemoteJWKSet
Nimbus DefaultJWTProcessor
Token refresh
120s proactive
Before expiry · /api/** routes
CSRF
Double Submit Cookie
CookieCsrfTokenRepository
Session
Fixation protection
changeSessionId() on auth
Security mode
3-mode config
development · smart · basic

Technology stack

Proven, well-supported, battle-tested

Every dependency is a deliberate choice — maintained by large organisations, widely deployed in healthcare, and stable enough to build a clinical system on.

Runtime
Java 17
LTS · Eclipse Temurin
Long-term support. Runs on any JVM — bare metal, Docker, or cloud VM.
Framework
Spring Boot
3.2
Auto-configuration, dependency injection, Security, Scheduling. The industry standard for Java services.
FHIR engine
HAPI FHIR
7.x · JPA R4
The dominant open-source FHIR implementation on the JVM, widely used for FHIR integrations across the healthcare ecosystem.
Database
PostgreSQL
15-alpine (Docker)
HAPI FHIR JPA's primary store. H2 in-memory for development without Docker.
Architecture
Spring Modulith
1.2.x
Build-time boundary verification. Module allowedDependencies enforced on every Maven build.
Templates
Thymeleaf
3.x · 120+ templates
Server-side rendering. Works without JavaScript. Accessible, SEO-friendly clinical UI.
PDF generation
OpenPDF / iText
Apache License 2.0 compatible
Prescriptions, summaries, and invoices stored as FHIR DocumentReference with LOINC codes. Use OpenPDF (LGPL) or Apache PDFBox for full Apache License 2.0 compatibility.
SMART / JWT
Nimbus JOSE+JWT
9.x
RS256 id_token validation against RemoteJWKSet. Full PKCE and nonce verification.
Cache
Caffeine
3.x · 60s TTL
Bounded cache with TTL eviction. Prevents unbounded memory growth on high-traffic deployments.
PACS
Orthanc
latest · DICOMweb
Open-source DICOM server. WADO-RS, STOW-RS, QIDO-RS. Paired with OHIF Viewer 3.
DICOM Viewer
OHIF Viewer 3
React · DICOMweb
Browser-based DICOM viewer. No plugin, no install. Launched from radiology orders.
Reporting
DHIS2 Web API
v2.36+ · dataValueSet
Aggregated indicators to national HMIS. Any DHIS2 v2.36+ instance worldwide.

National alignment

Built for any national health system,
anywhere in the world

Configure once for your country's reporting standards and interoperability requirements. JamEMR adapts to local health information systems, regulatory frameworks, and disease surveillance programmes — without customisation work.

DHIS2 national HMIS reporting — any instance, any version
Posts aggregated indicator data directly to any DHIS2 v2.36+ Web API as a standard dataValueSet JSON payload. Supply your facility's organisation unit UID and data element UIDs once — the ETL handles OPD, malaria, TB, NCD, maternal health, and EPI indicator aggregation automatically on a nightly schedule or manual trigger.
dataValueSet POST DHIS2 v2.36+ OrgUnit configurable HMIS CSV fallback
PEPFAR / DATIM HIV programme reporting — pre-configured MER indicators
TX_CURR, TX_NEW, HTS_TST, and HTS_POS PEPFAR MER indicators are pre-configured in every deployment. Age and sex disaggregation via categoryOptionCombo — the same UIDs used across all PEPFAR-supported programmes worldwide. No additional mapping required; deploy and start reporting on day one.
TX_CURR · TX_NEW HTS_TST · HTS_POS Age/sex disaggregation DATIM Web API
ICD-10 disease coding for national disease surveillance
All conditions are coded using ICD-10 — the international standard required by WHO-aligned national surveillance systems. Malaria (B50–B54), tuberculosis (A15–A19), sexually transmitted infections (A50–A64), and non-communicable diseases are automatically aggregated into the reporting ETL for submission to your national disease reporting system.
ICD-10 coded Malaria B50–B54 TB A15–A19 NCD surveillance
WHO EPI vaccination schedule — national immunisation programme ready
CVX-coded immunisation records align with any WHO Expanded Programme on Immunisation schedule. Due, overdue, and given status tracked per antigen per patient. Coverage rates aggregated by the reporting ETL for submission to national EPI dashboards. Configure your country's schedule once via the vaccine catalogue — no code changes.
CVX coded EPI schedule Coverage reporting Due/overdue tracking
FHIR R4 native storage — interoperable with any national health exchange
Because patient data is stored natively as FHIR R4 resources — not translated on demand — any national health information exchange, digital health platform, or ministry of health system that supports FHIR can query :8090/fhir directly using standard search parameters. No custom integration work required to connect to FHIR-based national data repositories.
FHIR R4 native Standard search API No adapter layer MoH system ready
National health insurance scheme integration — FHIR Claims lifecycle
The complete FHIR insurance revenue cycle — Coverage, Claim, and ClaimResponse — maps directly to the claims workflows used by national health insurance schemes worldwide. Configure your scheme's plan catalogue, copay rules, and adjudication logic once. The same workflow handles both public insurance schemes and private insurers without any structural changes.
National scheme ready FHIR Coverage · Claim ClaimResponse Plan catalogue
SMART on FHIR v2.0 — launch from any national EHR or HIE
Full SMART App Launch v2.0 means JamEMR can be launched as an embedded clinical app from any national electronic health record system or health information exchange that supports the SMART on FHIR standard. PKCE, RS256 JWT validation, and proactive token refresh are all implemented to spec — not approximated.
SMART v2.0 PKCE S256 RS256 JWT HIE compatible
Offline-capable deployment — air-gapped and low-connectivity environments
Docker Compose bundles the entire stack locally — FHIR server, database, PACS, and viewer — with no dependency on external cloud services. All clinical operations work without internet access. Reporting data accumulates locally and can be submitted to national systems when connectivity is available, or downloaded as a CSV for manual upload.
Fully offline capable Local FHIR server CSV manual upload Air-gap compatible

Platform capabilities

Where JamEMR stands out

A complete, production-grade clinical platform — every feature engineered to FHIR R4 spec, not bolted on afterward.

FHIR & Interoperability
Native FHIR R4 storage via HAPI FHIR JPA
27 resource types stored directly in HAPI FHIR JPA — no schema translation, no adapter layer. Every resource is queryable via standard FHIR search at :8090/fhir from day one.
SMART on FHIR App Launch v2.0 — full spec implementation
PKCE S256 with 128-character code_verifier at RFC 7636 maximum length, RS256 id_token validation via Nimbus JOSE+JWT against RemoteJWKSet, proactive token refresh 120 seconds before expiry, session fixation protection. Launches from Epic, Cerner, and any SMART v2.0-compliant EHR.
Complete FHIR insurance revenue cycle — three phases
Phase 1: Coverage + InsurancePlan catalogue. Phase 2: Claim generation from Invoice with pre-tax line items and duplicate-claim guard. Phase 3: ClaimResponse adjudication with automatic invoice reconciliation and gap invoicing.
FHIR Questionnaire forms engine
Build any clinical form — intake assessments, screening tools, consent forms — using Questionnaire + QuestionnaireResponse. All FHIR item types, group nesting, enableWhen conditional logic, LOINC codes per item. No Java required.
iText 7 PDF generation stored as FHIR DocumentReference
Prescription PDFs and patient summaries stored as DocumentReference resources with LOINC codes 57833-6 (prescription) and 34133-9 (summary of episode note). Every printable document is also a queryable FHIR resource.
Clinical Decision Support
Drug-allergy checker — three-level matching, fires automatically
Level 1: exact SNOMED code match. Level 2: display name word overlap. Level 3: drug class cross-reactivity (prescribing amoxicillin is blocked when a penicillin allergy is recorded). Fires asynchronously on every MedicationRequest save via MedicationSavedEvent. Stores a DetectedIssue on conflict.
NEWS2 early warning score — fires on every vitals save
NHS National Early Warning Score 2 (0–20) calculated on every Observation save via VitalsSavedEvent. Scores respiratory rate, SpO₂, systolic BP, heart rate, temperature, and consciousness (AVPU). Stores a FHIR RiskAssessment and logs a CDS audit event on elevated scores.
138 FHIR AuditEvent call sites — ATNA-aligned event structure
Every CREATE, UPDATE, DELETE, and CDS-ALERT across all 16 modules written as a FHIR AuditEvent asynchronously via @Async("taskExecutor"). Audit writes never block the HTTP request thread. AuditEvent resources use ATNA-aligned agent, source, entity, and outcome structure.
Clinical Modules
Full patient clinical record — 27 FHIR resource types
Encounters with SOAP notes, allergies with severity grading, ICD-10 conditions, LOINC-coded vitals, prescriptions, CVX-coded immunisations, diagnostic reports, procedures, family history, and clinical documents. MRN, blood group, and emergency contacts as FHIR extensions.
Appointment scheduling + live practice queue with TV display
7-day calendar view, per-practitioner queues with sequential token assignment, receptionist check-in / call / no-show / undo flow. Public TV waiting-room display at /queue/display/ — no authentication required, designed for lobby screens.
HIV / ART programme with PEPFAR reporting
Complete ART programme: enrolment (EpisodeOfCare), viral load and CD4 trend observations, WHO clinical staging (I–IV), regimen prescribing and switching (WHO lines 1A–3A). All routes require ROLE_HIV_PROVIDER enforced at the service layer — protection holds regardless of security mode.
Paediatrics with WHO growth monitoring and EPI schedule
WHO growth monitoring with z-scores: WAZ, HAZ, WHZ, MUAC. Interactive Chart.js growth charts rendered in the browser. WHO EPI vaccination schedule with due / overdue / given status per antigen. Weight-based dosing calculator with dose capping and age-band validation.
Inpatient ward management — beds, rounds, discharge
Live ward dashboard with bed-status grid, FHIR Location-based bed management, admissions via EpisodeOfCare, SOAP ward-round notes with inline vitals, patient transfer, and discharge with disposition coding. Bed lifecycle: Available → Occupied → Housekeeping → Available.
ANC (WHO minimum 8-contact), gynaecology, and sexual health
ANC follows the WHO minimum 8-contact model (2016 guidelines). Gynaecology covers Pap smear with Bethesda classification. STD module carries FHIR security labels on all resources, Cache-Control: no-store on all /std/** responses, and ICD-10 A50–A64 filtered from general condition lists.
Radiology with Orthanc PACS and OHIF Viewer 3
FHIR ImagingStudy resources, radiology order workflow via ServiceRequest, Orthanc PACS integration via DICOMweb (WADO-RS, STOW-RS, QIDO-RS), and OHIF Viewer 3 launch links for browser-based DICOM viewing — no plugin, no install.
National Reporting & Data Exchange
DHIS2 national reporting — dataValueSet POST or CSV download
FHIR-to-analytics ETL runs nightly at 2 AM or on manual trigger. Aggregates OPD attendance, malaria (ICD-10 B50–B54), TB (A15–A19), NCDs, and EPI vaccine doses by CVX code. Posts a dataValueSet JSON directly to any DHIS2 v2.36+ instance, or produces an HMIS CSV for manual upload.
PEPFAR DATIM indicators — pre-configured, zero setup
TX_CURR, TX_NEW, HTS_TST, and HTS_POS with PEPFAR MER UIDs pre-configured in every deployment. Age/sex disaggregation via categoryOptionCombo. No country-specific mapping required — UIDs are standardised across all PEPFAR programmes.
7 operational reports — activity, disease, prescriptions, revenue, immunisation, ETL status
Built-in reporting dashboard with OPD activity, disease burden, prescription volume, revenue summary, immunisation coverage, practitioner productivity, and ETL pipeline status. All reports read from the isolated analytics schema — zero impact on the FHIR server under load.
Architecture & Security
Spring Modulith — build-time boundary verification
16 modules each with package-info.java declaring allowedDependencies. ModularStructureTest.verifiesModularStructure() fails the Maven build on any violation. Feature-flagged with @ConditionalOnProperty — unused modules add zero startup cost.
Event-driven CDS — 7 typed application events, zero coupling
VitalsSavedEvent, MedicationSavedEvent, StdDiagnosisConfirmedEvent, PregnancyRegisteredEvent, EncounterCreatedEvent, PatientCreatedEvent, CriticalResultEvent. Each is a typed Java record — no stringly-typed payloads. Modules communicate without cross-module imports.
Production security hardening — all modes
CSP, X-Frame-Options: DENY, Referrer-Policy: strict-origin applied in every security mode. HSTS in smart mode. Global @ControllerAdvice strips HAPI URLs and JDBC strings from error responses. Patient deactivation is POST-only (CSRF-protected). Actuator exposes only /health and /info.
Caffeine-cached parallel dashboard — fast under load
Nine HAPI bundle queries fire in parallel via CompletableFuture, results cached for 60 seconds with a 200-entry maximum. Bounded eviction prevents unbounded memory growth. Dashboard page loads are consistently fast even on deployments with tens of thousands of patients.
Single-command deploy — Docker Compose with all services pre-wired
docker compose up -d launches JamEMR, HAPI FHIR JPA on PostgreSQL, Orthanc PACS, and OHIF Viewer 3 — all networked, all configured, ready in under 90 seconds. All configuration via environment variables. No config files to edit, no manual service wiring.
Apache License 2.0 — no vendor lock-in
Use commercially, modify freely, deploy on any infrastructure. No CLA, no paid tier required for production use, no feature gating. Fork it, extend it, build products on top of it. The full codebase — 200+ Java files, 128 templates, all 16 modules — is yours under the Apache License 2.0.
200+Java files · no generated code
16Modulith modules · verified
27FHIR R4 resource types
7Application events
138Audit call sites
ApacheLicense 2.0

Frequently asked

Questions from evaluators

Why use FHIR R4 as the storage layer rather than just an export format?
Other EMRs store data in a proprietary schema and generate FHIR on demand — meaning FHIR queries are slow, the schema drifts from the spec over time, and external systems need custom integration work. JamEMR stores directly as FHIR resources in HAPI FHIR JPA. Any FHIR-capable system — Epic, Cerner, a public health dashboard, a mobile app — can query https://your-fhir-server/fhir with standard FHIR search parameters from day one. No custom adapter work, ever.
How does the insurance revenue cycle work end-to-end?
Phase 1: Record the patient's Coverage (insurer, policy number, copay/deductible). Phase 2: Generate a Claim from the issued Invoice — pre-tax line items map to Claim.item[], 5 claim-tracking extensions are written back to the Invoice so billing and insurance modules stay independent. Phase 3: When the insurer's Remittance Advice arrives, record a ClaimResponse. Click "Reconcile Invoice" to set insuranceCovered, update patientOwes, and mark the invoice balanced.
What does DHIS2 reporting require to configure?
Four environment variables: DHIS2_URL, DHIS2_USERNAME, DHIS2_PASSWORD, and DHIS2_ORG_UNIT. Then one property per indicator mapping your data element UIDs. PEPFAR DATIM UIDs (TX_CURR, TX_NEW, HTS_TST, HTS_POS) are pre-configured and don't vary by country. In download-only mode you still get a JSON dataValueSet and HMIS CSV for manual upload.
Can I add custom modules without forking?
Yes. Create com.emr.fhir.yourmodule, add a package-info.java with @ApplicationModule(allowedDependencies = {"core"}), annotate your service with @ConditionalOnProperty, and add the flag to Docker Compose. The Modulith architecture test verifies your boundary declarations on every build. Subscribe to existing clinical events without coupling to any other module's internal classes.
Can JamEMR run without internet access?
Completely. Docker Compose includes a local HAPI FHIR JPA instance backed by PostgreSQL — no external FHIR server required. All clinical operations work locally with no network access. The only internet-dependent features are SMART on FHIR (requires the EHR's JWKS endpoint) and DHIS2 submission (requires the national HMIS URL). Both are optional and fully skippable in air-gapped environments.

Support tiers

Open source. Professionally supported.

Community support is free and permanent. Structured support is available for clinics and governments that need deployment guarantees.

Community
Free forever
  • GitHub Issues + Discussions
  • Full documentation
  • All releases · Apache License 2.0
Standard
Contact us
  • Email support
  • 2-business-day response SLA
  • Security patch notifications
  • Configuration guidance
Recommended
Enterprise
Contact us
  • Phone + email support
  • 4-hour response SLA
  • 24-hour security patches
  • Custom feature roadmap
  • On-premises deployment assistance
Government
Contact us
  • Custom SLA with 24/7 coverage
  • National DHIS2 / DATIM alignment
  • Technical team training
  • Procurement documentation