Nirmitee.io
FHIREHR IntegrationInteroperability

FHIR Observation Resource Explained (R4): Vitals, Labs and Screening Results with Real JSON

July 31, 202618 min readUpdated Sep 24, 2026
Written by
Jitendra Choudhary
Jitendra Choudhary

CTO & Co-Founder

CTO & Co-Founder at Nirmitee.io. Architects healthcare integrations across FHIR, SMART on FHIR, ABDM and NHCX, writing from production experience taking hospital software from sandbox to go-live.

FHIR Observation Resource Explained (R4): Vitals, Labs and Screening Results with Real JSON

A FHIR Observation is the R4 resource that carries one measurement or simple assertion about a patient: a heart rate, a potassium result, an AUDIT-C score, a smoking status. If your product ingests vitals, labs, remote monitoring readings or screening scores from an EHR, almost all of it arrives as Observation resources, each pairing a code (usually LOINC) with a value, a time and a subject.

This field guide checks each element against the FHIR R4 (4.0.1) specification and US Core, uses JSON captured from public test servers and the spec, and shows what Epic and Oracle Health document for reading and writing Observations.

Key takeaways

  • Base R4 Observation requires only status and code. Profiles such as US Core make subject, category and effective time mandatory.
  • Vital signs use fixed LOINC codes and UCUM units. Blood pressure is one Observation (85354-9) with systolic and diastolic components.
  • Lab results are Observations referenced from DiagnosticReport.result; the Observation carries value, reference range and interpretation.
  • Screenings use hasMember to link a panel to item Observations. component is for values that cannot stand alone.
  • The code search parameter matches Observation.code only, so systolic 8480-6 will not find a blood pressure panel.
  • EHRs differ on value types, reference ranges, local codes and write support. Read each vendor's docs before designing ingestion.

What is the FHIR Observation resource?

Observation is the FHIR resource for measurements and simple assertions about a patient, device or other subject. It holds vital signs, lab results, imaging findings, device readings, screening scores, social history and exam findings. Each instance records what was measured (code), the result (value), when it was true (effective) and whose record it belongs to (subject).

The R4 Observation specification also implies what Observation is not. A diagnosis belongs in Condition (see our FHIR Condition resource guide), the order-level lab report belongs in DiagnosticReport, and raw questionnaire answers belong in QuestionnaireResponse. Observation sits between them and points to them. New to how resources fit together? Start with what FHIR is and how it models healthcare data.

Observation anatomy: elements and cardinality

Observation has two dozen top-level elements; ingestion logic depends on about sixteen. Only status and code are mandatory in base R4, which is why the same clinical fact looks different on every server. Here is each element with its most common pitfall.

ElementCard.TypeWhat it holdsCommon pitfall
status1..1coderegistered, preliminary, final, amended, corrected, cancelled, entered-in-error, unknownA modifier. Filtering on final alone drops corrected results.
category0..*CodeableConceptBroad class, such as vital-signsOptional in base, required by US Core. Can repeat.
code1..1CodeableConceptWhat was measured, usually LOINCLocal codes sit beside LOINC. Match system plus code.
subject0..1Reference(Patient | Group | Device | Location)Whose record it isUS Core requires a Patient.
encounter0..1Reference(Encounter)Visit contextOften absent for outside labs and home readings.
effective[x]0..1dateTime | Period | Timing | instantCollection or measurement timeChart on this, not on issued.
issued0..1instantWhen this version was releasedGood for new-result alerts only.
performer0..*ReferenceWho is responsible for the valueThe Patient for home readings.
value[x]0..111 types: Quantity, CodeableConcept, string, boolean, integer, Range, Ratio and moreThe resultNever assume valueQuantity.
dataAbsentReason0..1CodeableConceptWhy the value is missingobs-6: only when value[x] is absent.
interpretation0..*CodeableConceptH, L, N, A, HH, LLExtensible, so local flags appear.
device0..1Reference(Device | DeviceMetric)The measuring deviceThe cuff, not the relaying phone.
referenceRange0..*BackboneElementlow, high, type, appliesTo, age, textobs-3: needs low, high or text.
hasMember0..*Reference(Observation | QuestionnaireResponse | MolecularSequence)Panel membersThe panel itself has no value.
derivedFrom0..*ReferenceSource dataLinks a score to its answers.
component0..*BackboneElementValues measured togethercode search ignores component codes.

