Skip to main content

FHIR API Explained: How EHR Integration Works (Epic, Oracle Health, HL7 v2).

15 min read
By Houston IT Developers

Quick Answer: A FHIR API is a REST-style web interface that exposes healthcare data as standard "resources" (Patient, Observation, Encounter and so on), usually exchanged as JSON. Most modern EHR integrations use FHIR R4 over HTTPS with SMART on FHIR (OAuth 2.0) for authorization. Older but still very common integrations use HL7 v2 messages, often routed through an interface engine such as Mirth Connect. A real project is mostly vendor registration, sandbox testing and customer approval, not code.

If you are building software that has to read from or write to an electronic health record, you will hit three acronyms in the first week: FHIR, HL7 and SMART. This guide explains what each one does, how they fit together, and what the work looks like in practice. We are a Houston software company that builds healthcare software, including EHR integration services, and we will say plainly where the standard stops and the vendor-specific work begins.

One piece of context on our own experience: we build and run clinical documentation software for home-health agencies, including visit documentation and EHR integration. That is the lens for the practical notes below. Everything about the standards and vendors is taken from their own public documentation, linked inline and read on November 1, 2026.

What FHIR is, in plain English

FHIR (Fast Healthcare Interoperability Resources) is, in HL7's words, "a standard for exchanging healthcare information electronically". The core idea is the resource: a small, standardized chunk of health data with a defined structure. A patient's demographics are one resource. A single lab result or blood-pressure reading is another. A visit is another.

FHIR does not model the whole hospital in one giant message. Per the same HL7 overview, specific use cases are usually implemented by combining resources. That is the practical difference from older HL7 standards, and it is why developers find FHIR approachable: you ask for the piece you need.

Resources you will meet first:

ResourceWhat it holds
PatientDemographics: name, birth date, gender, address, contact details, identifiers
EncounterA visit, admission or other interaction
ObservationMeasurements and simple assertions: vitals, lab values, device readings
ConditionDiagnoses and problems
MedicationRequestA prescription or medication order
AppointmentA scheduled visit
DocumentReferenceA pointer to a document, such as a clinical note or PDF

Each resource has a published definition on HL7's site. For example, the Patient resource page lists identifiers, name, gender, birth date, address and contacts, and marks the resource as normative, meaning stable enough for production use. The Observation page describes it as covering measurements and simple assertions about a patient, with a code (what was observed, typically a LOINC code), a subject, a time, and a value.

Versions: why everyone says "R4"

HL7 publishes FHIR in numbered releases. The overview page lists R5 as the latest release (published March 2023) with R4B, R4, R3 and R2 still available. In practice, R4 is the version most US EHRs expose. Epic's developer site lists R4 as its most current supported version alongside STU3 and DSTU2 (Epic on FHIR), and the SMART App Launch guide notes it works with any FHIR version from DSTU2 onward.

When a vendor says "we support FHIR," always ask: which release, which resources, and read-only or read and write? Those three answers decide your project.

REST and JSON: what a call looks like

FHIR's HTTP interface follows ordinary REST patterns, as laid out on HL7's RESTful API page:

  • Read: GET [base]/[type]/[id] returns one resource.
  • Search: GET [base]/[type]?param=value returns a Bundle of type searchset, with paging.
  • Create: POST [base]/[type] makes a new resource, returning 201 Created.
  • Update: PUT [base]/[type]/[id] replaces an existing resource.

The formal media type for JSON is application/fhir+json. FHIR also supports XML, and HL7 notes resources do not strictly require REST, but REST plus JSON is what you will almost always use.

Worked example: read a Patient, search Observations

The following is an illustrative example with fake data. It is not from any real system, and real servers add more fields (extensions, meta, narrative text).

Step 1. Read one patient by ID:

GET https://fhir.example-hospital.test/R4/Patient/example-123
Accept: application/fhir+json
Authorization: Bearer <access token>

An illustrative response:

{
  "resourceType": "Patient",
  "id": "example-123",
  "identifier": [
    { "system": "urn:example:mrn", "value": "000000" }
  ],
  "name": [
    { "family": "Sample", "given": ["Pat"] }
  ],
  "gender": "female",
  "birthDate": "1950-01-01"
}

Step 2. Search that patient's vital-sign observations:

GET https://fhir.example-hospital.test/R4/Observation?patient=example-123&category=vital-signs
Accept: application/fhir+json
Authorization: Bearer <access token>

An illustrative response (trimmed to one entry):

{
  "resourceType": "Bundle",
  "type": "searchset",
  "entry": [
    {
      "resource": {
        "resourceType": "Observation",
        "id": "obs-1",
        "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/example-123" },
        "effectiveDateTime": "2026-10-15T09:30:00Z",
        "valueQuantity": { "value": 72, "unit": "beats/minute" }
      }
    }
  ]
}

Three things to notice. The patient is referenced by ID, not copied into each observation. The "what was measured" part is a coded value, so your software can recognize heart rate without parsing text. And the result comes back as a Bundle, which you page through if there are many entries.

What the example hides is everything before the first call: you cannot just send that request. You need an access token, and getting one is the SMART part.

