Uploading Codes - Smile CDR Documentation
Uploading CodeSystems
Smile CDR bundles all conformance resources (StructureDefinitions, OperationDefinitions, CompartmentDefinitions, CodeSystems, ConceptMaps, and ValueSets) distributed as part of the FHIR release itself. These resources can be seeded into the repository at startup by enabling the Seed Base Validation Resources configuration. Once seeded, you can perform standard terminology operations such as $lookup on the Administrative Gender CodeSystem using a request like:https://try.smilecdr.com/baseR4/CodeSystem/$lookup?system=http://hl7.org/fhir/administrative-gender&code=male
In many cases, it is useful to upload your own CodeSystems for use in validation and search operations. This might involve uploading standard vocabularies such as LOINC or loading local, custom, organization-specific CodeSystems.
This page describes methods for uploading External CodeSystems (also called Not-Present CodeSystems; see CodeSystem Resources for more information on what this means). For general guidance on using external code systems with HL7 standards, including canonical URIs, OIDs, and usage notes for each system, see the HL7 External Code Systems reference.
Withdrawn Operations
As of Smile CDR 2026.08.R01 and HAPI FHIR 8.12.0, the following operations have been removed:
$upload-external-code-system– Replaced by Upload Terminology Operations with ?mode=SNAPSHOT$apply-codesystem-delta-add– Replaced by Upload Terminology Operations with ?mode=ADD$apply-codesystem-delta-remove– Replaced by Upload Terminology Operations with ?mode=REMOVE
The previous operations have been withdrawn because of a number of functional limitations: They were less secure as they relied on local file storage, and they were prone to running out of memory on smaller or heavily loaded servers. The new operations are designed from the ground up to be better replacements:
- They always work in small chunks, avoiding ever loading large amounts of data into memory. This means that even large CodeSystems such as LOINC and SNOMED CT can be loaded into a database without needing to increase available memory om the server.
- They are standard batch jobs, meaning that the storage process provides visible progress updates and can be cancelled.
- They are designed for multithreaded and clustered execution, allowing faster parallel processing if server specs support it.
Uploading External CodeSystems
Uploading external terminologies requires the FHIR_UPLOAD_EXTERNAL_TERMINOLOGY permission.
Smile CDR has the ability to import several standard terminology code systems using their native distribution formats. It is also possible to upload external terminology containing any other sets of codes, including other standard vocabularies and locally defined code sets.
This is done using the Upload Terminology Operations, which can be invoked either using a REST client, or automated using the Smile command-line tool (smileutil) command.
The following table lists the various terminologies supported by Smile CDR, as well as their URL and required input format.
| CodeSystem | URL | File Format | |
|---|---|---|---|
| LOINC | http://loinc.org | LOINC Complete Download ZIP | Upload Instructions |
| SNOMED CT | http://snomed.info/sct | SNOMED CT RF2 Distribution ZIP | Upload Instructions |
| ICD-10 (International Edition) | http://hl7.org/fhir/sid/icd-10 | XML Format (ClaML) | Upload Instructions |
| ICD-10-CM (US Edition) | http://hl7.org/fhir/sid/icd-10-cm | XML Format (CDC Tabular XML) | Upload Instructions |
| All Others | Any | Any CodeSystem may be uploaded using a CodeSystem resource and/or CSV (comma-separated value) files. | Upload Instructions |
Performing the Upload with smileutil
The Smile command-line tool (smileutil) Upload Terminology command can be used to upload standard and custom vocabulary. The sections below show examples of how to do this.
Performing the Upload via REST operation
It is also possible to upload external terminology using REST operations directly. See Upload Terminology Operations for details. The Smile command-line tool (smileutil) Upload Terminology command invokes these same operations.
Uploading LOINC
Smile CDR can ingest and process the distribution format for the LOINC vocabulary. LOINC is a rich set of codes related to health measurements, observations, and documents. LOINC is most commonly known for codes describing laboratory testing orders and results.
In order to upload LOINC, the LOINC Download File download should be selected from the LOINC website. This file will have a filename similar to Loinc_N.NN.zip. It is available from the LOINC Downloads page.
Importer Updates in 2026.08 (HAPI FHIR 8.12.0)
As of Smile CDR 2026.08 / HAPI FHIR 8.12.0, the LOINC uploader has been rewritten as a batch job in order to provide better performance and better visibility. Previously, uploading LOINC used the $upload-external-code-system operation. The previous mechanism is no longer supported, and LOINC uploads must now use the Upload Terminology Operations instead.
The new importer has several differences from the previous importer:
- When uploading LOINC, supplying a version ID for the LOINC distribution is now mandatory (previously this was optional).
- When a version is supplied, the previous importer would create two CodeSystems, one with a null version ID and one with the supplied version ID. Now, only a single version is created.
- All CodeSystems, ValueSets, and ConceptMaps created by the importer will use the supplied version ID.
- Linguistic variant files are not imported by default. See loincupload.properties below.
Input Files
The following input files are supported (note that version numbers given are only examples; newer and older versions of these files may also be supported).
| Filename | Required? | Description |
|---|---|---|
| Loinc_2.89.zip | Yes | LOINC Distribution |
| loincupload.properties | This optional file is not a part of the LOINC distribution and must be created manually. It contains version information about the upload. |
The loincupload.properties File
A second optional file may also be uploaded called loincupload.properties. This file supplies additional configuration for the import job.
# Include the following linguistic variants
loinc.linguistic.variants.codes=deAT24, frCA8
Copy
Performing the Upload
The Smile command-line tool (smileutil) Upload Terminology command can be used to upload LOINC files. An example command is shown below:
bin/smileutil upload-terminology -d Loinc_2.73.zip -d loincupload.properties -v r4 -t "http://localhost:8000" -u "http://loinc.org"
Copy
The easiest way to use this tool is to adapt the provided script, upload-loinc.sh in the terminology/loinc directory within the Smile CDR distribution.
Uploading SNOMED CT
Smile CDR has the ability to ingest and process the "RF2" distribution format for the SNOMED CT vocabulary. SNOMED CT is a very large and complex set of vocabulary covering almost all areas of healthcare.
For SNOMED specifically, the Upload Terminology command will likely need more memory than the default. See SmileUtil Memory Settings for details.
An example with memory increased to 4GB is given below:
$ env JAVA_OPTS=-Xmx4g bin/smileutil upload-terminology -d "./SnomedCT_RF2Release_INT_20160131.zip" -v "dstu3" -t "http://localhost:8000" -u "http://snomed.info/sct"
Copy
Input Files
The following input files are supported (note that version numbers given are only examples; newer and older versions of these files may also be supported).
| Filename | Required? | Description |
|---|---|---|
| SnomedCT_RF2Release_INT_20160731.zip | Yes | This file contains a complete release of SNOMED CT in the "RF2" format. The filename shown here is the international release of SNOMED CT, but national editions may be used instead as they share the same release format. The SNOMED CT distribution is a copyrighted work and requires a license to download and use. See the SNOMED CT website for more information. |
Uploading ICD-10
Smile CDR can ingest and process the distribution format for the WHO international editiion of the ICD-10 vocabulary.
Input Files
The following input files are supported (note that version numbers given are only examples; newer and older versions of these files may also be supported). Only one of the following files must be provided. ICD-10 distribution files can be obtained at the following URL: https://icdcdn.who.int/icd10/index.html
| Filename | Required? | Description |
|---|---|---|
| icd102019en.xml.zip | Either the ZIP or the XML file must be provided, but not both. | This ZIP file contains the "ClaML XML" file. |
| icd102019en.xml | Either the ZIP or the XML file must be provided, but not both. | This file in the "ClaML XML" format contains the complete codeset and hierarchy for ICD-10 codes. |
Performing the Upload
In order to upload ICD-10, the Smile command-line tool (smileutil) Upload Terminology command can be used. An example command is shown below:
bin/smileutil upload-terminology -d icd102019en.xml.zip -v r4 -t "http://localhost:8000" -u "http://hl7.org/fhir/sid/icd-10|2019en"
Copy
Uploading ICD-10-CM
Smile CDR has the ability to ingest and process the distribution format for the ICD-10-CM vocabulary.
Input Files
The following input files are supported (note that version numbers given are only examples; newer and older versions of these files may also be supported). Only one of the following files must be provided. ICD-10-CM distribution files can be obtained at the following URL: https://ftp.cdc.gov/pub/health_statistics/nchs/publications/ICD10CM/
| Filename | Required? | Description |
|---|---|---|
| icd10cm-table and index-2026.zip | Either the ZIP or the XML file must be provided, but not both. | This ZIP file contains the "tabluar XML" file. |
| icd10cm-tabular-2026.xml | Either the ZIP or the XML file must be provided, but not both. | This XML file contains the complete codeset and hierarchy for ICD-10-CM codes. |
Performing the Upload
In order to upload ICD-10-CM, the Smile command-line tool (smileutil) Upload Terminology command can be used. An example command is shown below:
bin/smileutil upload-terminology -d icd10cm-tabular-2026.xml -v r4 -t "http://localhost:8000" -u "http://hl7.org/fhir/sid/icd-10-cm|2026"
Copy
Uploading Other Vocabularies
If you have a set of concepts that is not already supported by one of the formats above, you can convert it into a standard HAPI FHIR custom vocabulary format and then upload it.
Input Files
| Filename | Required? | Description |
|---|---|---|
| custom.zip | Either the ZIP or the CSV/JSON/XML file(s) must be provided, but not both. | This ZIP file contains one or more of the CSV/XML/JSON files described in Vocabulary Input File Formats below. |
| concepts.csv | No | This CSV file contains concept codes and display names. The format is described below. |
| hierarchy.csv | No | This CSV file contains parent/child relationships between concepts. The format is described below. |
| properties.csv | No | This CSV file contains concept properties (key/value pairs associated with a specific concept). The format is described below. |
| codesystem.json or codesystem.xml | No | This file is a JSON or XML encoded CodeSystem resource. It can be used to describe the CodeSystem, and it can also be used to supply the concept definitions instead of using the CSV file formats. An example is provided below. |
Upload Mode / Delta Operations
Set of codes can be provided as a SNAPSHOT, meaning that any existing codes are replaced with the complete set of concepts, relationships, properties, etc. are all replaced with those supplied to the job. It is also possible to supply a delta, meaning a set of concepts/relationships/properties/etc. to ADD or REMOVE.
See the mode parameter of the $hapi.fhir.upload-terminology.create-job operation for more information on how to do this.
Performing the Upload
To upload custom terminology using the standard Custom CSV Vocabulary Input Files, use the Smile command-line tool (smileutil) Upload Terminology command. An example command is shown below:
bin/smileutil upload-terminology -d codesystem.json -d concepts.csv -d hierarchy.csv -v r4 -t "http://localhost:8000" -u "http://example.com/labCodes|1.0" -m SNAPSHOT
Copy
You can also package the distribution files into a single zip file, and upload it instead:
bin/smileutil upload-terminology -d custom.zip -v r4 -t "http://localhost:8000" -u "http://example.com/labCodes|1.0" -m SNAPSHOT
Copy
Vocabulary Input File Formats
A zip file should be created that has the following file(s) listed below as contents. Note that all CSV files are required to have a header line containing the column names as the first line. This is shown in the examples below.
Concepts File: concepts.csv
This file should have the following columns:
- CODE – contains the concept code
- DISPLAY – contains the concept display name
Example:
CODE,DISPLAY
CHEM,Chemistry
HB,Hemoglobin
NEUT,Neutrophils
MICRO,Microbiology
C&S,Culture and Sensitivity
Copy
Hierarchy File: hierarchy.csv
This file contains optional hierarchy information if your codes have a parent-child hierarchy. This file should have the following columns:
- PARENT – contains the concept code for the parent
- CHILD – contains the concept code for the child
Example:
In the example below, the HB and NEUT concept will be children of the CHEM concept. The C&S concept will be a child of the MICRO concept.
PARENT,CHILD
CHEM,HB
CHEM,NEUT
MICRO,C&S
Copy
Omitting hierarchy.csv The hierarchy.csv file is always optional; if it is missing, all codes defined in concepts.csv are treated as root concepts (concepts with no parents). Adding Child Records
When using this file for the Delta Operations it is possible to specify PARENT codes that do not exist in concepts.csv but are already present in the existing CodeSystem. In this case, the child code is added as a child to the existing PARENT code, whether it is a root concept itself, or is a child as well. If the PARENT code does not already exist, it will be created (with no display name or other attributes populated).
Properties File: properties.csv
This optional file can be used to supply properties to be applied to a concept (i.e. values for CodeSystem.concept.property). This file should have the following columns:
- CODE – The concept code to which the property will be attached.
- KEY – The property name.
- VALUE – The property value. This should be a simple string value for all types except
CODING, where it should be a JSON string containing the serializedCodingobject. - TYPE – The property type. Must be one of the following:
string,integer,boolean,code,dateTime,decimal,Coding
Example
The following example shows a number of properties being applied to the CHEM concept. Note that the Coding concept has its quote marks escaped using the CSV escape syntax (a double quote).
CODE, KEY, TYPE, VALUE
HB, color, string, red
HB, sequence, integer, 25
HB, archived, boolean, false
HB, created, dateTime, 2022-01-01
HB, k_score, decimal, 1.23
HB, loinc_equiv, Coding, "{""system"":""http://loinc.org"", ""code"":""1-2345""}"
Copy
CodeSystem Definition: codesystem.json or codesystem.xml
This file contains the CodeSystem definition. If this file is not supplied and a CodeSystem resource already exists for the given CodeSystem URL, the existing CodeSystem resource is not modified.
codesystem.json Example Without Codes If a CodeSystem resource is supplied along with the CSV file(s), it will be stored in the repository if no CodeSystem already exists for the given system URL and version.
{
"resourceType": "CodeSystem",
"id": "example-lab-codes-1.0",
"url": "http://example.com/labCodes",
"version": "1.0",
"name": "Example Lab Codes",
"description": "A set of lab codes",
"status": "active",
"publisher": "Example Organization Corporation Worldwide",
"date": "2019-07-30",
"content": "not-present"
}
Copy
codesystem.json Example With Codes The CodeSystem resource can be used to supply concepts as well, instead of using the CSV files described above.
{
"resourceType": "CodeSystem",
"id": "example-lab-codes-1.0",
"url": "http://example.com/labCodes",
"version": "1.0",
"name": "Example Lab Codes",
"description": "A set of lab codes",
"status": "active",
"publisher": "Example Organization Corporation Worldwide",
"date": "2019-07-30",
"content": "not-present",
"concept": [ {\
"code": "CODE-1",\
"display": "Code 1",\
"property": [ {\
"code": "property-key",\
"valueString": "A Property Value"\
} ],\
"concept": [ {\
"code": "CHILD-CODE-1",\
"display": "A Child Code"\
} ]\
}, {\
"code": "CODE-2",\
"display": "Code 2"\
}, {\
"code": "CODE-3",\
"display": "Code 3"\
} ]
}
Copy
Upload Terminology Operations
To upload external terminology directly using REST operations (as opposed to using The Smile command-line tool / smileutil Upload Terminology command), a set of FHIR operations can be used.
These operations support uploading both supported standard terminologies (using their native distribution formats), and other terminologies (using a standard file format described on this page).
Uploading terminology involves a sequence of operations:
- Step 1: The
$hapi.fhir.upload-terminology.create-joboperation is used to create a new terminology upload job, and assign an ID to the created job instance. - Step 2: The
$hapi.fhir.upload-terminology.attach-fileoperation is used to upload the terminology distribution file(s) and attach them to the job instance. - Step 3: The
$hapi.fhir.upload-terminology.start-joboperation starts the upload job instance and begins processing the distribution file(s). - Step 4: The
$hapi.fhir.upload-terminology.poll-for-statusoperation is used to poll the status of the upload job instance.
These operations are safe to use on a live system, even if clients are actively invoking the terminology services directly (through operations such as CodeSystem/$lookup) and indirectly (through operations such as $validate). After a job is complete, there may be a short delay (up to several minutes) before the new or updated content becomes available due to internal memory caches in Smile CDR. The system will remain consistent throughout the process.
External Terminology Upload Operation: $hapi.fhir.upload-terminology.create-job
The $hapi.fhir.upload-terminology.create-job operation is used to create a new terminology upload job. This operation assigns a unique ID to the job and returns it in the response. The job is ready for one or more files to be attached to it, and is not yet started.
Request Parameters
This operation takes the following parameters, which may be supplied in the request URL or in the request body using a Parameters resource:
| Name | Cardinality | Type | Description |
|---|---|---|---|
| system | 1..1 | uri | Specifies the CodeSystem URL to upload. This may be a versioned canonical URL (e.g. `http://loinc.org |
| version | 1..1 | code | Specifies the CodeSystem version to upload. |
| mode | 0..1 | code | This parameter determines whether the operation should add, remove, or replace existing concepts in the database. It supports the following values: - SNAPSHOT – (This is the default if not explicitly specified) Any existing concepts (and their relationships/properties/etc.) for the CodeSystem version being targeted will be removed, and replaced with the concepts supplied to the job.- ADD – Any existing concepts for the CodeSystem version being uploaded will be retained, and the concepts supplied to this job will be added to them. If any concepts supplied to the job are already present in the database, they will be updated if necessary (replacing the display name if it has changed, adding properties and designations, etc) but no duplicate concepts will be created.- REMOVE – Any supplied concepts will be removed if they are found in the database. Any children of supplied concepts will also be removed. |
| makeCurrent | 0..1 | boolean | Specifies whether the CodeSystem version being uploaded should be marked as the current version. This means that code lookups, code validations, and other operations will use this version by default if a CodeSystem version isn't explicitly specified. This parameter defaults to true, so the version being uploaded will be marked as the current version unless this parameter is included with a value of false. |
Response Parameters
The response to this operation is a Parameters resource containing the following parameters:
| Name | Cardinality | Type | Description |
|---|---|---|---|
| outcome | 1..1 | string | Returns a human-readable message indicating the outcome of the operation. |
| jobInstanceId | 1..1 | code | Returns a unique identifier for the newly created job instance. |
External Terminology Upload Operation: $hapi.fhir.upload-terminology.attach-file
The $hapi.fhir.upload-terminology.attach-file operation is used to upload the terminology distribution file(s) and attach them to the job for processing. This operation is a nonstandard FHIR operation, and requires a resource body containing a raw distribution file, such as a ZIP file.
Request Parameters
This operation takes the following parameters, which must be supplied in the request URL.
| Name | Cardinality | Type | Description |
|---|---|---|---|
| filename | 1..1 | code | Specifies the filename being uploaded. Different CodeSystems files with specific names to be uploaded, so the filename must be appropriate for the CodeSystem. For example, the LOINC CodeSystem ( see above) requires a file with the name Loinc_[version].zip or Loinc.zip). |
| jobInstanceId | 1..1 | code | The job instance identifier for the upload job, as returned by the $hapi.fhir.upload-terminology.create-job operation. |
Request Example
The following example shows an invocation of the $hapi.fhir.upload-terminology.attach-file operation.
POST /CodeSystem/$hapi.fhir.upload-terminology.attach-file?jobInstanceId=SOME-INSTANCE-ID&filename=Loinc_2.89.zip
[...zip file contents...]
Copy
Response Parameters
The response to this operation is a Parameters resource containing the following parameters:
Response Example
The following example shows the response to the $hapi.fhir.upload-terminology.attach-file operation.
{
"resourceType": "Parameters",
"parameter": [ {\
"name": "outcome",\
"valueString": "Attachment with ID[SOME-ATTACHMENT-ID] has been stored for job with ID[SOME-INSTANCE-ID]."\
}, {\
"name": "jobAttachmentId",\
"valueCode": "SOME-ATTACHMENT-ID"\
} ]
}
Copy
External Terminology Upload Operation: $hapi.fhir.upload-terminology.start-job
Once all required files have been attached to the job, the $hapi.fhir.upload-terminology.start-job operation is used to start the upload job. This operation uses the FHIR Asynchronous Interaction Request Pattern, and requires a Prefer: respond-async header to be included in the request.
Request Parameters
This operation takes the following parameters, which may be supplied in the request URL or in the request body using a Parameters resource:
| Name | Cardinality | Type | Description |
|---|---|---|---|
| jobInstanceId | 1..1 | code | The job instance identifier for the upload job, as returned by the $hapi.fhir.upload-terminology.create-job operation. |
Request Example
The following example shows an invocation of the $hapi.fhir.upload-terminology.attach-file operation.
POST /CodeSystem/$hapi.fhir.upload-terminology.start-job?jobInstanceId=SOME-INSTANCE-ID
Copy
The server will respond with a 202 Accepted response code, and will include a Content-Location header with a URL that can be used to poll the status of the upload job.
External Terminology Upload Operation: $hapi.fhir.upload-terminology.poll-for-status
The $hapi.fhir.upload-terminology.poll-for-status operation is used to poll the status of the upload job. It should be invoked as an HTTP GET using the URL retuend in the Content-Location header of the response to the $hapi.fhir.upload-terminology.start-job operation.
This operation will return a 202 Accepted response code if the upload job is still in progress, and a 200 OK response code if the job has been completed successfully. If the job has failed, a 5xx series error code will be returned.
How Uploaded Terminology Interacts with IG Packages
A CodeSystem with content=not-present is typically a licensed external terminology (e.g. ICD-10-CM, CPT) that an IG ships as a placeholder. It registers the CodeSystem URL but contains no concepts. Only CodeSystems actually shipped in an installed package get a placeholder; one that's merely referenced (e.g. by a ValueSet) but never shipped by any installed package has none.
Uploading terminology via the Upload Terminology Operations (or smileutil upload-terminology) loads the concepts into dedicated terminology tables alongside the placeholder, regardless of whether the upload happens before or after IG installation. The placeholder itself is never replaced or deleted by this, and its content=not-present status stays intentional, since the concepts live in the terminology tables rather than inline in the resource. By default, a later package install also leaves an existing placeholder alone; see overwriteContentNotPresentCodeSystems below.
Protecting uploaded CodeSystems during package installation
The overwriteContentNotPresentCodeSystems parameter (default false) controls what happens when a subsequent package installation encounters an existing content=not-present``CodeSystem:
- When set to
false(the default), the package'sCodeSystemresource is skipped, preserving the externally loaded concepts in the terminology tables. This is the safe default. - When set to
true, the package'sCodeSystemresource overwrites the existing placeholder. This can cause externally loaded concepts to become orphaned from theCodeSystemresource. Only use this if you intentionally want the package version to replace an externally loaded one.
When installing IGs on a repository that already has externally loaded terminology, always ensure overwriteContentNotPresentCodeSystems is false (or omitted) to avoid accidentally replacing loaded CodeSystems.
Uploading Codes
Terminology
Terminology Introduction Uploading Codes Terminology and Full-Text Indexing ValueSet Expansion Terminology Mapping FHIR Response Terminology Mapping In-Place Code Translation