Vitalis Hackathon 2026
0.1.0 - ci-build
Vitalis Hackathon 2026 - Local Development build (v0.1.0) built by the FHIR (HL7® FHIR® Standard) Build Tools. See the Directory of published versions
Track lead: Vadim Peretokin
This track explores how applications can utilize the Nordic FHIR terminology server (tx-nordics) for authoring FHIR content, and how AI agents can serve as terminology co-pilots - helping find codes, create mappings, and validate bindings.
No prior experience with terminology servers or AI agents is required. The track is structured as a progression from guided exercises to open hacking, so you can join at whatever level suits you. Use of LLMs (ChatGPT, Claude, etc.) is welcomed and encouraged, but not necessary (for part 1).
The exercises below are self-paced - start wherever you're comfortable and work through them at your own speed. The track lead will be walking around to help.
These exercises introduce the core FHIR terminology operations. You'll work directly with the Nordic TX server using a REST client, browser, or curl.
$lookup - Given a SNOMED CT code, retrieve its display name and available designations. Does the server have translations for your language?
GET https://tx-nordics.fhir.org/fhir/r4/CodeSystem/$lookup?system=http://snomed.info/sct&version=http://snomed.info/sct/45991000052106/version/20251130&code=73211009&property=designation
This looks up "Diabetes mellitus" (73211009) using the Swedish SNOMED CT edition and returns sv: diabetes alongside the English designations. Try the Norwegian edition (module 51000202101, version 20251215) or the Danish edition (module 554471000005108, version 20250930) by replacing the module ID and version date in the version parameter.
$validate-code - Check whether a code is valid in a code system. Try with a valid code, then an invalid one - what does the server return?
GET https://tx-nordics.fhir.org/fhir/r4/CodeSystem/$validate-code?url=http://snomed.info/sct&version=http://snomed.info/sct/45991000052106/version/20251130&code=73211009
This returns "result": true. Now try with a made-up code:
GET https://tx-nordics.fhir.org/fhir/r4/CodeSystem/$validate-code?url=http://snomed.info/sct&version=http://snomed.info/sct/45991000052106/version/20251130&code=9999999999
This returns "result": false with a message explaining the code is unknown.
Try it yourself:
display parameter with the wrong display name for code 73211009? Does the server catch it? (hint: add &display=Hypertension to the valid code query)ValueSet/$validate-code endpoint with the diabetes descendants value set from exercise 3 below. Does 44054006 (Type 2 diabetes mellitus) belong? What about 38341003 (Hypertension)?http://npu-terminology.org - can you check if NPU03835 (HbA1c) is valid?$expand - Expand a value set, optionally filtering by text. How does the result change with different filters?
GET https://tx-nordics.fhir.org/fhir/r4/ValueSet/$expand?url=http://snomed.info/sct/45991000052106?fhir_vs=isa/73211009&count=5
This expands all descendants of "Diabetes mellitus" using the Swedish edition and returns the first 5. Now add a text filter:
GET https://tx-nordics.fhir.org/fhir/r4/ValueSet/$expand?url=http://snomed.info/sct/45991000052106?fhir_vs=isa/73211009&filter=type%202&count=5
This narrows it down to 16 matches containing "type 2".
Try it yourself:
&includeDesignations=true to the expand query. What extra information do you get back? Can you spot translations in your language?&displayLanguage=sv (or no, da) to the query. How does the output change?73211009 (Diabetes mellitus) with 38341003 (Hypertension) to find all types of hypertension. How many are there?&offset=5&count=5 - can you paginate through results?$translate - Use a ConceptMap to translate a code between systems. First, upload this sample ConceptMap that maps a few diabetes SNOMED codes to ICD-10:
{
"resourceType": "ConceptMap",
"id": "snomed-to-icd10-diabetes-sample",
"url": "https://hl7.se/fhir/ConceptMap/snomed-to-icd10-diabetes-sample",
"name": "SnomedToIcd10DiabetesSample",
"status": "draft",
"sourceUri": "http://snomed.info/sct",
"targetUri": "http://hl7.org/fhir/sid/icd-10",
"group": [
{
"source": "http://snomed.info/sct",
"target": "http://hl7.org/fhir/sid/icd-10",
"element": [
{
"code": "73211009",
"display": "Diabetes mellitus",
"target": [
{
"code": "E14",
"display": "Unspecified diabetes mellitus",
"equivalence": "wider"
}
]
},
{
"code": "44054006",
"display": "Type 2 diabetes mellitus",
"target": [
{
"code": "E11",
"display": "Type 2 diabetes mellitus",
"equivalence": "equivalent"
}
]
},
{
"code": "46635009",
"display": "Type 1 diabetes mellitus",
"target": [
{
"code": "E10",
"display": "Type 1 diabetes mellitus",
"equivalence": "equivalent"
}
]
}
]
}
]
}
Upload it with a PUT:
PUT https://tx-nordics.fhir.org/fhir/r4/ConceptMap/snomed-to-icd10-diabetes-sample
Then translate a code:
GET https://tx-nordics.fhir.org/fhir/r4/ConceptMap/$translate?system=http://snomed.info/sct&code=44054006&target=http://hl7.org/fhir/sid/icd-10
This should return E11 (Type 2 diabetes mellitus).
Build your own ConceptMap - Now create a ConceptMap from scratch. Map these SNOMED CT codes to ICD-10:
| SNOMED CT code | Display |
|---|---|
| 38341003 | Hypertensive disorder |
| 48146000 | Diastolic hypertension |
| 56218007 | Systolic hypertension |
Figure out the appropriate ICD-10 codes for each, use the sample ConceptMap from exercise 4 as a template, and upload it with a PUT. Test it with $translate - does the server return the ICD-10 code you expected?
These exercises show how to use a national SNOMED CT edition when building a FHIR Implementation Guide. You'll write FSH, build the IG, and verify that the Nordic TX server was used automatically through the FHIR terminology ecosystem.
Clone and build - Clone this hackathon IG and build it:
git clone https://github.com/vadi2/vitalis-hackathon-2026-ig.git
cd vitalis-hackathon-2026-ig
./_genonce.sh
The build should succeed. The IG publisher uses tx.fhir.org by default, which knows how to route requests to national terminology servers like the Nordic TX server.
Add a Swedish SNOMED code - Create a new FSH file (e.g. input/fsh/diabetes-condition.fsh) with an example Condition that uses a code from the Swedish SNOMED CT edition:
Instance: DiabetesExample
InstanceOf: Condition
Usage: #example
* subject = Reference(Patient/example)
* code = http://snomed.info/sct|http://snomed.info/sct/45991000052106#73211009 "Diabetes mellitus"
* clinicalStatus = http://terminology.hl7.org/CodeSystem/condition-clinical#active
Note the version in the code system URI - http://snomed.info/sct|http://snomed.info/sct/45991000052106 pins it to the Swedish edition.
Build and check TX logs - Rebuild the IG with ./_genonce.sh. After the build completes, open output/qa-tx.html in your browser. This shows every terminology request the IG publisher made. Can you find the request that validated your Swedish SNOMED code? Which server handled it - was it routed to the Nordic TX server?
Try it yourself:
#73211009 "Hypertension") and rebuild. What does the QA report say? Check both output/qa.html and output/qa-tx.html.http://snomed.info/sct/51000202101) or Danish (http://snomed.info/sct/554471000005108) edition. Does the build still validate successfully?Add an NPU-coded Observation - Create an Observation example that uses an NPU code for a lab result:
Instance: HbA1cExample
InstanceOf: Observation
Usage: #example
* status = #final
* code = http://npu-terminology.org#NPU03835 "Hb(Fe;B)—Haemoglobin A1c(Fe); subst.fr. = ?"
* subject = Reference(Patient/example)
* valueQuantity = 48 'mmol/mol'
Does the build validate the NPU code? Check qa-tx.html to see if it reached the Nordic TX server.
Create a ValueSet - Write a ValueSet in FSH that includes descendants of a SNOMED concept from a national edition, then bind it to a profile element. Does the IG publisher expand and validate it correctly?
ValueSet: DiabetesTypesSE
Id: diabetes-types-se
Title: "Diabetes Types (Swedish edition)"
* include codes from system http://snomed.info/sct|http://snomed.info/sct/45991000052106
where concept is-a #73211009 "Diabetes mellitus"
These exercises introduce AI agents that can query terminology servers. If you've never used an AI coding agent before, this is a gentle starting point.
$validate-code. Did the AI get it right, or did it hallucinate?
AI-assisted ConceptMap - Take the sample legacy codes below (or bring your own) and ask the AI agent to propose SNOMED CT mappings for each. Validate the proposals against the TX server with $validate-code. How many were correct?
| Legacy code | Description |
|---|---|
| LAB-001 | Fasting blood glucose |
| LAB-002 | HbA1c |
| LAB-003 | Total cholesterol |
| DX-101 | High blood pressure |
| DX-102 | Adult-onset diabetes |
| DX-103 | Chest pain on exertion |
| DX-104 | Iron deficiency |
| PROC-201 | Total knee replacement, left |
| PROC-202 | Removal of gallbladder |
| PROC-203 | Insertion of cardiac pacemaker |
$lookup. Where do they diverge? This is a practical lesson in why you should validate AI-generated terminology.Bring your own problem, or pick from these:
NPU codes - NPU (Nomenclature for Properties and Units) is available on the server (http://npu-terminology.org). Try looking up common lab codes like NPU03835 (HbA1c) or NPU22089 (Glucose):
GET https://tx-nordics.fhir.org/fhir/r4/CodeSystem/$lookup?system=http://npu-terminology.org&code=NPU03835
CSIRO Shrimp browser - Shrimp is a free SNOMED CT browser that works with any FHIR terminology server. Point it at the Nordic TX server by entering https://tx-nordics.fhir.org/fhir/r4 in the endpoint field (top right), or use this direct link:
https://ontoserver.csiro.au/shrimp/?fhir=https://tx-nordics.fhir.org/fhir/r4
terminology.lookup, terminology.expand, and terminology.translate. Point it at the Nordic TX server by setting TERMINOLOGY_BASE_URL=https://tx-nordics.fhir.org/fhir/r4 and use it from Claude Code or Cursor to look up codes conversationally