Validating a code
Check a code where it enters your system, rather than where it leaves. By the time a claim is rejected for an unrecognised code, the patient has gone home and the correction costs a person rather than a round-trip.
Everything below elaborates this sentence.
Two questions that look like one
"Is this code valid?" is two questions, and they have different endpoints because they have different answers.
| Call | What it does | What you keep |
|---|---|---|
Does this code exist in this system, and is it active? | A question about the vocabulary. NATIONAL_ID is a real identifier type. NATIONAL-ID, with a hyphen, is not. | $validate-code on the code system |
Is this code allowed in this field? | A question about the binding. A withdrawn identifier type still exists in the vocabulary. It is simply not offered any more, and existing in the vocabulary is not the same as being allowed in the field. | $validate-code on the value set |
The second is almost always the one you want on a form. A field is bound to a value set, and the question at the boundary is whether what arrived belongs in that set, not whether it exists somewhere in the wider vocabulary.
What the answer looks like
Both operations return a FHIR Parameters resource. Three parameters matter:
| Call | What it does | What you keep |
|---|---|---|
result | The verdict, as a boolean. This is the only field your branch should read. | result |
display | The label, when the code resolved. Useful to render back at the operator so they can see what they matched. | nothing |
message | Why it failed, when it did. Log it: 'invalid code' with no reason is a support ticket rather than a fix. | message |
Where each check belongs
The same screen, twice: one code that resolved, one that did not.
1A001AOOThe calls
Is this code a member of this value set? The binding check for a form field, and the one you want most of the time.
resultDoes this code exist in this system, and is it active? A question about the vocabulary rather than the field.
resultWhat does this code mean? Display, definition, designations and properties. This is how you render a stored code you never stored a label for.
displayTranslating rather than coding twice
Some payers are still on ICD-10 while diagnoses are coded in ICD-11. The answer is not to store both.
The equivalent code in another vocabulary, one match per target.
the target codeCode once in the primary vocabulary, and let the map resolve the rest. A system that stores the older representation as its primary one has committed to a migration it has not scheduled.
There is more to this than the one call. Which map to use, what an equivalence promises, and why
a result: false means two different things are covered in
translating between vocabularies.
Building the check in
- 01Validate at the boundary, not at submissionEvery place a code can enter: a typed field, an import, an interface from a third-party system. The import is the one that is usually missed, and it is the one that arrives at volume.
- 02Read the result parameter, never the status codeWrite this once, in one helper, so no call site can get it wrong. A helper that returns a boolean from the body is the whole fix.
- 03Pin the check to the same version as the pickerValidating against serving while your dropdown was populated from a cached older release will reject codes you offered. One version string, read in both places.
- 04Log the message on failureThe reason is in the body. Discarding it turns every invalid code into the same unhelpful line in your log.
- 05Do not validate in a loop over a large importFetch the value set expansion once and check membership locally, then validate individually only what failed. One call per row of a ten thousand row import is a self-inflicted outage.
What breaks here
| Where it surfaces | What the desk sees | What actually went wrong |
|---|---|---|
| Submission, in production only | "Invalid codes are getting through and we validate everything" | The check branches on the HTTP status, which is 200 for an invalid code. Read the result parameter. |
| A form the user filled correctly | "It rejects a code we offered in our own dropdown" | The picker and the validator are reading different versions. Pin both to the same one. |
| A bulk import | "The import takes hours, or times out" | One validation call per row. Expand the value set once and check membership in memory. |
| Rendering an old record | "The label we show does not match the payer's statement" | A display string stored at capture time and never revisited. Store the code, resolve the label. |
| A third-party interface | "Codes from the lab system are rejected downstream" | Validation was built on the typed-entry path only. Every entry point needs the same boundary check. |
Next: Translating between vocabularies · Pinning to a release · Error dictionary