SMART on FHIR: how authorization works

FHIR defines the data. SMART App Launch defines how an app proves who it is and what it may see. It is an HL7 implementation guide built on OAuth 2.0 (HL7 SMART App Launch). It describes two main patterns:

  1. SMART App Launch, for user-facing apps. A clinician or patient signs in, approves access, and the app receives a token, optionally with context such as the current patient.
  2. SMART Backend Services, for automated systems with no user at the keyboard.

Permissions are expressed as scopes tied to resource types. HL7's examples include user/Encounter.rs (read and search Encounters the signed-in user can see) and system/Encounter.rs (the same for a backend service). Note that scope syntax changed after SMART v1, so older tutorials that show patient/Observation.read use the earlier form.

Epic's documentation mirrors this. Its OAuth guidance distinguishes patient-facing apps, clinician-facing apps launched inside the EHR, and backend systems, and describes the token response from a SMART launch: an access token, a refresh token, and the patient's FHIR ID (Epic OAuth 2.0 documentation).

The practical rule: ask for the narrowest scopes that do the job. A reviewing health system will read your scope list, and every extra resource is a reason for them to say no.

Read access vs write access in practice

Reading is the easy half. Writing is where projects slow down, for good reasons: a bad write corrupts a medical record.

Epic's documentation shows the split clearly. Its published read APIs include Patient.Search, Patient.Read and EpisodeOfCare.Search, while write support is narrower: for example, Observation.Create is documented for filing patient-entered vitals from patient-facing apps, and the same documentation points to HL7 v2 interfaces for backend systems filing flowsheet data (Epic on FHIR documentation). In other words, even at the largest EHR vendor, "FHIR write" is a per-resource, per-app-type question, not a switch.

What this means for your plan:

  • Design the product so it is useful with read-only access, then add writes where the vendor supports them.
  • For each write, confirm the exact resource, who the user type must be, and whether the customer has to enable it.
  • Expect extra review for anything that changes the chart.
  • Keep an audit trail on your side of every record you send.

In our own home-health documentation work, the distinction between pulling context into a visit note and filing something back into the agency's EHR is the line that decides how long an integration takes.

Bulk FHIR: when you need many patients at once

Single-record calls do not scale to "give me all patients in this group." For that, HL7 publishes the FHIR Bulk Data Access (Flat FHIR) implementation guide, currently v3.0.0 (STU 3), based on FHIR R4. HL7's repository describes it as defining "a standardized, FHIR based approach for exporting bulk data from a FHIR server to a pre-authorized client". The full specification lives at hl7.org/fhir/uv/bulkdata.

You will meet bulk access in population analytics, quality reporting and data migration. It pairs naturally with SMART Backend Services, since there is no user present. Read the specification itself before designing around it; the details of the export workflow matter and vendors vary in what they support.

HL7 v2: the older standard that still runs hospitals

Before FHIR there was HL7 v2, and it has not gone away. HL7 describes v2 as one of its most widely adopted standards, built from messages composed of reusable segments (HL7 comparison of FHIR and v2). In practice, v2 messages are event notifications sent between systems, usually over a persistent connection inside the hospital network. Three types matter most:

MessageStands forTypical use
ADTAdmit, Discharge, TransferTells other systems a patient was registered, admitted, moved or discharged, or that demographics changed
ORUObservation Result (Unsolicited)Sends results, such as lab values or reports, to another system
SIUScheduling Information UnsolicitedAnnounces new, changed or cancelled appointments

HL7's own comparison page lists the differences you should plan for. v2 segments cannot be independently manipulated the way FHIR resources can; v2 is generally not human-readable; sites extend it with custom "Z-segments" whose meaning must be explained separately; and, importantly, HL7 states that mapping between v2 and FHIR generally needs to be done on an implementation-by-implementation basis.

That last point is the reason integration is a project, not a plugin. Two hospitals can both send "ADT^A01" and populate fields differently.

Epic's documentation reflects the same reality: it describes backend systems receiving HL7 v2 alongside its FHIR APIs. If you are integrating with a hospital, assume you may need both.

Where interface engines like Mirth Connect fit

An interface engine sits between systems. It receives messages (often HL7 v2), checks them, transforms them, and routes them to one or more destinations. You would reach for one when:

  • you receive HL7 v2 from several sources with different quirks,
  • you need to translate v2 into FHIR resources (or the reverse),
  • you want retry, queueing and message logging in one place instead of inside your app.

