> ## Documentation Index
> Fetch the complete documentation index at: https://docs.haau3.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Terminology service

> A FHIR R4 terminology service: look up codes, expand value sets, and validate codes against published value sets.

The **haau3 Terminology API** is a hosted **FHIR R4 terminology service**. It serves standard
FHIR terminology operations over clinical code systems, so you can look up codes, expand value
sets, and validate codes without running a terminology server yourself.

## Service base

<Snippet file="fhir-base.mdx" />

The [Provider directory](/provider-directory/provider-directory) is served from this same base,
under the same `CapabilityStatement`.

## Operations

Each requires a valid API key (see [Authentication](/authentication)). Each accepts **GET**
with query parameters or **POST** with a FHIR `Parameters` 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` — the `CapabilityStatement`, or a `TerminologyCapabilities` with `?mode=terminology`.

See the [API Reference](/api-reference) for the full parameter list.

## Look up a code

<CodeGroup>
  ```bash GET theme={null}
  curl "https://api.haau3.com/v1/fhir/r4/CodeSystem/\$lookup?system=http://loinc.org&code=2345-7&property=SHORTNAME" \
    -H "Authorization: Bearer $HAAU3_API_KEY"
  ```

  ```bash POST theme={null}
  curl -X POST "https://api.haau3.com/v1/fhir/r4/CodeSystem/\$lookup" \
    -H "Authorization: Bearer $HAAU3_API_KEY" \
    -H "Content-Type: application/fhir+json" \
    -d '{
      "resourceType": "Parameters",
      "parameter": [
        { "name": "system", "valueUri": "http://loinc.org" },
        { "name": "code", "valueCode": "2345-7" },
        { "name": "property", "valueCode": "SHORTNAME" }
      ]
    }'
  ```
</CodeGroup>

`property` is repeatable and narrows what comes back. Leave it off and you get everything the
code system knows about the code.

<Tip>
  `displayLanguage` defaults to `en-US`, which keeps responses small. The upstream code system
  otherwise returns around thirty translations per code, which is roughly fourteen times the
  payload for content most callers discard.
</Tip>

## 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 a `400` 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:

```bash theme={null}
curl -X POST "https://api.haau3.com/v1/fhir/r4/ValueSet/\$validate-code" \
  -H "Authorization: Bearer $HAAU3_API_KEY" \
  -H "Content-Type: application/fhir+json" \
  -d '{
    "resourceType": "Parameters",
    "parameter": [
      { "name": "url", "valueUri": "http://hl7.org/fhir/ValueSet/observation-vitalsignresult" },
      { "name": "coding", "valueCoding": { "system": "http://loinc.org", "code": "8867-4" } }
    ]
  }'
```

On `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:

```bash theme={null}
curl -X POST "https://api.haau3.com/v1/fhir/r4/ValueSet/\$validate-code" \
  -H "Authorization: Bearer $HAAU3_API_KEY" \
  -H "Content-Type: application/fhir+json" \
  -d '{
    "resourceType": "Parameters",
    "parameter": [
      { "name": "url", "valueUri": "http://hl7.org/fhir/us/core/ValueSet/us-core-laboratory-test-codes" },
      { "name": "codeableConcept", "valueCodeableConcept": {
        "text": "GLUCOSE, SERUM",
        "coding": [
          { "system": "urn:oid:1.2.3.4.5.999", "code": "GLU-123" },
          { "system": "http://loinc.org", "code": "2345-7" }
        ]
      } }
    ]
  }'
```

```json theme={null}
{ "resourceType": "Parameters", "parameter": [
  { "name": "result", "valueBoolean": true },
  { "name": "message", "valueString": "Matched on coding http://loinc.org|2345-7." } ] }
```

When no coding matches, the `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-`coding` form, where the
  response tells you the code was valid and only the label differed.
* **`coding.version` is honoured on the CodeSystem operations and refused on ValueSet
  validation** (which always uses the current code-system version) rather than being
  silently ignored.

<Note>
  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.
</Note>

## 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:

```bash theme={null}
curl -G "https://api.haau3.com/v1/fhir/r4/ValueSet/\$validate-code" \
  -H "Authorization: Bearer $HAAU3_API_KEY" \
  --data-urlencode "url=<value-set-canonical>" \
  --data-urlencode "system=http://loinc.org" \
  --data-urlencode "code=<code>"
```

```json theme={null}
{ "resourceType": "Parameters", "parameter": [{ "name": "result", "valueBoolean": true }] }
```

`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.

<Warning>
  `$expand` is refused for rule-defined value sets whose expansion runs to many thousands of codes.
  A truncated expansion looks complete, which is worse than a clear refusal — `$validate-code`
  answers membership without materialising the set.
</Warning>

## Several operations in one request

POST a FHIR `Bundle` with `type: batch` to the service base. Entries are independent: one
unknown code does not fail the others, and each carries its own status.

```bash theme={null}
curl -X POST "https://api.haau3.com/v1/fhir/r4" \
  -H "Authorization: Bearer $HAAU3_API_KEY" \
  -H "Content-Type: application/fhir+json" \
  -d '{
    "resourceType": "Bundle",
    "type": "batch",
    "entry": [
      { "request": { "method": "GET", "url": "CodeSystem/$lookup?system=http://loinc.org&code=2345-7" } },
      { "request": { "method": "GET", "url": "CodeSystem/$lookup?system=http://loinc.org&code=8867-4" } }
    ]
  }'
```

This is worth using for anything more than a handful of codes. Measured against the upstream, a
batch of fifty lookups costs about 5 ms per code, against about 180 ms each when sent one at a
time. Transaction bundles are not accepted: these operations do not write anything, so
all-or-nothing would only turn one bad code into a wholly failed request.

## Responses and errors

Success returns standard FHIR: a `Parameters` 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.

| Status        | Meaning                                                                  |
| ------------- | ------------------------------------------------------------------------ |
| `400`         | Invalid parameters, or two different FHIR versions in one request.       |
| `401`         | Missing or invalid API key.                                              |
| `404`         | The code system is not served here, or the code was not found.           |
| `406`         | You asked for a FHIR release this endpoint does not serve.               |
| `422`         | The request is well formed but cannot be answered as asked.              |
| `502` / `504` | An upstream code system could not be reached, or did not answer in time. |
| `503`         | No source is configured for that code system on this deployment.         |

Two things worth knowing:

* **A code that is not in a value set is a successful `200`** with `"result": false`, not an
  error.
* **`result: false` can also mean the display you sent does not match.** If you pass `display`,
  it is checked against the code's real display, and a mismatch returns `false` *with 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.

We never pass an upstream error through unchanged. Upstream terminology servers are not
consistently valid FHIR and their messages name their own internals, so errors are translated
into outcomes of our own, with the upstream text kept as supporting `diagnostics`.

## Code systems

<Snippet file="code-systems.mdx" />

## Legal

This material contains content from LOINC ([http://loinc.org](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](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 an
`EXTERNAL_COPYRIGHT_NOTICE` property, and you must keep it with the code wherever you use it.

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](https://platform.haau3.com/terms).

For your first call, start with the [Quickstart](/quickstart).