Three base invariants catch most malformed data. obs-3: a reference range needs a low, high or text. obs-6: dataAbsentReason appears only when there is no value. obs-7: if code repeats a component code, the top-level value must be empty. Validate these on ingest. Our guide to FHIR profiles, extensions and Must Support explains how profiles tighten the optional elements.

Which Observation category codes will you see?

R4 defines nine codes in the observation-category code system: vital-signs, laboratory, social-history, imaging, procedure, survey, exam, therapy and activity. The binding is Preferred, so servers can add their own. Category is the first filter you apply, and in some EHR APIs it changes which other search parameters are honored.

CategorySpec scopeTypical integration source
vital-signsBP, heart and respiratory rate, height, weight, BMI, SpO2, temperatureNursing flowsheets, RPM devices
laboratorySpecimen-based chemistry, hematology, microbiology, pathologyLIS feeds, reference labs
social-historyLifestyle, occupational and environmental historySmoking status, alcohol use
surveyAssessment tools and survey instrumentsPHQ-9, AUDIT-C, Apgar
examPhysical exam findingsStructured exam documentation
imagingFindings from x-ray, ultrasound, CT, MRIMeasurements from imaging reports
procedureResults of non-lab, non-imaging proceduresEndoscopy, cardiac cath
therapyNon-interventional treatment protocolsPhysical, nutrition therapy
activityActivity outside clinical supervisionSteps, sleep from wearables

Definitions are in the R4 category value set. Real APIs support a subset and add codes: Oracle Health lists laboratory, vital-signs, social-history, survey and sdoh.

FHIR vital signs: LOINC codes and UCUM units

The R4 vital signs profile fixes a LOINC code and UCUM unit for each common vital sign. Each vital sign Observation needs a status, the vital-signs category, one of these codes, a patient, an effective time, and either a numeric value with a UCUM unit or a dataAbsentReason. The bindings are extensible, so additional codings are allowed.

Vital signLOINCUCUM unitSpec note
Vital signs panel85353-1noneMembers via hasMember. Replaces 8716-3.
Respiratory rate9279-1/min
Heart rate8867-4/min
Oxygen saturation2708-6%59408-5 (pulse oximetry) may be added.
Body temperature8310-5Cel, [degF]
Body height8302-2cm, [in_i]
Body length (lying)8306-3cm, [in_i]Typically infants.
Head circumference9843-4cm, [in_i]
Body weight29463-7g, kg, [lb_av]
Body mass index39156-5kg/m2
Blood pressure panel85354-9noneComponents only.
Systolic BP8480-6mm[Hg]Component code.
Diastolic BP8462-4mm[Hg]Component code.
Mean BP8478-0mm[Hg]

Source: the R4 vital signs profile. Two details break parsers. valueQuantity.unit is display text and valueQuantity.code is the UCUM code, so "mmHg" and "mm[Hg]" appear together; convert on system plus code. And when a local code is recorded, the spec expects the standard LOINC too, so pick the LOINC coding from code.coding. For mapping at scale, see terminology services for SNOMED, LOINC and RxNorm.

US Core 9.0.0 adds a profile for each vital sign plus pediatric percentiles, listed on the US Core profiles page. Which version an EHR certifies against is covered in USCDI vs US Core version mapping.

How is blood pressure represented in FHIR?

Blood pressure is one Observation coded 85354-9 with no top-level value and two components, systolic (8480-6) and diastolic (8462-4), each a valueQuantity in mm[Hg]. Both components are required, though either may carry a dataAbsentReason. This response from the public HAPI FHIR R4 server is trimmed, with identifiers replaced:

{
  "resourceType": "Observation",
  "status": "final",
  "category": [{ "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "vital-signs" }] }],
  "code": { "coding": [{ "system": "http://loinc.org", "code": "85354-9", "display": "Blood pressure panel" }] },
  "subject": { "reference": "Patient/example" },
  "effectiveDateTime": "2026-07-30T10:27:00",
  "component": [
    {
      "code": { "coding": [{ "system": "http://loinc.org", "code": "8480-6", "display": "Systolic blood pressure" }] },
      "valueQuantity": { "value": 120, "unit": "mmHg", "system": "http://unitsofmeasure.org", "code": "mm[Hg]" }
    },
    {
      "code": { "coding": [{ "system": "http://loinc.org", "code": "8462-4", "display": "Diastolic blood pressure" }] },
      "valueQuantity": { "value": 80, "unit": "mmHg", "system": "http://unitsofmeasure.org", "code": "mm[Hg]" }
    }
  ]
}

The captured timestamp has no timezone offset, although R4 says one SHALL be present when a time is given. Decide which zone to assume and flag it. The search trap: code=8480-6 will not return this resource. Search on 85354-9, or use combo-code, which matches code and component.code where supported.

FHIR lab results: DiagnosticReport plus Observation

A lab result has two layers. DiagnosticReport represents the ordered test or panel, its status and conclusion. Each analyte is a separate Observation referenced from DiagnosticReport.result, holding the value, units, reference range and interpretation. Result Observations can also be searched on their own, without the report.

In the SMART Health IT R4 sandbox, a Basic Metabolic Panel report (51990-0) references result Observations coded 2339-0 (glucose), 6299-2 (urea nitrogen), 38483-4 (creatinine), 2947-0 (sodium) and 6298-4 (potassium). That synthetic data omits reference ranges, so here is the glucose example from the R4 spec, trimmed:

{
  "resourceType": "Observation",
  "status": "final",
  "code": { "coding": [{ "system": "http://loinc.org", "code": "15074-8", "display": "Glucose [Moles/volume] in Blood" }] },
  "subject": { "reference": "Patient/example" },
  "effectivePeriod": { "start": "2013-04-02T09:30:10+01:00" },
  "issued": "2013-04-03T15:30:10+01:00",
  "valueQuantity": { "value": 6.3, "unit": "mmol/l", "system": "http://unitsofmeasure.org", "code": "mmol/L" },
  "interpretation": [{ "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation", "code": "H", "display": "High" }] }],
  "referenceRange": [{
    "low": { "value": 3.1, "unit": "mmol/l", "system": "http://unitsofmeasure.org", "code": "mmol/L" },
    "high": { "value": 6.2, "unit": "mmol/l", "system": "http://unitsofmeasure.org", "code": "mmol/L" }
  }]
}

The US Core Laboratory Result Observation Profile requires the laboratory category and a LOINC code when available, and marks as Must Support the value, UCUM units, SNOMED CT for coded values, interpretation, reference range and specimen type. Interpretation codes come from the interpretation value set: H, L, N, A, HH (critical high), LL (critical low), POS and NEG. Three rules keep lab data honest:

  • Keep the lab's flag. Do not recompute H or L from a generic range; ranges vary by lab, method, age and sex.
  • Respect range semantics. Multiple referenceRange entries mean OR, multiple appliesTo codes mean AND, and a range can be text only, such as "Negative".
  • Handle status transitions. Upsert on resource id so a corrected potassium replaces the preliminary one.

If results start as HL7 v2 ORU messages, our LIS integration guide for ORU to DiagnosticReport mapping covers the OBX conversion.

Screening assessments and panels: hasMember vs component

Use component when values only make sense together and share every other attribute, like systolic and diastolic pressure. Use hasMember when each part is a standalone Observation, like the questions and total score of a screening instrument or the members of a vital signs panel.

The US Core Screening Assessment Profile models instruments as a survey-category panel with an overarching code, an empty value and hasMember references to one Observation per question. This is the AUDIT-C panel example published with US Core 9.0.0, trimmed:

{
  "resourceType": "Observation",
  "status": "final",
  "category": [{ "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "survey" }] }],
  "code": { "coding": [{ "system": "http://loinc.org", "code": "72109-2", "display": "Alcohol Use Disorder Identification Test - Consumption [AUDIT-C]" }] },
  "subject": { "reference": "Patient/example" },
  "effectiveDateTime": "2023-08-14T20:40:49.675000+00:00",
  "hasMember": [
    { "reference": "Observation/AUDIT-C-item-example-68517-2" },
    { "reference": "Observation/AUDIT-C-item-example-68519-8" },
    { "reference": "Observation/AUDIT-C-item-example-68520-6" },
    { "reference": "Observation/AUDIT-C-item-example-75626-2" }
  ],
  "derivedFrom": [{ "reference": "QuestionnaireResponse/AUDIT-C" }]
}

The last member, 75626-2 (total score), carries valueQuantity with UCUM code "1". A search for patient=X&category=survey returns the panel and every item as separate entries, so ingestion must assemble panels by following hasMember or users see four unrelated scores instead of one AUDIT-C result.

How EHRs populate Observation differently

Two conformant servers can return the same potassium or blood pressure in different shapes. Differences cluster around value types, reference range formats, component versus separate resources, local codes and flowsheet-backed storage. Where a vendor documents a behavior we cite it; treat the rest as patterns to test on every target.

PatternWhat you receiveHow to handle it
Value typevalueString for qualified or free-text results, valueQuantity elsewhereBranch on type, keep the original string
Reference rangesStructured low and high, or text onlyStore and show text; never invent bounds
Blood pressureComponents, or values stored separately upstreamNormalize to 85354-9; Oracle Health pairs components only when paired in Millennium
CodesLOINC plus local codes, or local onlyMap through a terminology service
Flowsheet dataVitals filed as flowsheet rows mapped to LOINCConfirm row mappings with each site
API surfaceObservation split into category-specific APIsRequest every relevant API and scope

Epic. The open.epic FHIR interface list publishes Observation as separate Read and Search APIs by data type, including Labs, Vital Signs, Social History, Core Characteristics, Assessments, SDOH Assessments, Lines Drains and Airways, SmartData Elements and Genomics. Each specification sets its own search rules:

  • Vital Signs search: patient or subject, plus category=vital-signs or a code. A code sent without a system is treated as LOINC, and Epic flowsheet IDs also work. Beyond the 17 LOINC codes Epic supports by default, it returns other non-duplicable flowsheet data.
  • Labs search: patient or subject, plus category or code but not both. Category accepts laboratory, SNOMED CT lab section codes the site has mapped, or site-specific order types. Values arrive as valueQuantity, valueString (also used for narrative and impression text), valueRange or valueRatio, and referenceRange.text carries the display range. For whole panels such as a CBC, Epic points to DiagnosticReport.Search.
  • Assessments search (August 2024 and later): category=survey for all assessments, or functional-status, disability-status, cognitive-status, sdoh, activity or social-history. Panels such as PHQ-9 reference their items through hasMember. From August 2024 the Vital Signs API stopped returning these assessments, which Epic marks as a breaking change.

Epic's search parameter guide splits parameters into native and post-filter types. Post-filters (R4 only, from May 2024) such as combo-code or value-string run after the native search, so their cost grows with how many resources the native parameters match. Epic's error reference on fhir.epic.com lists error 59111 for an R4 Observation search where "the required category parameter is not a valid category option".

Oracle Health. The Millennium Observation search docs state that when category is included, as a parameter or granular scope, the code parameter is ignored. _count defaults to 50 with a maximum of 200, results sort by effective date descending, and a vital-signs search by code with a proprietary system returns an empty response. So category=laboratory&code=2339-0 will not narrow to glucose there.

More vendor behavior in why FHIR compliant does not mean interoperable.

Ingesting vitals and labs from more than one EHR? We build and run Observation pipelines across Epic, Oracle Health, athenahealth, eClinicalWorks and NextGen for product teams. Talk to our team and we will map what each of your target EHRs actually returns for the codes you care about.

Writing Observations: RPM and device data

Reading Observations is broadly supported; writing them is not. Where EHRs accept create, it is limited to specific categories and codes and often depends on site configuration. For remote patient monitoring products, this decides whether readings reach the chart.

US Core's informative Writing Vital Signs page, which carries no certification requirement yet, sets the intended contract. Servers advertise create in the CapabilityStatement and use category-scoped SMART scopes such as patient/Observation.c?category=...|vital-signs. Single create SHALL be supported, batch MAY be. Apps writing patient-supplied data tag it patient-supplied, and device references the measuring device. Servers MAY discard near-duplicate readings but SHALL document it. An illustrative request following that guidance (not captured from a server):

POST [base]/Observation
Content-Type: application/fhir+json

{
  "resourceType": "Observation",
  "meta": { "tag": [{ "system": "http://hl7.org/fhir/us/core/CodeSystem/us-core-tags", "code": "patient-supplied" }] },
  "status": "final",
  "category": [{ "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "vital-signs" }] }],
  "code": { "coding": [{ "system": "http://loinc.org", "code": "29463-7", "display": "Body weight" }] },
  "subject": { "reference": "Patient/example" },
  "performer": [{ "reference": "Patient/example" }],
  "device": { "reference": "Device/example-scale" },
  "effectiveDateTime": "2026-07-30T07:12:00-05:00",
  "valueQuantity": { "value": 81.4, "unit": "kg", "system": "http://unitsofmeasure.org", "code": "kg" }
}

Epic lists Observation.Create (Vital Signs) (R4) and Observation.Create (Lines, Drains, Airways) (R4). The Vital Signs create specification files one reading per request to a flowsheet row, with specific rules:

  • category must be vital-signs. subject, effectiveDateTime and one value[x] are required, and status accepts only final.
  • code is a LOINC code or an Epic flowsheet ID: an encoded ID that the site's IT team generates, or the internal ID, which works only for rows treated as vital signs.
  • Blood pressure goes in component with 8480-6 and 8462-4.
  • Clinician and backend apps must reference an existing Encounter by FHIR ID, and cannot write to closed encounters or future appointments. Patient-facing apps write to patient-entered flowsheets, which need an order placed in Epic first, and Epic's remote patient monitoring guide adds that those patients need active MyChart accounts.
  • A request fails if a reading already exists at the same timestamp or if it includes an id.

To file several readings at once, or overwrite a value at the same timestamp, Epic points to its HL7v2 flowsheet data interfaces. Its error reference shows how create fails: 59187 when a patient-facing app writes for a patient with no Patient-Entered Flowsheets assigned, 59188 when "no single flowsheet row can be found by the codes provided", and 59189 when the reading fails to file.

Oracle Health's Observation create docs support VitalSigns, Laboratory and Imaging, one category per request. Vital signs accept only valueQuantity and require a performer, components are limited to blood pressure and pulse oximetry, and a create takes one interpretation and one reference range.

When the target does not accept writes, keep readings in your platform and send clinicians summaries or HL7 v2 results. Our RPM data pipeline from wearable to FHIR Observation covers that architecture.

FHIR Observation search patterns that perform

Always scope Observation searches to a patient and narrow by category, code or date. US Core requires servers to support patient plus category, patient plus code, and patient plus category plus date with gt, lt, ge and le. Unscoped or code-only queries are slow at best and rejected at worst.

# US Core SHALL: vital signs for a patient
GET [base]/Observation?patient=123&category=http://terminology.hl7.org/CodeSystem/observation-category|vital-signs

# US Core SHALL: specific codes (OR list SHOULD be supported)
GET [base]/Observation?patient=123&code=http://loinc.org|8867-4,http://loinc.org|85354-9

# US Core SHALL: category plus a date window
GET [base]/Observation?patient=123&category=laboratory&date=ge2026-06-01&date=lt2026-07-01

# Base R4, where supported: latest reading
GET [base]/Observation?patient=123&code=http://loinc.org|29463-7&_sort=-date&_count=1

The SHOULD set on the US Core lab and vital signs profiles adds patient plus category plus status, patient plus category plus _lastUpdated, and patient plus code plus date. Beyond that it is server-specific: value-quantity, combo-code and _sort are valid R4 but not universal, and while R4 defines $lastn, open.epic lists it only for STU3 APIs. Check the server first with our guide to reading a FHIR CapabilityStatement.

Use system|code tokens so a local code matching a LOINC string is not returned, and follow the Bundle next link instead of building page URLs, as the FHIR Bundle resource guide explains. More mistakes in 10 FHIR search patterns developers get wrong.

Where teams get stuck with FHIR Observation data

Observation failures rarely show up in a sandbox. They appear once real sites send real data, when they cost the most to fix. These consume the most engineering time on integrations we build:

  • Assuming every value is a Quantity. A lab arrives as valueString and is dropped without an error. Finding silently missing results after launch means auditing every code path.
  • Searching component codes. A dashboard queries systolic 8480-6 and shows nothing. Teams chase permissions for days before finding the code versus component.code rule.
  • Ignoring status transitions. Corrected results never replace originals and entered-in-error readings stay visible. That is a safety issue, not a cosmetic one.
  • Charting on the wrong timestamp. Using issued or lastUpdated instead of effective[x] shifts trend lines, especially for backfilled RPM data.
  • Trusting that LOINC is present. Rows with only local codes vanish from analytics and nobody notices.
  • Duplicate device readings. Device cloud retries create duplicates, or the EHR discards them under its own rules. Idempotency keys and a dedupe window are needed before go-live.
  • Assuming write works because read works. Create needs its own scopes, code mappings and often site flowsheet build, which means another round of coordination with every customer's analysts.

Many Observations carry no encounter, which breaks visit-based joins; the FHIR Encounter resource guide covers when that link is reliable. For profile expectations, read our US Core implementation guide.

FHIR Observation implementation checklist

Run through this before calling an Observation integration production-ready. Every item is cheaper to test in week one of EHR integration work than to fix after launch.

  1. Parse every value[x] type the target can send; log unknown types instead of dropping them.
  2. Select codings by system plus code and store all codings, including local ones.
  3. Normalize units on the UCUM code and keep the original value.
  4. Model blood pressure as 85354-9 with components; search the panel code or combo-code.
  5. Handle every status, upserting by resource id.
  6. Use effective[x] for clinical time and issued or _lastUpdated for sync.
  7. Store reference range text and interpretation flags exactly as sent.
  8. Assemble panels by following hasMember and derivedFrom.
  9. Build queries from US Core mandatory combinations, then apply each vendor's search rules.
  10. Validate against obs-3, obs-6, obs-7 and the relevant US Core profile.
  11. For writes, confirm create in the CapabilityStatement, request category scopes, tag patient-supplied data and document your dedupe window.

Need Observation data from Epic, Oracle Health or athenahealth flowing into your product without per-site surprises? Our Healthcare Interoperability Solutions team builds and runs these pipelines, and our open-source FHIR server passes the ONC (g)(10) Inferno SMART App Launch suite, 47 of 47. Building the RPM or monitoring product itself? Our Custom Healthcare Software Development team builds that side too. Talk to our team to scope your integration.

Ready to scale?

Talk to our healthcare engineering team about building, integrating, and shipping faster.

Frequently Asked Questions

What is a FHIR Observation resource?

A FHIR Observation is the resource used to record a single measurement or simple assertion about a patient, such as a vital sign, lab result, screening score or smoking status. In R4 only status and code are required. Most Observations also carry a LOINC code, a value, an effective time and a Patient reference, and US Core profiles make several of those mandatory for US EHR APIs.

What LOINC code is used for blood pressure in FHIR?

Blood pressure uses LOINC 85354-9 (Blood pressure panel) on Observation.code, with no top-level value. The readings go in two components: 8480-6 for systolic and 8462-4 for diastolic, each a valueQuantity with the UCUM unit mm[Hg]. Searching by 8480-6 will not return the panel, because the code search parameter only matches Observation.code. Use 85354-9 or combo-code instead.

What is the difference between Observation and DiagnosticReport in FHIR?

DiagnosticReport represents the whole report for an ordered test or panel, including its status, category and conclusion. Observation represents each individual result inside it, such as glucose or potassium, with its own value, units, reference range and interpretation. The report points to its results through DiagnosticReport.result, and each result Observation can also be retrieved on its own with an Observation search.

What are the FHIR Observation category codes?

FHIR R4 defines nine Observation category codes: vital-signs, laboratory, social-history, imaging, procedure, survey, exam, therapy and activity, in the code system http://terminology.hl7.org/CodeSystem/observation-category. The binding is Preferred, so servers can add their own codes. US Core profiles require a category, and EHR APIs often require or restrict category values in searches.

When should I use component vs hasMember in a FHIR Observation?

Use component when several values are measured together and cannot be interpreted alone, such as systolic and diastolic blood pressure. Use hasMember when each part is a complete Observation in its own right, such as the questions and total score of an AUDIT-C or PHQ-9 screening, or the members of a vital signs panel. Panels that use hasMember normally have no value of their own.

Can you write Observations to Epic or Oracle Health with FHIR?

Yes, within limits. Epic lists Observation.Create (Vital Signs) and Observation.Create (Lines, Drains, Airways) for R4. Its vitals create files one final reading per request to a flowsheet row matched by LOINC code or Epic flowsheet ID, needs an existing, open encounter for clinician and backend apps, and rejects a second reading at the same timestamp. Oracle Health documents Observation create for vital signs, laboratory and imaging, one category per request. Expect site-level setup before writes work in production.

How do I search FHIR Observations by patient and date?

Use GET [base]/Observation?patient=[id]&category=vital-signs&date=ge2026-01-01, and add a second date parameter such as date=lt2026-02-01 to close the window. US Core requires servers to support patient plus category plus date with the gt, lt, ge and le prefixes. The date parameter searches Observation.effective, so it reflects when the measurement was taken, not when it was recorded.
Share