Mirth Connect is probably the best-known example. It is operated by NextGen Healthcare, which describes it as an integration engine supporting protocol conversion, message mapping, HL7 and FHIR-enabled capabilities (NextGen's integration engine page). If you are budgeting for it, check the license terms: NextGen's page describes a commercial product with annual per-server licensing, but older public documentation described it as open source, so confirm the current terms with NextGen directly before you commit.

The honest decision rule: if your product is a FHIR app talking to an EHR's REST API, you may not need an engine at all. If your product sits on the receiving end of hospital HL7 v2 feeds, you almost certainly want one, whether Mirth Connect or another.

The regulation behind it: Cures Act, ONC and information blocking

Why do EHR vendors expose these APIs at all? Partly because the law pushes them to.

The 21st Century Cures Act established information blocking rules. ONC defines information blocking as practices likely to interfere with access, exchange or use of electronic health information, except when required by law or covered by an exception. It applies to three groups: healthcare providers, health IT developers of certified products, and health information exchanges and networks (ONC information blocking page). ONC lists exceptions, including privacy, security, preventing harm, fees and "manner" of provision.

ONC's Cures Act Final Rule goes further for certified EHRs. It calls on the industry to adopt standardized APIs, built on FHIR and the USCDI (United States Core Data for Interoperability) data set, so individuals can access structured health information using smartphone apps (ONC Cures Act Final Rule). Developers in ONC's Health IT Certification Program must meet conditions of certification that include not engaging in information blocking (ONC Health IT Certification Program).

What that means for you as a developer:

  • Certified EHRs should offer a standard FHIR API for patient data, which is why a basic read integration is now feasible without a custom contract in many cases.
  • A vendor cannot simply refuse access without fitting an exception, but exceptions (security, fees, manner) are real, so "you can have the data" does not mean "on your preferred timeline, for free, in the format you want."
  • None of it removes HIPAA. You still need a business associate agreement where applicable and a secure environment. See our guide to HIPAA-compliant hosting on AWS, Azure and Google Cloud.

What an EHR integration project actually involves

Here is the checklist we work from. The code is the smallest item on it.

  1. Define the data flow. List each resource you need, whether each is read or write, and the user type (clinician, patient, backend).
  2. Pick the vendor path. For Epic, that starts at open.epic.com and fhir.epic.com. Epic describes a testing sandbox, client registration and developer documentation, and the open.epic site offers developer playbooks and a template that creates a client ID with recommended APIs.
  3. Register the app. You request a client ID per environment. Request only the scopes and APIs you need.
  4. Build against the sandbox. Epic says its sandbox simulates an EHR environment, is for testing only, and should hold only sample or synthetic data. Never put real patient data in it.
  5. Prepare for customer approval. Epic's documentation states production access requires the customer organization (an Epic Community Member) to approve and activate the integration, and direct access to Epic's software can be granted only with approval from both that member and Epic. Each hospital or clinic is its own approval, with its own security questionnaire.
  6. Handle HL7 v2 where needed. Stand up the interface (and an engine if warranted), agree message specifications and test with the site's sample messages.
  7. Secure the environment. BAA with each cloud provider, encryption, access logging, minimum-necessary scopes.
  8. Test against real-world variation. Different sites populate fields differently. Test missing values, merged patients, corrected results and time zones.
  9. Plan go-live. Staged rollout, monitoring, a rollback plan and a named contact on the customer's IT side.
  10. Plan for maintenance. Vendors release new versions and retire old ones. Budget for upgrades.

What about Oracle Health?

Oracle Health (formerly Cerner) has its own FHIR APIs and developer program. We do not cover Oracle's program in detail here. The general shape (register, sandbox, scopes, customer approval) is the same, but confirm each step in Oracle's current documentation.

Need help with an integration?

If an integration is one feature of a larger product, it helps to work with a team that has been through vendor approval before. We design and build EHR integration as part of broader healthcare software development. Related reading: what drives healthcare app development cost.

FAQ

What is a FHIR API? A FHIR API is a web API that exposes healthcare data as standardized resources such as Patient, Observation and Encounter. Apps read and search those resources over HTTP, usually exchanging JSON, using the HL7 FHIR standard.

Is FHIR the same as HL7? FHIR is one standard published by the HL7 organization. HL7 also publishes the older HL7 v2 messaging standard, which is still widely used inside hospitals for events such as admissions and lab results.

Can I write data back into Epic through FHIR? Sometimes, but not everywhere. Epic documents specific write APIs, such as Observation.Create for patient-entered vitals, while many workflows still use HL7 v2 interfaces or other mechanisms. Check the current API list for the exact resource and customer.

Do I need Mirth Connect to integrate with an EHR? No. An interface engine such as Mirth Connect is useful when you must receive, route and transform HL7 v2 messages from several systems. A pure FHIR app that talks to an EHR's REST API may not need one.

How long does an EHR integration take? It depends on the vendor's registration process, the number of customer organizations that must approve the app, and how much testing each requires. The approvals often take longer than the code, so start them early.

Planning an EHR integration?

Tell us which EHR, which data and which users, and we will tell you what is realistic. Start with our EHR integration services page or talk to our team.

Sources read November 1, 2026: HL7 FHIR overview, REST API, Patient, Observation, FHIR vs v2, SMART App Launch; ONC at healthit.gov; Epic at fhir.epic.com and open.epic.com; NextGen's integration engine page. Standards and vendor programs change, so verify against the originals before you build.

Houston IT Developers

Houston IT Developers

Houston IT Developers is a leading software development and digital marketing agency based in Houston, Texas. We specialize in web development, mobile apps, and digital solutions.

View all posts →

Need Help With Your Project?

Our team of experts is ready to help you build your next web or mobile application. Get a free consultation today.

Get in Touch

Related Posts