Short answer: a terminology server is a FHIR server specialised in codes. It stores CodeSystems (SNOMED CT, LOINC, ICD-10, UCUM, HL7's own tables), ValueSets (named subsets for a purpose: vital signs codes, allergy substances) and ConceptMaps (translations between systems), and answers through standard operations: $lookup (what does this code mean?), $validate-code (is this code allowed here?), $expand (list the codes in this value set, optionally filtered by text), $translate (what is this code in that other system?) and $subsumes (is A a kind of B?). Applications call it instead of shipping copies of terminologies, which are large, licensed and updated several times a year.
The resources
A FHIR terminology server works with three resources. CodeSystem declares a code system by canonical URL and version, with its concepts or a note that content is held elsewhere; ValueSet defines a purposeful subset of codes through compose rules and an optional computed expansion; ConceptMap records source-to-target relationships between systems with an equivalence for each mapping.
- CodeSystem declares a system by its canonical URL (
http://snomed.info/sct,http://loinc.org,http://hl7.org/fhir/sid/icd-10), its version, and either its concepts or a statement that content is held elsewhere (content: not-presentfor licensed systems). - ValueSet has a
compose(rules: include all codes from a system, specific codes, or a filter such as descendants of 404684003 Clinical finding) and, when computed, anexpansion(the actual list). Bindings in profiles point to value sets; see FHIR profiles and extensions. - ConceptMap holds source → target relationships with an equivalence (
equivalent,wider,narrower,inexact,unmatched) and optional dependencies, for maps such as SNOMED CT to ICD-10 or a laboratory's local codes to LOINC.
The operations, with requests
A FHIR terminology server answers five standard operations: $lookup returns the meaning of one code, $validate-code checks whether a code belongs to a system or value set, $expand lists the codes in a value set, optionally filtered by text, $translate converts a code to another system through a ConceptMap, and $subsumes tests whether one concept is a kind of another.
$lookup: details of one code.
GET /CodeSystem/$lookup?system=http://loinc.org&code=4548-4
Returns a Parameters resource with display ("Hemoglobin A1c/Hemoglobin.total in Blood"), designations in other languages, and properties (for LOINC the six axes; for SNOMED CT the parents and defining relationships).
$validate-code: is the code in the system, or in the value set?
GET /ValueSet/$validate-code?url=http://hl7.org/fhir/ValueSet/observation-vitalsignresult&system=http://loinc.org&code=8480-6
Returns result: true with the display, or false with a message. Servers that validate resources call this for every bound element.
$expand: the codes in a value set, with text filtering for search boxes.
GET /ValueSet/$expand?url=http://hl7.org/fhir/ValueSet/condition-code&filter=diabetes&count=20
Returns the ValueSet with an expansion.contains list: code, system, display. This is how an EHR's diagnosis search works against SNOMED CT without holding 360,000 concepts locally.
$translate: cross a system boundary.
GET /ConceptMap/$translate?url=https://lab.example.org/ConceptMap/local-to-loinc&system=https://lab.example.org/codes&code=GLU&targetsystem=http://loinc.org
Returns the matches with their equivalence. The same operation serves SNOMED CT → ICD-10 maps where the server hosts them.
$subsumes: hierarchy questions.
GET /CodeSystem/$subsumes?system=http://snomed.info/sct&codeA=73211009&codeB=44054006
Answers subsumes (diabetes mellitus is an ancestor of type 2 diabetes), subsumed-by, equivalent or not-subsumed. Decision support uses it to ask is this condition any kind of diabetes? without listing every subtype.
Responses are Parameters resources: a list of named parts, not a plain object, which surprises first-time callers.
Servers you will meet
The terminology servers most often met in practice are tx.fhir.org, HL7's public reference server used by its validator; Ontoserver from CSIRO, a commercial server behind several national programmes; Snowstorm from SNOMED International, open source and SNOMED CT native; general FHIR servers such as HAPI FHIR and Firely Server with terminology operations; and national servers run by health agencies.
| Server | Who | Notes |
|---|---|---|
| tx.fhir.org | HL7 (reference) | Public, used by the HL7 validator and IG Publisher; LOINC, SNOMED CT (where licensed), HL7 tables, UCUM. Not for production traffic |
| Ontoserver | CSIRO (Australia) | Commercial; used by national programmes (Australia, UK NHS Ontology Server, Netherlands, Belgium); full SNOMED CT with ECL queries |
| Snowstorm | SNOMED International | Open source; SNOMED CT native with a FHIR API; powers the official browser |
| HAPI FHIR, Firely Server, Microsoft/Google/AWS FHIR services | Vendors | General FHIR servers with terminology operations; load code systems yourself |
| National servers | Health ministries and agencies | Often Ontoserver or Snowstorm with the national edition and local value sets |
Content is the hard part: SNOMED CT requires a licence outside member countries, LOINC requires accepting its terms, ICD-10 national variants have their own distribution. A server gives you the operations; you still obtain and load the content legally.
How applications use one
Applications use a terminology server to validate codes and units at write time, to power search boxes through $expand with a text filter and a value set, to display official names through $lookup, to map local codes to LOINC or SNOMED CT to ICD-10 through $translate, and to reason over hierarchies through $subsumes and SNOMED CT's Expression Constraint Language.
- Validation at write time: reject an Observation whose LOINC code does not exist or whose unit is not UCUM, with a message that names the problem.
- Search boxes:
$expandwithfilterfor diagnosis, procedure and medication pickers, scoped by a value set so clinicians only see relevant concepts. - Display:
$lookupto show the official name and translations instead of storing display strings that go stale. - Mapping:
$translateto turn local laboratory codes into LOINC on import (how to map local lab codes to LOINC) or SNOMED CT into ICD-10 for reporting (SNOMED CT vs ICD-10). - Reasoning:
$subsumesand SNOMED's Expression Constraint Language (ECL, supported by Ontoserver and Snowstorm through$expandfilters) to define cohorts and rules by hierarchy.
Cache aggressively (terminology changes twice a year, not twice a day), pin versions in production, and treat a server outage as degraded validation rather than a reason to reject every write.
In Anpheros
Anpheros Platform validates the LOINC codes and UCUM units it accepts for observations and the ATC codes for medications against the terminology it ships (a LOINC subset and the WHO ATC index), and documents its terminology API on the developer site. For full SNOMED CT or ICD-10 browsing, it points to the official browsers rather than redistributing licensed content.
Related pages
- FHIR profiles and extensions explained
- How to map local lab codes to LOINC
- SNOMED CT vs ICD-10
- CodeableConcept and Coding in FHIR
- UCUM units in lab results
- Medical terminology API (developer site)
Sources
- HL7 FHIR R4: Terminology Service
- HL7 FHIR R4: ValueSet $expand
- HL7 FHIR R4: ConceptMap $translate
- HL7 FHIR R4: CodeSystem $lookup
- HL7 terminology server tx.fhir.org
- Snowstorm (SNOMED International, GitHub)
- Ontoserver (CSIRO)
Frequently asked questions
Do I need a terminology server to use FHIR?
Not for a small system with a fixed code list. As soon as you validate codes from large systems, offer clinical search or translate between systems, a terminology server saves you from shipping and updating the terminologies yourself.
Can I use tx.fhir.org in production?
No. It is HL7's reference server for validation tooling and testing, with no service guarantees and licence constraints on some content. Run your own or use a national or commercial one.
What is ECL?
SNOMED CT's Expression Constraint Language, a query syntax for sets of concepts (for example << 73211009 for diabetes and all its subtypes). Servers that support it accept ECL in ValueSet filters and $expand.
How do I know which version of SNOMED CT a server has?
Ask the CodeSystem (GET /CodeSystem?url=http://snomed.info/sct) and read its version, which encodes the edition and release date (for example http://snomed.info/sct/900000000000207008/version/20260301). Pin it in your requests when results must be reproducible.
Try it free in the sandbox
Your first FHIR call in 5 minutes. An HL7 FHIR R4 API with the patient's consent built in: try it in the sandbox, then connect your own app or clinic system.
Free · 30 synthetic patients · no card

The more you log, the clearer your record
Your health history in one place, under your control.
Free · Works in your browser · No card
