“Integrate with the EHR” is one line on a roadmap and, very often, the item that takes longest to ship. The standard itself is not the hard part. FHIR is well designed and reasonably pleasant to work with. What takes the time is everything around it: authorization, the approval process for each health system, terminology, and the question of whose data this is once it leaves the chart. This guide covers what a team building a healthcare app needs to know about FHIR integration in 2026, using code from our own templates as examples, and it says plainly which parts are still integration work that no generator does for you.
1. What FHIR Is, and FHIR vs HL7 v2
FHIR (Fast Healthcare Interoperability Resources) is an HL7 standard for exchanging health data over a REST API as JSON or XML. Each clinical concept, whether a patient, a lab value, a prescription or a visit, is a resource with a defined structure, and you read and write resources with ordinary HTTP: GET /Patient/123, POST /Observation, GET /Observation?patient=123&category=laboratory.
The version that matters in the US is FHIR R4 (4.0.1). It is the version US regulation points at, through the US Core Implementation Guide, and it is what certified EHRs expose. R5 exists and R6 is in development, but if you are integrating with American health systems in 2026, you are writing R4.
HL7 v2 is the older standard. It is still everywhere, and it is not going away.
| HL7 v2 | FHIR R4 | |
|---|---|---|
| Shape | Pipe-delimited text messages (PID|1||12345^^^MRN||DOE^JANE) | JSON or XML resources over REST |
| Model | Event messages pushed between systems: an admission (ADT), a lab result (ORU), an order (ORM) | Resources you query, create and update on demand |
| Transport | Usually MLLP over a VPN, through an interface engine | HTTPS with OAuth 2.0 |
| Where you meet it | Inside a hospital: labs, radiology, registration feeds | Apps outside the hospital: patient apps, SaaS tools, anything third-party |
| Onboarding | A custom interface per site, specified by that site’s integration team | A standard API, still gated by per-site app approval |
A useful rule: if you are an app that a clinician or patient launches, you will use FHIR. If you are a system that has to receive every lab result a hospital produces as it happens, you will probably still get HL7 v2 messages, even in 2026. Plenty of production products do both.
2. The Resources Most Apps Actually Need
FHIR R4 defines around 145 resource types. A typical app touches fewer than ten. These cover most patient-facing and clinical-workflow products:
| Resource | What it holds | Typical use |
|---|---|---|
Patient | Demographics, identifiers (MRN), contact details | Every integration starts here |
Encounter | A visit, admission or telehealth session | Scheduling, visit history, billing context |
Observation | Vitals, lab results, survey scores, anything measured | Remote monitoring, lab portals, outcomes tracking |
Condition | Diagnoses and problems | Problem lists, risk scoring |
MedicationRequest | Prescriptions and medication orders | Medication lists, adherence apps |
AllergyIntolerance | Allergies and adverse reactions | Anything that suggests or prescribes |
DocumentReference | A clinical document or note, with its content | Filing an AI scribe note, uploading a PDF |
QuestionnaireResponse | Answers to a structured form | Patient intake, screening instruments |
Appointment | A booked slot | Scheduling and reminders |
Two supporting ideas matter as much as the resources themselves.
US Core profiles. A profile narrows a base resource: which fields are required, which code systems are allowed. US Core is the set of profiles certified EHRs support, and it maps to USCDI (the United States Core Data for Interoperability), the federal list of data elements that must be exchangeable. If your data fits US Core, the EHRs you talk to will understand it.
Terminology. The JSON shape is the easy part. The codes inside it are what receiving systems check: LOINC for labs and vitals, SNOMED CT for conditions, RxNorm for medications, ICD-10-CM for billing diagnoses, CVX for vaccines. An Observation with a well-formed body and a free-text code is, to most EHRs, an Observation they cannot file anywhere useful.
{
"resourceType": "Observation",
"status": "final",
"category": [{ "coding": [{
"system": "http://terminology.hl7.org/CodeSystem/observation-category",
"code": "vital-signs" }] }],
"code": { "coding": [{
"system": "http://loinc.org", "code": "8867-4", "display": "Heart rate" }] },
"subject": { "reference": "Patient/123" },
"effectiveDateTime": "2026-09-18T14:05:00Z",
"valueQuantity": { "value": 72, "unit": "/min",
"system": "http://unitsofmeasure.org", "code": "/min" }
}
3. SMART on FHIR: How an App Gets In
FHIR describes the data. SMART on FHIR describes how a third-party app is allowed to reach it. It is a profile of OAuth 2.0 and OpenID Connect, and it is what the major EHRs implement for outside apps. The current version is SMART App Launch 2.x, which requires PKCE and uses a finer-grained scope syntax than v1.
The flow has four steps.
- Discovery. The app fetches
/.well-known/smart-configurationfrom the FHIR server. It lists the authorization and token endpoints and the capabilities the server supports. - Launch. Either an EHR launch, where a clinician opens your app from inside the EHR and the EHR passes a
launchparameter with the current patient and encounter, or a standalone launch, where a patient opens your app directly and picks which record to connect. - Authorize. The user signs in at the EHR, not in your app, and approves the scopes you asked for. You get back an authorization code.
- Token. You exchange the code for an access token, and usually a refresh token, plus launch context such as the patient ID. Every FHIR call then carries the token.
Scopes decide what the token can reach. Ask for the least you need.
launch/patient openid fhirUser offline_access
patient/Patient.r
patient/Observation.rs?category=laboratory
patient/DocumentReference.c
In SMART v2 syntax, r is read, s is search, c is create, u is update and d is delete. The patient/ prefix limits the token to one patient’s data, user/ gives the signed-in user’s access, and system/ is for backend services. The minimum-necessary standard in HIPAA and the scope list in your SMART request are the same idea, and a health system’s reviewer will read the scope list with that in mind.
system/ scopes. Pair it with the Bulk Data $export operation when you need many patients at once. Health systems approve these more cautiously than user-facing apps, because no person is in the loop.
4. Getting Into Epic, Oracle Health and athenahealth
This is the part of FHIR integration that roadmaps under-estimate. Writing the code against a sandbox takes days. Being allowed to run it against a real health system’s production data takes much longer, and the steps are organisational rather than technical.
- Register as a developer with the vendor’s program: Epic’s at fhir.epic.com, Oracle Health’s (formerly Cerner) developer program, athenahealth’s developer portal. You get sandbox credentials and test patients.
- Build against the sandbox. Every vendor’s implementation has quirks: which search parameters they support, how they page results, which US Core profiles they emit, what they do with write requests. Test against each vendor you plan to support, not just one.
- Register the production app. You declare your redirect URIs, scopes, and whether the app is patient-facing, clinician-facing or a backend service.
- Get each health system to turn it on. For patient-facing apps that use the certified patient-access API, the process is usually lighter, because the regulation behind that API limits what a health system can demand. Clinician-facing and backend apps are different: each organisation decides for itself, usually after a security questionnaire, often after a BAA, and sometimes after a contract.
For a clinician-facing app, allow weeks to months per health system, not per vendor. The first go-live is the slowest, because you are also writing the security documentation, the data-flow diagram and the support process that every later site will ask for. Vendor program names and marketplace rules change often, so check the current terms before you plan around any of them.
5. FHIR and HIPAA: A Format, Not a Safeguard
FHIR makes no compliance claims and has no compliance features. A FHIR resource containing a diagnosis is PHI exactly as a database row containing that diagnosis is. Everything in the Security Rule still applies to it:
- Encryption. TLS 1.2 or later for every FHIR call, and encryption at rest for anything you cache. Tokens count as secrets too. See our PHI encryption guide.
- Audit logging. Log every FHIR read and write with actor, patient, resource type and outcome. A bulk export is one request that touches thousands of records, so log what it returned, not just that it ran. See our audit logging guide.
- Access control. The SMART token decides what the EHR will give you. Your own app still has to decide which of its users can see what it received.
- Business associate agreements. If you pull PHI on behalf of a covered entity, you are a business associate and need a BAA, and so does every vendor in your stack that stores or processes that data.
There is one case where the answer changes. When a patient directs their provider to send their record to an app the patient chose, and that app is not acting for the provider, HHS has said the provider is not responsible for what the app does with the data afterwards, and the app is generally not a business associate. That does not make the app unregulated. The FTC’s Health Breach Notification Rule covers many consumer health apps outside HIPAA, as do state health-privacy laws such as Washington’s My Health My Data Act. Work out which side of that line your product is on before you design the data flow, because the two sides have different obligations.
6. Export, Read, Write-Back: Three Different Projects
“FHIR integration” covers three jobs with very different effort. Scope them separately.
| Direction | What it means | Effort |
|---|---|---|
| Export | Your app produces FHIR from its own data, such as a patient downloading their record as a Bundle | Low. You control both ends of the mapping and no EHR approval is involved |
| Read | Your app pulls data from an EHR over SMART on FHIR | Medium. The code is standard; the per-site approval is the long part |
| Write-back | Your app creates or updates data inside the EHR | High. Many EHRs accept only a few resource types for writing, and every site will review it closely |
Export deserves more attention than it gets. Under HIPAA’s right of access (45 CFR 164.524), an individual can ask for their record in the electronic form they want if the practice can readily produce it. An app that can hand a patient a clean FHIR R4 Bundle meets that request with a single endpoint, and it is also the easiest way to prove your data model maps to FHIR at all.
Write-back is where plans go wrong. An AI scribe filing a signed note as a DocumentReference, or an intake chatbot writing a QuestionnaireResponse, are both reasonable designs. Neither works until the target EHR accepts that resource type for writing, the health system approves the write scope, and someone at that site agrees where in the chart the data should appear. Build write-back behind a flag, and make copy-to-clipboard or PDF the fallback until a site is live.
7. Six Mistakes That Get FHIR Resources Rejected
These come up repeatedly, and several came up in our own template code.
- Timestamps without an offset. FHIR requires a timezone whenever a
dateTimeincludes a time.2026-09-18T14:05:00is invalid;2026-09-18T14:05:00Zis valid. If your database stores naive timestamps, decide once, in one place, what timezone they are in. - Your own status words.
Encounter.status,Observation.statusandMedicationRequest.statuseach have a fixed value set. Sending your app’s own"confirmed"or"expired"where FHIR expects"planned"or"completed"can make a receiving system reject the whole resource. Map every internal status explicitly, and map anything unknown to the spec’s ownunknownvalue rather than passing it through. - References that don’t resolve. A Bundle where an Observation points at
Patient/42but noPatient/42is in the Bundle or on the server is broken, and validators will say so. - Identifiers with no system. An MRN of
"12345"means nothing on its own.Identifier.systemshould be a URI that names your organisation’s MRN namespace, so a receiving system can tell your 12345 from everyone else’s. - Ignoring paging. Search results come back one page at a time, with a
nextlink inBundle.link. Code that reads only the first page works in a sandbox with five test patients and silently drops data in production. - Treating structural checks as validation. Tests that check required fields and reference integrity are necessary, but they are not what the official HL7 FHIR validator does. The validator also checks codes against their value sets, which needs a terminology server. Run it before any partner does.
Here is how the first two look in the chart-export module of our general-practice template, where every internal status is mapped to the value set FHIR allows:
# Our vocabulary -> the value sets FHIR actually allows. Anything unrecognised
# becomes the spec's own "unknown" rather than being passed through: an invalid
# status code makes the whole resource unparseable to the receiving system.
_ENCOUNTER_STATUS = {
"pending": "planned",
"confirmed": "planned",
"completed": "finished",
"cancelled": "cancelled",
}
8. What a Generated App Gets, and What It Doesn’t
Our position is that you should know exactly where the generated code stops. Here is what VertiComply’s templates include today:
- Chart export as a FHIR R4 Bundle. The general-practice clinic template lets a signed-in patient download their whole record as a
collectionBundle containingPatient,Encounter,Observation,MedicationRequest,CarePlan,CompositionandDocumentReferenceresources, served asapplication/fhir+json. It is rate-limited, and every export is written to the audit log. Tests cover structural R4 conformance: required elements, allowed status codes, and every reference resolving inside the Bundle. It has not been through the official validator with a terminology server. - A FHIR R4 API surface in the EHR template. The modular EHR template publishes a CapabilityStatement (
fhirVersion 4.0.1), servesPatientread and create and a LOINC-codedObservationsearch for vitals, parses inbound HL7 v2 messages (MSH, PID and OBX segments), and audit-logs each call.
And here is what is still integration work, whatever tool you use:
- SMART on FHIR. The EHR template’s FHIR endpoints are protected by the app’s own clinician sign-in, not by SMART tokens. The OAuth authorize and token flow that an outside SMART app would need is not implemented, and the template deliberately does not publish a SMART discovery document until it is.
- A live connection to any real EHR. No template connects to Epic, Oracle Health or athenahealth, and the interoperability screens in demos show illustrative data. Connecting means the developer registration and per-site approval in section 4, and no code generator can do those for you.
- Write-back. The AI scribe and clinical-documentation templates hand the signed note to the clinician to paste into the chart, and they say so. Filing it through the EHR’s API is production work, done per health system.
If you need that last part built, a live Epic or Oracle Health connection is the kind of project our custom build team scopes. For the wider question of what a no-code EHR can and can’t do, start with our EHR app builder guide. If payments are involved, our Stripe and EHR guide covers mapping charges to FHIR Claim resources without leaking PHI into the processor.
9. Frequently Asked Questions
What is FHIR integration?
FHIR integration means connecting a healthcare application to other systems, usually an EHR, through the HL7 FHIR standard: a REST API that exchanges clinical data as structured resources such as Patient, Observation and MedicationRequest. In practice it has three parts: mapping your data to FHIR resources and codes, authorizing access (usually with SMART on FHIR), and getting each health system to approve your app.
What is the difference between HL7 and FHIR?
FHIR is one of the standards HL7 publishes. When people say “HL7” they usually mean HL7 v2, an older pipe-delimited messaging standard that systems inside a hospital use to push events such as admissions and lab results to each other. FHIR is a newer REST API with JSON resources, designed for apps to query and update data on demand. Most hospitals run both: HL7 v2 for internal feeds and FHIR for third-party apps.
What is SMART on FHIR?
SMART on FHIR is the authorization layer for FHIR apps, built on OAuth 2.0 and OpenID Connect. It defines how an app discovers an EHR’s authorization endpoints, how it launches either from inside the EHR or on its own, which scopes it can request (such as patient/Observation.rs), and how it receives the current patient and encounter context. Major EHRs, including Epic and Oracle Health, use it for third-party app access.
How long does it take to integrate with Epic using FHIR?
Building against Epic’s sandbox typically takes days to a few weeks, depending on how many resources you use. Going live takes longer, because each health system approves your app separately, usually with a security review and often a BAA and contract. Patient-facing apps using the certified patient-access API tend to move faster. Clinician-facing and backend apps commonly take weeks to months per health system.
Is FHIR HIPAA compliant?
FHIR is a data format and API standard, so it is neither compliant nor non-compliant. Compliance depends on how you handle the data: TLS for every call, encryption at rest, audit logs of each read and write, least-privilege scopes and user permissions, and BAAs with vendors that touch PHI. An app a patient chooses to receive their own record may fall outside HIPAA, but it can still be covered by the FTC Health Breach Notification Rule and state health-privacy laws.
Which FHIR version should I use?
Use FHIR R4 (4.0.1) with the US Core profiles if you are integrating with US health systems. It is the version referenced by US certification rules and the one certified EHRs expose. R5 is published and R6 is in development, but production EHR APIs in the US are R4.
Does the 21st Century Cures Act require my app to support FHIR?
The Cures Act rules apply mainly to certified EHR developers, health information networks and healthcare providers. Certified EHRs must offer a standard FHIR R4 API, and the information-blocking rules restrict interference with access to health data. A third-party app is usually not directly required to support FHIR, but FHIR is the practical way to get data out of those certified APIs, and a FHIR export is the simplest way to meet a patient’s HIPAA right-of-access request.
Can I write data back into an EHR with FHIR?
Sometimes. Write support varies by EHR and by resource type, and it needs write scopes that each health system must approve. Documents, questionnaire responses and some observations are the most commonly accepted. Plan write-back as a separate project from reading, keep a manual fallback such as copy-to-chart or PDF, and log every write with who initiated it and what was filed.
Last reviewed 18 September 2026. Timelines are typical ranges, and vendor developer-program names and approval rules change often, so check current terms before planning around them. Nothing here is legal advice on whether HIPAA or another privacy law applies to a specific product.