Lesson 38 of 51 · The RESTful API
Search — Parameters, Chaining, and Includes
Reading a resource by its id is only useful once you already know the id. Most real work starts with a question — which patients were born before 1980? what observations carry this LOINC code? — and FHIR answers those questions through search. Search is a read operation layered on the REST API: you describe the resources you want with query parameters, and the server returns the matches packaged as a searchset Bundle 1. This lesson covers how those parameters are typed, how to constrain and combine them, and how to pull related resources into a single response.
The basic form
A search is an HTTP GET against a resource type’s endpoint, with parameters in the query string:
GET [base]/[type]?parameter=value
You combine multiple parameters with &, and the server treats them as a logical AND — every parameter must be satisfied for a resource to match 1. The result is always a Bundle whose type is searchset; each matching resource appears in the Bundle’s entry array, alongside paging links and a total count 1. Because the response is a standard Bundle, the same envelope you learned for packaging resources is reused to deliver search results 1.
Search parameter types
A search parameter is not just a field name — it has a type that tells the server how to interpret your value 1. The same string in the query string means different things depending on the parameter’s type. The defined types are:
- token — matches coded values, identifiers, and other exact-match codes. A token can carry a system and a code separated by a pipe:
system|code. - string — matches human text such as names and addresses; by default a string match is case- and accent-insensitive and matches at the start of the field.
- date — matches dates and date-times, with partial dates allowed.
- number — matches simple numeric values.
- quantity — matches a measured amount, optionally with a unit and system.
- reference — matches a link to another resource.
- uri — matches a URI value exactly.
A few examples make the distinction concrete:
GET [base]/Patient?family=Doe
GET [base]/Observation?code=http://loinc.org|2345-7
GET [base]/Patient?birthdate=ge1980-01-01
The first is a string parameter, the second a token (system plus code), and the third a date using a prefix, described next 1.
Prefixes
For ordered types — primarily date, number, and quantity — a value may be preceded by a prefix that turns an equality test into a comparison 1. The common prefixes are:
eq— equal (the default when no prefix is given)ne— not equalgt— greater thanlt— less thange— greater than or equalle— less than or equal
So birthdate=ge1980-01-01 matches patients born on or after the start of 1980, and a range is expressed by repeating the parameter with two prefixes:
GET [base]/Observation?date=ge2024-01-01&date=le2024-12-31
Modifiers
Where a prefix sits on the value, a modifier sits on the parameter name, after a colon, and changes how the match is performed 1. Useful ones include:
:exact— on a string, require an exact, case-sensitive, full-value match rather than the default starts-with behavior.:missing— test for presence:=truematches resources where the element is absent,=falsewhere it is present.:not— on a token, exclude resources whose value matches.
GET [base]/Patient?family:exact=Doe
GET [base]/Patient?gender:missing=true
GET [base]/Observation?status:not=cancelled
Other modifiers exist (for example, modifiers that change how tokens or references are interpreted), and which ones apply depends on the parameter’s type 1.
Chaining
Sometimes the criterion you care about lives on a referenced resource rather than the one you are searching for. Chaining lets you search across a reference by naming the reference parameter, the target type, and a search parameter on that target, joined with dots 1:
GET [base]/Observation?subject:Patient.name=Doe
This returns observations whose subject reference points to a Patient whose name matches “Doe” — without you first having to find the patient and then search again.
Reverse chaining goes the other direction with the _has parameter: it selects resources that are referenced by some other resource meeting a condition 1. For example, return patients who have an Observation with a particular code:
GET [base]/Patient?_has:Observation:subject:code=http://loinc.org|2345-7
The _has syntax names the referencing type (Observation), the reference parameter that links back (subject), and finally the search parameter to apply on that referencing resource (code).
_include and _revinclude
By default a searchset contains only the resources that matched. Often a client also needs the resources those matches point to, or the resources that point at the matches, and fetching them one by one is wasteful. Two control parameters solve this 1:
_includepulls in resources referenced by the matches — following a reference outward.Observation?_include=Observation:patientadds the referenced Patient resources to the Bundle._revincludepulls in resources that reference the matches — following references inward.Patient?_revinclude=Observation:patientadds Observations that point back at the matched patients.
The included resources are added to the same searchset Bundle. They are distinguished from the primary matches by each entry’s search.mode element, which marks them as include rather than match 1, so a client can tell the answer from the supporting context.
Shaping the result
Two more parameters tune the response itself rather than the matching. _count asks the server for a maximum page size, and _sort orders the results by one or more named parameters, with a leading - requesting descending order 1:
GET [base]/Observation?subject:Patient.name=Doe&_include=Observation:patient&_sort=-date&_count=50
Read from left to right, that query finds observations belonging to patients named “Doe”, attaches each observation’s Patient, sorts newest first, and caps the page at fifty entries — a realistic search that combines typing, chaining, includes, and result shaping in one request 1.
References
- HL7 FHIR Release 4 (R4), v4.0.1. HL7 International. 2019. verified Cited at: search.html; bundle.html.