Service base
The Provider directory, Questionnaires and MedList are served from this same base, under the sameCapabilityStatement.
Operations
Each requires a valid API key (see Authentication). Each accepts GET with query parameters or POST with a FHIRParameters resource.
CodeSystem/$lookup— a code’s display and properties.CodeSystem/$validate-code— is this a real code in this code system?ValueSet/$expand— expand a value set to its member codes.ValueSet/$validate-code— is this code a member of this value set?metadata— theCapabilityStatement, or aTerminologyCapabilitieswith?mode=terminology.
Look up a code
property is repeatable and narrows what comes back. Leave it off and you get everything the
code system knows about the code.
Three ways to pass a code
The validate operations accept a code in three shapes. The first works everywhere; the other two are complex FHIR datatypes, which the operations framework only permits in a POST body — sent in a query string they return a400 explaining exactly that.
1. system + code — two separate parameters, GET or POST. The form used in every
example above.
2. coding — the two bundled as one object, POST only. In a real FHIR record a code
does not live as two loose fields; it lives as a Coding. This form lets you pass it
without taking it apart first:
CodeSystem/$validate-code the coding’s system stands in for url — the code
system is the thing being asked about.
3. codeableConcept — one concept, several labels, POST only. A CodeableConcept
is a single idea coded more than one way, and it validates as a member if any of its
codings is. This is the shape real clinical data actually has: exports routinely carry a
vendor-local coding alongside a standard one on the same element. The vendor label cannot
decide membership — no terminology server has ever heard of it — but the standard label
beside it can, and this form means you never have to guess which label to send:
message names each label’s own reason — an unrecognised
vendor system and a real code that simply is not in the set are different kinds of no.
And if the request could not actually be answered — the value set does not exist, a
shared parameter is invalid, a code system was unreachable — the whole request answers
with that error rather than a false. “We could not ask” is never reported as “no”, and
the concept form always agrees with what the plain system + code form would say.
Two details of how codings are read:
- Per-coding membership ignores each coding’s
display. A display mismatch fails validation even when the code is a member, and a vendor-worded label must not veto a right code. Display checking is available on the single-codingform, where the response tells you the code was valid and only the label differed. coding.versionis honoured on the CodeSystem operations and refused on ValueSet validation (which always uses the current code-system version) rather than being silently ignored.
Value sets and code systems are addressed by canonical URL only (the
url
parameter). Instance-level operation paths (/ValueSet/{id}/$validate-code) are not
offered: this service hosts published definitions whose canonical URLs are their
identity, so there are no server-assigned ids to address.Validating against a hosted value set
Some published value sets are defined as a rule rather than a list — “every code in this system with such-and-such property” — and resolve to tens of thousands of members. This service hosts a number of those definitions and answers membership for them directly, so you can ask about a code without expanding anything:GET /v1/fhir/r4/metadata?mode=terminology lists the value sets and code systems this service
answers for. A canonical it does not host and cannot resolve upstream is refused with an
OperationOutcome, never answered with a guess.
Expanding a value set
An expansion comes back whole.url is the only parameter accepted for a value set resolved
from its own source: filter, count and offset are refused there with a 400 naming
them, because that source answers a whole expansion or nothing. Expand the set and filter the
result. On value sets this service hosts, those three narrow the expansion normally.
displayLanguage, includeDesignations and activeOnly are refused on $expand everywhere,
also with a 400 naming them. An expansion is returned in its source’s own language and
order.
An empty expansion does not always mean the value set is empty. For a canonical inside a
source’s own namespace, a set that does not exist can come back as a successful expansion
with no members rather than as an error, so an empty result cannot be read as proof that the
set exists and is empty. Use
$validate-code when you need a decided answer about a
specific code, and treat total: 0 as “nothing to show” rather than as a fact about the set.Several operations in one request
POST a FHIRBundle with type: batch to the service base. Entries are independent: one
unknown code does not fail the others, and each carries its own status.
Responses and errors
Success returns standard FHIR: aParameters for $lookup and $validate-code, a ValueSet
for $expand.
Every error is a FHIR OperationOutcome, with issue.code telling you what kind of problem
it is.
Two things worth knowing:
- A code that is not in a value set is a successful
200with"result": false, not an error. result: falsecan also mean the display you sent does not match. If you passdisplay, it is checked against the code’s real display, and a mismatch returnsfalsewith the expected display alongside it. The code is fine; only the label differs. Vendor labels differ from published displays routinely, so do not read that as an invalid code.
diagnostics. Code systems
we hold ourselves have no upstream to pass through; their errors are written here.
Code systems
RxNorm
Most code systems here are resolved from their own source when you ask. RxNorm is different: we hold it, at a named release, and answer from our own copy. That changes two things you can see. Answers are fast and do not depend on anyone else being up. And every answer tells you which release it came from, so a result you got last month and a result you get today are comparable. Which release you are talking to is inTerminologyCapabilities:
codeSystem with a version, and the same value comes back on every
$lookup. If a deployment has no release published yet, RxNorm is listed as not served with
the reason, and requests answer 503 rather than pretending.
Looking up a concept
The
system and url parameters default to LOINC, so an RxNorm request has to name RxNorm
explicitly. Leave it off and you are asking a different question.designation entries, and a property for
each of:
- RxNorm’s own attributes, under RxNorm’s own names — term type, strength, quantity, dispensable-form flags, NDC codes and the rest. We do not rename them, so what you read here matches what you read in RxNorm’s documentation.
inactive, FHIR’s standard property, which isfalsefor everything we hold. The content set we hold contains active concepts only. RxNorm’s own suppressibility flag comes back separately under its own name, because one of its values means “unquantified but current”, and reporting such a concept as inactive would tell you it had been retired.- each relationship the concept has, keyed by RxNorm’s name for it and carrying the
related concept as a
Coding. So a brand drug’s relationship to its clinical drug comes back with the other concept’s code and display, not just a label you would have to look up again.
property= — repeatable, and a name we have no value for is
simply absent rather than an error.
What we hold, and what that means for a “no”
We hold RxNorm Current Prescribable Content, the subset NLM publishes for currently prescribable drugs. As NLM defines it, that is active normalized names, and it excludes obsolete or suppressed data, drugs that are exclusively non-US, and drugs for exclusive veterinary use. This is also why membership questions use our own value set for the content we hold rather than a canonical meaning all of RxNorm:result is a real answer either way.
Asking for a particular release
version is honoured when it names the release we are serving, in either the FHIR form (the
release date as it appears in the source’s file names) or the source’s own form. Any other
value is refused by name: we hold one release at a time, and quietly answering about a
different one would answer a question you did not ask.
Not offered
ValueSet/$expand of the content set. It runs to tens of thousands of concepts, and an
expansion we truncated would read as a complete list. Ask about a code with
ValueSet/$validate-code, or look it up.
Legal
This material contains content from LOINC (http://loinc.org). LOINC is copyright © Regenstrief Institute, Inc. and the Logical Observation Identifiers Names and Codes (LOINC) Committee and is available at no cost under the license at http://loinc.org/license. LOINC® is a registered United States trademark of Regenstrief Institute, Inc. Some individual codes carry a further copyright held by whoever created the underlying instrument, most often a survey or assessment. Where one does, it comes back with the code as anEXTERNAL_COPYRIGHT_NOTICE property, and you must keep it with the code wherever you use it.
This product uses publicly available data courtesy of the U.S. National Library of Medicine
(NLM), National Institutes of Health, Department of Health and Human Services; NLM is not
responsible for the product and does not endorse or recommend this or any other product.
Code systems we hold locally are served from a dated release, named in the version of every
answer and in TerminologyCapabilities. A held release may not reflect the most current data
available from its publisher.
FHIR® is the registered trademark of Health Level Seven International and its use here does not
constitute endorsement by HL7.
Full terms are at platform.haau3.com/terms.
For your first call, start with the Quickstart.