How to Read Lab and Imaging Reports from EHRs with
Your product can read a patient's diagnostic reports (lab panels, imaging studies, pathology and cardiology reports) from AdvancedMD, athenahealth, CharmHealth, Epic, MEDITECH, NextGen Healthcare, Oracle Health, Orion Health, PointClickCare, SMART on FHIR, TruBridge and Veradigm through one connection and one method call (as of 24 October 2026).
sdk.healthcare.listHealthcareReports returns the same Report object on all twelve, and each report links to its individual results, which you read as Observations. Every request is executed directly against the customer's EHR.
Why a report is more than its results
A lab result on its own is a number: glucose 105 mg/dL. Clinicians read results as reports: a complete blood count with its dozen values, issued together, with a status (preliminary or final) and often a conclusion. Imaging is almost all conclusion. Products that show results, alert on abnormal values, or summarize a patient's history for an AI model need both levels.
Unified.to's Healthcare API returns the report as a Report object with an observation_ids list, and each individual result as an Observation with its value, unit, reference range and interpretation. You read the report, then the results it points at.
What you are building
A results view: each report with its status and conclusion, expanded into its values with high/low flags.
- Authorize the customer's EHR and store one connection ID
- List a patient's reports
- Group results under their report using
observation_ids - Flag abnormal values using each observation's
interpretation - Pick up new and corrected reports where supported
List a patient's reports
import { UnifiedTo } from '@unified-api/typescript-sdk';
const sdk = new UnifiedTo({
security: { jwt: process.env.UNIFIED_API_KEY },
});
const reports = await sdk.healthcare.listHealthcareReports({
connectionId,
patientId,
limit: 50,
});
On a patient-launch connection, leave out patientId and Unified.to uses the patient who authorized it.
What each field tells you
type is LABORATORY, IMAGING, PATHOLOGY, CARDIOLOGY or OTHER, normalized from the EHR's report category. Use it to split a results tab into labs and imaging.
status follows the report's lifecycle: REGISTERED, PARTIAL, PRELIMINARY, FINAL, AMENDED, CORRECTED, APPENDED, CANCELLED, ENTERED_IN_ERROR. Show preliminary results as preliminary, and treat AMENDED and CORRECTED as replacing what you showed before.
observed_at is when the specimen was taken or the study performed; issued_at is when the report was released. Sort by observed_at for a clinical timeline and by issued_at for "new results" notifications.
conclusion is the reading clinician's interpretation, often the only content of an imaging report.
name and codes identify the test (LOINC for most panels). practitioner_ids are the clinicians responsible, and encounter_id the visit the test was ordered in.
Join reports to their results
observation_ids lists the results in the report. List the patient's lab observations once and index them by ID:
const observations = await sdk.healthcare.listHealthcareObservations({
connectionId,
patientId,
type: 'LABORATORY',
});
const byId = new Map(observations.map((o) => [o.id, o]));
const panels = reports.map((report) => ({
report,
results: (report.observation_ids ?? []).map((id) => byId.get(id)).filter(Boolean),
}));
Each observation carries value_number and value_unit (or value_text), a reference_range, and interpretation (NORMAL, ABNORMAL, LOW, HIGH, CRITICAL_LOW, CRITICAL_HIGH). Use interpretation for flags rather than comparing to the range yourself: the lab already decided.
Imaging reports usually have no observation_ids; render the conclusion.
Handling coverage that varies by EHR
Check support before you scope on the Supported Integrations page.
Treat 501 as information, not failure. An empty list means the patient has no reports; 501 means the EHR doesn't expose them.
Reports are read-only. Results come from the lab and the EHR; Unified.to reads them.
Stay current when results arrive
On Oracle Health, SMART on FHIR, TruBridge and Veradigm (as of 24 October 2026), subscribe to healthcare_report changes with [virtual webhooks](/blog/what_are_virtual_webhooks_how_they_differ_from_sync_based_webhooks), or call with updatedGte to read only reports changed since your last sync. Subscribe to updated as well as created: a preliminary report becoming final is an update. On the other EHRs, read on a schedule.
→ Start your 30-day free trial → Book a demo
Frequently asked questions
Can I filter reports by type on the server?
Not yet. Filter on type in your own code. To narrow results server-side, list Observations with type: 'LABORATORY'.
Can I get the PDF of a report?
The Report object returns the structured report. Where the EHR files the PDF as a clinical document, it appears in the Documents list with type: 'LABORATORY_REPORT' or 'IMAGING_REPORT', and its content is available through document_url.