Written and maintained by CASRAI Editorial Board
Last updated
HL7 FHIR search parameters define the standardized query syntax used to filter, traverse, and retrieve clinical resources across a FHIR RESTful API. Because clinical data in FHIR are normalized into discrete, interconnected resources (such as Patient, FHIR Observation, Condition, and MedicationRequest) rather than monolithic documents, mastering FHIR search parameter data types, comparison prefixes, modifiers, reference inclusions (_include / _revinclude), and chained searches is essential for building EHR integrations and clinical research cohorts.
How Do HL7 FHIR Search Parameter Types Work?
Every search parameter in FHIR is formally defined by a canonical SearchParameter resource (using a FHIRPath expression to bind the parameter name to one or more target JSON elements) and is assigned one of nine normative data types that govern how values, prefixes, and modifiers are parsed:
| Search Parameter Type | Target FHIR Data Types | Query Syntax & Clinical Example |
|---|---|---|
token |
Coding, CodeableConcept, Identifier, code, boolean |
Matches `[system]|[code]`, `|[code]` (no system), `[code]` (any system), or `[system]|`.GET [base]/Observation?code=http://loinc.org|4548-4 |
date |
date, dateTime, instant, Period, Timing |
Matches ISO-8601 partial or full dates (`YYYY`, `YYYY-MM`, `YYYY-MM-DD`, `YYYY-MM-DDThh:mm:ssZ`) with range prefixes.GET [base]/Observation?date=ge2026-01-01&date=le2026-06-30 |
string |
string, HumanName, Address |
Case-insensitive, accent-insensitive ”starts-with” prefix match by default.GET [base]/Patient?family=Smith |
reference |
Reference, canonical |
Matches `[type]/[id]`, logical `[id]`, or absolute URL.GET [base]/Observation?patient=Patient/12345 |
quantity |
Quantity, SampledData |
Matches `[prefix][number]|[system]|[code]` (typically UCUM units).GET [base]/Observation?value-quantity=gt6.5|http://unitsofmeasure.org|% |
number |
integer, decimal |
Numeric value with optional comparison prefix and significant-figure precision.GET [base]/RiskAssessment?probability=gt0.8 |
uri |
uri, url, canonical, oid |
Exact character-by-character URI match unless `:below` or `:above` modifier is used.GET [base]/ValueSet?url=http://hl7.org/fhir/ValueSet/observation-codes |
composite |
Paired sub-elements within the same parent array | Joins two search values with `$` to ensure both match inside the same array element (e.g., matching blood pressure code AND value inside the same `Observation.component[]`).GET [base]/Observation?code-value-quantity=http://loinc.org|8480-6$ge140|http://unitsofmeasure.org|mm[Hg] |
special |
Custom server-defined structures | Used for specialized parameters such as `_near` geospatial coordinates or `_filter` expressions. |
Boolean AND vs. OR Logic and POST _search
- OR Logic (Comma-Separated Values): Separating values with a comma within a single parameter applies logical OR—for example, querying both Systolic and Diastolic LOINC codes:
?code=http://loinc.org|8480-6,http://loinc.org|8462-4. - AND Logic (Repeated Parameters): Repeating the parameter key in the query string applies logical AND—for example, bounding a date range between two timestamps:
?date=ge2026-01-01&date=le2026-03-31. - Protecting PHI via
POST [base]/[type]/_search: Because URL query strings containing patient names, Social Security Numbers, or MRNs are frequently logged in plaintext by reverse proxies and web application firewalls, the FHIR specification requires servers to support `POST [base]/[type]/_search` with `Content-Type: application/x-www-form-urlencoded`, placing search parameters inside the encrypted HTTP request body.
How Do Search Prefixes and Modifiers Filter Clinical Resources?
FHIR distinguishes between prefixes (prepended directly to the parameter value for `number`, `date`, and `quantity` types) and modifiers (appended with a colon `:` to the parameter name):
The 9 Normative Comparison Prefixes (Ordered Types)
eq(Equal — default when omitted),ne(Not equal),gt(Greater than),lt(Less than),ge(Greater than or equal to), andle(Less than or equal to).- Period Boundary Prefixes:
sa(Starts after the specified date/period),eb(Ends before the specified date/period), andap(Approximately — typically $pm 10%$ of the target value or interval).
Key FHIR Search Modifiers
- String Modifiers (
:exactand:contains): While default string search is a case-insensitive prefix match,?family:exact=McDonaldenforces strict case-sensitive full-string equality, and?name:contains=annmatches the substring anywhere within the field. - Null Check Modifier (
:missing): Takes `true` or `false` to find resources where an element is absent or present—e.g.,GET [base]/Condition?abatement-date:missing=trueretrieves conditions without a recorded resolution date. - Terminology & Ontology Modifiers (
:text,:not,:in,:not-in,:below,:above): Used on `token` and `uri` parameters. In ontologies like SNOMED CT,?code:below=http://snomed.info/sct|73211009utilizes hierarchical subsumption to match Diabetes mellitus (`73211009`) and all of its descendant child concepts, while?code:in=[ValueSet-canonical-URL]filters for any code belonging to a specified HL7 `ValueSet`.
What Is the Difference Between _include, _revinclude, and Chained Search in FHIR REST Queries?
When querying relational graphs across multiple FHIR resource types, developers choose between including related resources in the response Bundle (`_include` / `_revinclude`) and filtering the primary resource based on attributes of a linked resource (chaining / `_has`):
| Graph Query Mechanism | Traversal Direction | Effect on Returned Searchset Bundle | Runnable HTTP Example |
|---|---|---|---|
_include |
Forward inclusion (from primary resource outward along its own `Reference` fields) | Returns primary matching resources (search.mode = "match") plus the referenced target resources (search.mode = "include") in the same FHIR Bundle. |
Fetch `MedicationRequest`s and include the referenced `Medication` and ordering `Practitioner`:GET [base]/MedicationRequest?patient=123&_include=MedicationRequest:medication&_include=MedicationRequest:requester |
_revinclude |
Reverse inclusion (inbound from other resources that point to the primary resource) | Returns primary matching resources (mode = "match") plus external resources that reference them (mode = "include"). Supports `:iterate` for multi-hop inclusion. |
Fetch an `Encounter` and reverse-include all `Observation`s and `Provenance` records pointing to it:GET [base]/Encounter?_id=E99&_revinclude=Observation:encounter&_revinclude:iterate=Provenance:target |
| Forward Chained Search | Forward filtering across a reference path (`param:TargetType.childParam=val`) | Returns only the primary resource (`mode = “match”`), filtered by criteria on the referenced resource. | Find `DiagnosticReport`s where the referenced `Patient` has family name ”Garcia” and birth date `1985-04-12`:GET [base]/DiagnosticReport?subject:Patient.family=Garcia&subject:Patient.birthdate=1985-04-12 |
Reverse Chained Search (_has) |
Reverse filtering (`_has:SourceType:refParam:filterParam=val`) | Returns only the primary resource (`mode = “match”`), filtered by the existence of another resource pointing to it. | Find all `Patient`s who have an `Observation` with HbA1c (`4548-4`) creates > 9.0%:GET [base]/Patient?_has:Observation:patient:code=http://loinc.org|4548-4 |
Under US Core FHIR and ONC `(g)(10)` certification, servers are not required to support arbitrary chaining across all resources, but SHALL support specific mandatory single and composite search parameter combinations (such as `Patient` + `category` + `date` on `Observation`, and `_revinclude=Provenance:target`) as declared in the server’s FHIR CapabilityStatement.
Frequently Asked Questions
How do HL7 FHIR search parameter types (number, date, string, token, reference, composite, quantity, uri) work?
Each FHIR search parameter has a defined data type that dictates its matching syntax: token matches `system|code` pairs for terminologies and identifiers; date matches ISO-8601 dates/periods with range prefixes; string performs case-insensitive prefix matching (or `:exact` / `:contains`); reference matches `ResourceType/id` links; quantity matches numeric values with UCUM units (`number|system|code`); number matches integers/decimals; uri matches exact URLs/OIDs; and composite pairs two criteria with `$` inside the same repeating component element.
What is the difference between _include, _revinclude, and chained search in FHIR REST queries?
_include and _revinclude expand what is returned in the response Bundle by appending referenced resources (forward via _include) or referencing resources (backward via _revinclude) with search.mode = "include" alongside the primary matches. In contrast, chained search (`subject:Patient.family=Smith`) and reverse chaining (`_has`) filter which primary resources match without automatically returning the linked secondary resources in the Bundle.
How do search prefixes (eq, ne, gt, lt, ge, le) and modifiers (:exact, :contains, :missing, :below) filter clinical resources?
Prefixes (`eq`, `ne`, `gt`, `lt`, `ge`, `le`, `sa`, `eb`, `ap`) are placed immediately before the parameter value on ordered types (`date`, `number`, `quantity`) to express range comparisons (e.g., `date=ge2026-01-01`). Modifiers (`:exact`, `:contains`, `:missing`, `:not`, `:text`, `:in`, `:below`) are appended to the parameter name with a colon to alter matching behavior, such as checking for null fields (`:missing=true`) or performing hierarchical SNOMED CT ontology subsumption (`:below`).







