Back to BlogArchitecture & Engineering

FHIR API Integration for Startups: SMART on FHIR, Epic and Cerner Sandboxes

Rupak Amin

Founder & Lead Engineer, RAITHub

12 min read

FHIR API integration means reading and writing health data through HL7 FHIR R4 (version 4.0.1) REST endpoints, authorised with SMART on FHIR, an OAuth 2 profile. A first sandbox read of a Patient and their Observations from Epic or Oracle Health takes a developer about 2–4 days. Going live takes far longer: app registration, each health system's review, and mapping LOINC, SNOMED CT and RxNorm codes.

If you would rather have the integration built for you, see how RAITHub would build this below.

This is engineering guidance. RAITHub has not shipped a production EHR or FHIR integration; its 8 client projects include a healthcare scheduling app, and a FHIR integration would be new ground that a quote names as such. Where data rules apply, treat this as general information and confirm with your adviser.

What is FHIR, and which resources will my app actually use?

FHIR (Fast Healthcare Interoperability Resources) is the HL7 standard for exchanging health data as small JSON or XML documents called resources, over a REST API. Release 4 is the version US EHRs expose today; the R4 Observation page, for example, marks Observation as normative since 4.0.0. In the US, the US Core implementation guide narrows each resource to what US systems must support and tracks the USCDI data set.

Most startup integrations touch fewer than ten resource types:

ResourceHoldsTypical use in a startup app
PatientDemographics and identifiersMatch the EHR record to your user
ObservationVitals, lab results, social history, measurementsShow trends; feed a care programme or risk score
ConditionProblems and diagnosesEligibility and care-plan logic
MedicationRequestPrescriptionsMedication lists, adherence reminders
AllergyIntoleranceAllergiesSafety checks before recommendations
EncounterVisits and admissionsFollow-up after discharge
DiagnosticReportGrouped results, such as a lab panelShow a report with its Observations
Practitioner, OrganizationClinicians and facilitiesWho ordered or authored a record
Appointment, SlotSchedulingBooking, where the EHR exposes write access

Read access is widely available. Write access is not: many health systems allow only a few write operations, and each one is negotiated. Design your first version to read.

How does SMART on FHIR authorisation work?

SMART on FHIR is the OAuth 2 profile that FHIR servers use to grant apps scoped access. The current spec is SMART App Launch 2.2. The app discovers the server's authorize and token endpoints from [fhir-base]/.well-known/smart-configuration, runs an authorization-code flow, and gets back an access token, often with the patient ID it is allowed to see. The spec says "All SMART apps SHALL support Proof Key for Code Exchange (PKCE)", with the S256 method only.

There are three ways in:

FlowWho starts itContext you getFits
EHR launchA clinician, from inside the EHRThe EHR passes iss and an opaque launch value; the token response can carry the current patient and encounterClinician tools embedded in the EHR
Standalone launchA patient or clinician, from your appAsk for the launch/patient scope and the user picks a patient during sign-inPatient-facing apps that pull a user's records
Backend servicesYour server, no user presentSystem scopes; the client signs a JWT with its registered keyNightly syncs and bulk export for a population

Scopes name the resource and the permission. SMART 2 uses forms such as patient/Observation.rs (read and search for the launched patient), while many servers still accept the older patient/Observation.read; Oracle Health's documentation lists the v1 style. Add openid fhirUser if you need to know who signed in. Ask for the smallest set of scopes that does the job: reviewers at health systems read your scope list first.

In the US, certified EHRs must offer a standardised API for patient and population services under the ONC certification criterion 45 CFR 170.315(g)(10), which is why Epic and Oracle Health both publish SMART-protected FHIR endpoints.

How do I get access to the Epic and Cerner FHIR sandboxes?

Both vendors run free developer sandboxes with synthetic patients. Neither sandbox gives you access to any real health system.

EpicOracle Health (Cerner)
PortalEpic on FHIR, described by Epic as "a free resource for developers"Millennium Platform R4 APIs
Sandbox dataSynthetic test patients; Epic says the sandbox "should be populated only with sample or synthetic data"A public sandbox tenant, with an open (no-auth) endpoint and a secure SMART endpoint
RegistrationCreate an app, choose APIs and scopes, receive non-production and production client IDsRegister through Oracle's developer console and its authorization framework
Going livePer the Epic OAuth documentation, the app cannot be used in customer environments until marked ready for production, and each customer must sign the open.epic API Subscription AgreementEach Oracle Health client site enables your app on its own domain

The pattern is the same for both: the sandbox proves your code works; production access is granted one health system at a time.

What does a FHIR API call look like in TypeScript?

A minimal example: given a FHIR base URL and an access token from the SMART flow, read the Patient and page through their vital-sign Observations. It filters out OperationOutcome entries, which some servers include in search results, and caps the number of pages.

// fhir/read-patient.ts: Patient plus vital signs over FHIR R4
type Coding = { system?: string; code?: string; display?: string }

type Patient = {
  resourceType: 'Patient'
  id: string
  name?: { family?: string; given?: string[] }[]
  birthDate?: string
}

type Observation = {
  resourceType: 'Observation'
  id: string
  status: string
  code: { coding?: Coding[]; text?: string }
  effectiveDateTime?: string
  valueQuantity?: { value?: number; unit?: string; code?: string }
}

type Bundle = {
  resourceType: 'Bundle'
  entry?: { resource?: { resourceType: string } }[]
  link?: { relation: string; url: string }[]
}

async function fhirGet<T>(url: string, token: string): Promise<T> {
  const res = await fetch(url, {
    headers: { Authorization: 'Bearer ' + token, Accept: 'application/fhir+json' },
  })
  if (!res.ok) throw new Error('FHIR ' + res.status + ' on ' + new URL(url).pathname)
  return (await res.json()) as T
}

export async function readPatientVitals(baseUrl: string, token: string, patientId: string) {
  const id = encodeURIComponent(patientId)
  const patient = await fhirGet<Patient>(baseUrl + '/Patient/' + id, token)

  const observations: Observation[] = []
  let next: string | undefined = baseUrl + '/Observation?patient=' + id + '&category=vital-signs'
  for (let page = 0; next && page < 20; page++) {
    const bundle: Bundle = await fhirGet<Bundle>(next, token)
    for (const entry of bundle.entry ?? []) {
      if (entry.resource?.resourceType === 'Observation') {
        observations.push(entry.resource as Observation)
      }
    }
    next = bundle.link?.find((l) => l.relation === 'next')?.url
  }
  return { patient, observations }
}

Three details matter in production. The error message logs the path, not the full URL, because query strings can carry identifiers. The token is PHI-grade: keep it server-side, never in local storage. And follow the server's next link rather than building page URLs yourself, because each vendor paginates differently.

When should I use FHIR bulk data instead?

When you need data for a whole population, not one patient at a time: analytics, quality measures, payer or care-management programmes. The Bulk Data Access spec (v3.0.0) defines an asynchronous $export operation at system, Patient and Group level. You start an export with the header "Prefer: respond-async", get a 202 response with a status URL to poll, and download the results as NDJSON files, one resource per line. Bulk export uses the backend-services flow, so there is no user in the loop, and health systems treat it as a bigger request: expect more review than a single-patient app.

What actually takes the time in a FHIR integration?

Rarely the code. The planning figures below are typical ranges for a first integration, not vendor commitments; each health system sets its own pace.

PhaseWhat happensTypical effort
Sandbox buildSMART flow, reads, pagination, error handling against synthetic dataDays to two weeks
App registration and reviewScopes, a description of data use, and security answers for the vendor and each health systemWeeks per health system
ContractsAPI subscription terms and, where PHI flows to you, a BAA with the health systemWeeks to months; legal, not engineering
Terminology mappingMap local codes to LOINC (labs and vitals), SNOMED CT (conditions) and RxNorm (medications); normalise unitsThe longest engineering task; ongoing
Site-by-site variationDifferent enabled resources, extensions and data quality per health systemRepeats for every new site

Terminology is where integrations quietly go wrong. The same blood glucose result can arrive under different LOINC codes, in mg/dL from one site and mmol/L from another, or with only free text. Build a mapping table with tests, show the source code and unit alongside every derived value, and flag anything unmapped instead of guessing. The QA and test automation service describes how RAITHub tests this kind of logic.

Doing it yourself: a developer who knows OAuth can read a Patient and Observations from Epic's sandbox in 2–4 days. The main risk is assuming the sandbox predicts production: real sites differ in data, scopes and review, so budget for each one separately.

Buy, build or hire?

Prices are from each vendor's pricing page on 2 October 2026.

OptionExampleChoose this when
Integration platform (off-the-shelf)Redox: Sandbox plan from $15k a year for companies under 500 employees, Core from $35k a year for live productionYou need many health systems quickly, including HL7 v2 feeds, and can carry a platform fee
FHIR-native backend (template layer)Medplum: free tier for prototyping; hosted Production $2,000 a month with a BAAYou want your own FHIR data store and tooling without writing a FHIR server
Direct SMART integration (custom)Your code against Epic and Oracle Health endpoints, free developer portalsOne or two EHRs, read-mostly, and you want no per-connection platform fee
Hire a team to build itA fixed-scope integration with tests and runbooksYou have the product and the health-system partner, and need the integration done properly

Why RAITHub for this

RAITHub is a founder-led, QA-first software studio, founded in 2024 in Dhaka, Bangladesh, working with clients worldwide in English. To be plain: it has not shipped a production FHIR integration. What carries over:

  • Many external APIs, tested. PadhAI, an AI tutoring platform built by RAITHub, integrates 9 payment gateways across 11 services. Unreliable third-party APIs with different behaviour per provider are the same problem FHIR sites pose.
  • Large, tested backends. TheSkinProof, the founder's own venture rather than a client project, has 217 API endpoints and 750+ tests. Sundor Skin runs 146 PostgreSQL tables with row-level security and 530+ tests. See the work page.
  • Health-adjacent client work. RAITHub's 8 client projects include a healthcare scheduling app.
  • Your data stays yours. RAITHub signs NDAs and DPAs and works inside your controls. Production and patient data stay in your own BAA-covered cloud account; development uses the vendors' sandboxes and synthetic data. RAITHub makes no HIPAA compliance claim and does not sign BAAs.

When you don't need us

  • You need dozens of health systems now. An integration platform will get you there faster than any custom build.
  • Your EHR partner offers a ready connector for your use case. Use it.
  • You need a vendor that holds PHI under your BAA. RAITHub does not sign BAAs.
  • You need a native mobile app. RAITHub builds web apps and PWAs only; a PWA can run the SMART flow in the browser.
  • You need a certified health IT module. ONC certification is a separate programme RAITHub does not offer.

How RAITHub would build this

For a startup adding read access to one or two EHRs:

  • SMART client: discovery, authorization code with PKCE, token storage server-side, refresh, and the launch type your users need (EHR, standalone or backend services).
  • FHIR read layer: typed clients for Patient, Observation and the few other resources you need, with pagination and per-site configuration.
  • Terminology mapping: a tested mapping table for LOINC, SNOMED CT and RxNorm codes and units, with an unmapped-codes report.
  • Sandbox-first testing: automated tests against Epic and Oracle Health sandboxes and recorded synthetic fixtures, so CI never touches real patient data.
  • Review pack: scope justifications and architecture notes for each health system's app review.

Timeline: an integration-heavy backend or API build takes 6–12 weeks; a fixed-scope MVP around a single read integration can fit 4–6 weeks. Health-system review and contracts run on their own clock. See API and backend development, the HealthTech page and the health software guide.

You receive: automated tests and CI, handover docs and runbooks (including how to onboard a new health system), and full IP under NDA.

Next step: book the free 15-minute technical audit, then you get a written fixed quote. Do not send patient data in the first message.

Frequently asked questions

What is SMART on FHIR?

SMART on FHIR is an OAuth 2 profile that lets apps get scoped access to FHIR data, either launched from inside an EHR or standalone. It adds discovery, launch context such as the current patient, and scopes like patient/Observation.rs. PKCE is required.

Is the Epic FHIR sandbox free?

Yes. Epic describes Epic on FHIR as a free resource for developers, with synthetic test patients. Using an app at a real Epic customer is a separate step: the app must be marked ready for production and the customer must activate it.

Is Cerner FHIR the same as Oracle Health FHIR?

Yes. Cerner is now Oracle Health, and its Millennium Platform R4 APIs are documented on Oracle's site. The public sandbox offers an open endpoint and a secure SMART endpoint.

How long does a FHIR integration take?

A sandbox prototype takes days. Production usually takes months, because each health system reviews the app and contracts separately, and terminology mapping keeps going after launch.

Do I need a BAA to integrate with an EHR?

Often, if PHI flows from the health system to your company, but it depends on the arrangement; patient-directed access can differ. This is general information; confirm with your adviser.

What is FHIR bulk data export?

An asynchronous operation, $export, that returns data for a whole group or population as NDJSON files. It uses backend-services authorisation with no user present and is meant for analytics and population programmes.

FHIRSMART on FHIREpicOracle HealthCernerEHR integrationHealthTech

Ready to discuss your project?

Book a free 15-minute technical audit with our engineering team.