IMO® Precision Normalize - Classic API Guide
1 Introduction
This guide is intended to provide an introduction and overview of the Classic implementation of the IMO Precision Normalize API for integrating partner organizations.
The IMO Precision Normalize API supports two operations for normalizing input to IMO lexicals:
-
POST /precision/normalize/v1: The subject of the current guide, commonly referred to as the Classic endpoint. This endpoint is the recommended option for term normalization when you want to return lexicals from any domain other than "Problem"; if you want to employ custom lexical mappings; or if you want to return a broader range of lexicals with no specific preference for specificity or billing codes.
This operation can match input terms to lexicals from any domain, but has only limited support for AI models.
-
POST /precision/normalize/enrichment: Commonly referred to as the Enrichment endpoint. This endpoint is usually the recommended option for term normalization relevant to the Problem domain. Enrichment normalization employs enhanced contextual analysis using AI models and always aims to supply the most specific lexical applicable to your input that is also associated with a billable ICD-10-CM code.
This operation can only match input terms to Problem domain lexicals, does not support custom lexical mappings, and returns a more limited quantity of the highest scoring, billing-relevant lexical matches. For more information on this operation, please refer to the ENRICHMENT GUIDE tab.
This guide consists of the following major sections:
-
1 Introduction
Introduces the Classic implementation of the IMO® Precision Normalize API, its operations, and its primary terminology and concepts.
-
Provides guidance on getting started with Classic normalization operations, including prerequisites, basic communication and authentication requirements, and a high-level summary of the request and response payload.
-
Describes the code-based matching approach to normalization. This method normalizes each supplied clinical code by returning the one IMO lexical that best represents its clinical concept.
-
Describes the term-based matching approach to normalization for Classic operations. This method normalizes each supplied input term by returning one or more IMO lexicals that best match the clinical intent of the input.
-
5 Classic Term Normalization Requests
Demonstrates the basic request-response patterns applicable to Classic term normalization for each supported domain, including sample payloads.
-
Lists each of the error messages that may be returned for a normalization record in the
response.error_messagearray of a response payload. -
7 Request Rate and Response Times
Provides guidelines on recommended request payload size and expected API response times based on the quantity of supplied normalization records and the target domain.
-
Describes an optional workflow involving the generation of a session to track input term normalization across multiple requests and endpoints with the goal of identifying the most specific lexical applicable to the relevant clinical concept.
-
Describes the SFTP interface for Classic normalization, used to process large batches of time-independent normalization records.
1.1 Normalization Overview
The IMO® Precision Normalize API standardizes inconsistent clinical data from diverse systems into clinically-validated terminology with comprehensive mappings to standard industry codes. In IMO products, normalization refers to the process of "cleaning" or standardizing clinical data obtained from various sources to arrive at a common, consistent data set, enabling more effective analysis and accurate billing.
In the IMO Precision Normalize API, each act of normalization takes as input a single medical term or code, which the API attempts to match to an internal IMO library of identifiers known as "lexicals". When using a medical term as input, you may also supply additional context for that term, such as the surrounding text from the original data source. The output to the normalization process is one or more lexicals matched to the input with varying degrees of confidence. Each returned lexical provides a standardized title describing a particular clinical concept and a set of code mappings from all applicable clinical code systems.
Each request to the IMO Precision Normalize API may include multiple normalization records, each describing a single term or code that requires normalization. This API is designed for use cases requiring real-time normalization of small batches of records. When processing large batches of normalization records, for optimal performance each request payload should include 10 to 25 normalization records. For the Classic normalization endpoint, an SFTP interface is also available for processing larger batches of time-independent normalization records.
1.2 Document Scope
This guide provides a high level description of each available endpoint applicable to Classic normalization, their intended purposes and workflows, guidelines for their use, and example payloads for different use-cases. This guide also briefly describes the internal processes by which the API performs Classic normalization and matches input terms and codes to IMO lexicals.
This guide does not provide an exhaustive description of every available parameter and payload field. For full technical details about each supported operation, please refer to the REFERENCE DOCUMENTATION tab.
1.3 Operations
The Classic implementation of the IMO Precision Normalize API supports the following operations:
-
Authentication: The following operation retrieves an OAuth 2.0 Bearer token to be supplied in the header of all other IMO Precision Normalize API requests. The body of this request must supply a Client ID and Secret, obtained as described below in 2.1 Prerequisites.
POST /oauth/token
-
Normalization: The following operation matches input terms and codes to IMO lexicals using the Classic implementation of the IMO Precision Normalize API. This operation is the primary topic of the current guide.
POST /precision/normalize/v1
-
Term Refinement: The following operations are used for the term refinement workflow. This workflow involves generating a session to track the normalization of an input term across multiple requests and endpoints to identify greater levels of lexical specificity. For more information on this workflow, see 8 Term Refinement Workflow below.
-
GET /precision/normalize/sessionRetrieves a new session id. This value can be supplied in the request payloads of a number of IMO API operations.
-
POST /precision/normalize/event/selectionReports which lexical the partner application selected as most specifically identifying the clinical concept represented by the input term.
-
The current guide includes guidelines and best practices for using each of the above operations. For an exhausitive description of each available parameter and payload field, please refer to the REFERENCE DOCUMENTATION tab.
1.3 Terminology and Concepts
Before working with the IMO Precision Normalize API, it is a good idea to familiarize yourself with the following IMO terminology and concepts relevant to normalization:
- 1.3.1 Lexical
- 1.3.2 Clinical Code
- 1.3.3 Domain
- 1.3.4 Term-Based Matching
- 1.3.5 Code-Based Matching
- 1.3.6 Normalization Record
- 1.3.7 Score
1.3.1 Lexical
An IMO data object representing one possible description for a particular clinical concept. A given clinical concept may be represented by several related lexicals, each representing one description "variant" for that concept. For all such related lexicals, there exists a single default variant, which is considered to be the most accurate description for the clinical concept. For example, IMO maintains the lexical variants "Pain in the chest" and "Chest pain, unspecified", both of which are associated with a default variant of "Chest pain".
When performing normalization, the IMO Precision Normalize API always returns both the lexical that was directly matched to your input and its default variant. In response payloads, the directly matched lexical is identified in the items.lexical_title field and its default variant is identified in the items.default_lexical_title field. The default lexical title is typically considered to be the normalized text for the input term. When your input is directly matched to the default variant, these two response fields are identical.
Each IMO lexical has the following properties relevant to normalization:
-
Lexical Code: A unique, numeric IMO identifier for the lexical. This value exists to uniquely identify the lexical data object within IMO applications.
-
Lexical Title: One or more words briefly describing a single clinical concept. When normalizing an input term, this title represents the normalized text that should replace that input term. Lexical titles are written and validated by professionally credentialled subject matter experts employed by IMO Health.
-
Domain: Each lexical is associated with a single IMO content Domain representing a clinical subject area. See Domain below.
-
Subdomain: Each Procedure domain lexical is typically assigned to one or more subdomains representing clinically meaningful classifications for the procedure. For example, a lexical may have a subdomain of "surgical procedure" or "imaging procedure".
In response payloads, a lexical's subdomains are identified in the
items.metadata.subdomainsarray. This array is excluded for lexicals from any domain other than Procedure.
1.3.2 Clinical Code
An alphanumeric identifier from an industry standard code system, such as ICD-10-CM or SNOMED CT. Each clinical code represents a single clinical concept from its respective system. For example, in the ICD-10-CM system, the code "R07.9" represents "Chest pain, unspecified".
IMO maintains a detailed, frequently updated library of clinical codes from each supported system. Within IMO's database, each code can be associated with one or more lexicals corresponding to the same clinical concept. This relationship is often referred to as a "mapping" between codes and lexicals. A lexical is typically mapped to different codes from many different systems, and may be sometimes even be mapped to multiple codes from the same system. Likewise, a given clinical code may be mapped to multiple lexicals, each representing a different variant of the same basic clinical concept (see Lexical above).
When performing normalization, the IMO Precision Normalize API returns a list of all clinical codes associated with the default variant of each matched lexical. In response payloads, these associated codes are listed in the items.metadata.mappings object, broken down by each aplicable code system. For information on how code mappings appear in response payloads, see 2.4.3 Response Metadata Mappings below.
The exact details that can be returned for each code depends on its code system, but the following properties are applicable to most clinical codes stored in IMO's database:
-
Code System: Each clinical code belongs to a particular industry standard code system.
-
Code: The formal alphanumeric identifier for the code, as specified by the applicable code system.
-
Title: The formal description of the clinical concept represented by the code, as specified by the applicable code system.
-
Map Type: This is a property of the relationship between the code and a particular lexical. This property is primarily applicable when a lexical is associated with multiple codes from the same code system and describes the preference relationship of each applicable code to the lexical.
If applicable to the code system, the
mappingsobject in response payloads most commonly reports one of the following values for this property in themap_typefield:-
Preferred Primary - The single best code mapping for the lexical from the applicable system, as recommended by IMO's subject matter experts. For billing workflows, this may serve as the primary billing code.
-
Non-Preferred Primary - An alternate choice to the Preferred Primary when more than one option was deemed clinically defensible by IMO's subject matter experts.
-
Other Preferred Primary - An additional code of equal importance to the Preferred Primary, used when more than one billing code is necessary to fully represent the lexical.
-
Preferred Secondary - A secondary code that may be needed for complete billing in addition to the Preferred Primary (e.g. a manifestation code paired with an etiology code). This code does not in itself suffice as a primary billing code.
-
Other Preferred Secondary - Additional codes that may be needed for complete billing in addition to the Preferred Secondary. Typically listed after preferred codes in all relevant documentation. This code does not in itself suffice as a primary billing code.
-
One of these codes - Used when any one of several returned codes from the same system could possibly apply to the lexical. This is used when every available code represents a more specific clinical concept than the lexical itself.
-
Use one code from group X - Similar to One of these codes, but this property is also accompanied by a relationship_group property specifying a particular value (X). This indicates that any of the returned codes with the same relationship_group value may apply.
-
-
Relationship Type: This is a property of the relationship between the code and a particular lexical. This property indicates how well the clinical concepts respectively represented by the code and the lexical align in terms of specificity. This is sometimes also referred to as the code and lexical's "semantic relationship".
If applicable to the code system, the
mappingsobject in response payloads may report any of the following values for this property in therelationship_typefield:-
Same as - The code and lexical represent the exact same clinical concept.
-
Broader than - The code's clinical concept is less specific than the lexical.
-
Narrower than - The code's clinical concept is more specific than the lexical.
-
1.3.3 Domain
An IMO content category representing a particular clinical subject area, used to group lexicals by their purpose or intended use. Each lexical is associated with only one domain. Each IMO domain supports several applicable clinical code systems, which determine the code mappings returned in response payloads for each lexical matched to your input.
The following table lists every domain applicable to the IMO Precision Normalize API and its supported code systems:
| Domain | Description | Code Systems |
|---|---|---|
| Problem | Lexicals representing the states of being that can apply to a patient and are relevant to their health or healthcare. Primarily diagnoses, but may also represent symptoms, physical findings, care status, and states of abnormality on lab tests. | ICD-9-CM, ICD-10-CM, ICD-O, DSM-5-TR, SNOMED International, SNOMED US, UMLS, USCDI |
| Procedure | Lexicals representing actions that can be performed on, or on behalf of, a patient as part of the patient’s health care. Examples include surgical procedures, imaging, referrals, and education interventions. | CPT, HCPCS, ICD-10-PCS, LOINC, SNOMED International, SNOMED US, UMLS, USCDI |
| Medication | Lexicals representing generic and branded medications at various levels of granularity, such as dose strength and dose form. | CVX, FDA BIOSIMILAR, NDC, RxNorm, UMLS, USCDI |
| Lab | Lexicals representing laboratory and anatomic pathology results, orders, and associated observations. | LOINC, SNOMED International, UMLS, USCDI |
| Allergen | Lexicals representing a substance that may trigger an allergic reaction in a patient, including but not limited to food, medication, environmental factors, and other allergenic agents. | RxNorm, SNOMED International, UMLS, USCDI |
| Anatomical Site | Lexicals representing specific anatomical locations, structures, and regions of the human body, enabling the extraction and normalization of anatomical observations, abnormalities, and measurements from unstructured clinical data such as radiology reports. | SNOMED International, UMLS, USCDI |
Note: When reviewing lexical code mappings in response payloads, keep in mind the following exceptions to the code system support outlined in the table above. For information on how code mappings appear in response payloads, see 2.4.3 Response Metadata Mappings below:
-
For Lab domain lexicals, the
mappingsobject may return codes for the cpt, hcpcs, and icd10pcs code systems, even though these systems are not explicitly supported by the Lab domain. This is because Lab domain requests use a special context matching process that may return lexicals from several domains. For more information, see 5.4 Lab Domain below. -
For Medication domain lexicals, in the
mappingsobject, the ndc field will be empty if there are more than 25 NDC product codes mapping to the same RxNorm. -
In the
mappingsobject, the uscdi field will only appear if your Client ID has confirmed USCDI licensing. For more information, see 2.1 Prerequisites below.
1.3.4 Term-Based Matching
One method by which the IMO Precision Normalize API can match a normalization record's input to lexicals. When term-based matching, the API attempts to match a supplied input_term to one or more lexicals, with the possible assistance of any supplied context. The domain specified for each normalization record determines which lexicals the API can match.
Depending on a normalization request's preferences.match_field_pref setting, the API can be set to use only term-based matching, only code-based matching, or to try one method first before falling back to the other. For more information, see 2.5 Match Field Preference below.
Term-based matching is most commonly used to translate a medical term found in patient data to a standardized lexical title and to identify the codes associated with the corresponding clinical concept. It can also be used a backup to code-based matching when your supplied input code turns out to be incorrect, but your input term is valid.
1.3.5 Code-Based Matching
One method by which the IMO Precision Normalize API can match a normalization record's input to lexicals. When code-based matching, the API attempts to match a supplied input_code and input_code_system to exactly one lexical. When code-based matching, the API can match the supplied input code to a lexical from any domain, regardless of the endpoint or the normalization record's domain preference.
Depending on a normalization request's preferences.match_field_pref setting, the API can be set to use only code-based matching, only term-based matching, or to try one method first before falling back to the other. For more information, see see 2.5 Match Field Preference below.
Code-based matching is commonly used to confirm the correct title of a clinical concept for which you possess the code or when you want to view related codes from alternate clinical code systems. It can also be used as a backup to term-based matching when your supplied input term cannot be adequately matched, but your input code is valid.
1.3.6 Normalization Record
An IMO record for the normalization of a single medical term or code. When defining an IMO Precision Normalize API request payload, in the requests array, you must include one object for each term or code that you want to normalize to an IMO lexical. Each object in this array defines a separate normalization record that you will use to track a single normalization action. The response payload will also include a requests array containing one corresponding object for each normalization record you supplied in the request. In the response, the requests.items array for each normalization record lists one or more lexicals that the API matched to that record's input.
The normalization records that you define in your request payload may map to records from a partner system, or they may exist independently solely for the purpose of performing IMO Precision Normalize API operations. There is no requirement that a normalization record maps to any external entity.
In a request payload, each normalization record includes some or all of the following fields:
-
record_id: A unique identifier for the normalization record, primarily used to identify corresponding record objects between the request and the response. This value may map to a partner application record identifier, or it may exist only for normalization purposes. Each supplied record_id should typically be unique per normalization request, but there is no strict uniqueness requirement and you may use this field as best suits your workflow.
-
domain: This field is used differently depending on the situation:
-
Term-based matching: This field can specify a single IMO content domain (Problem | Procedure | Medication | Lab | Allergen | Anatomical Site) from which the API should match lexicals to the supplied
input_term, or a value of "Auto". For a description of each domain that may be supplied in this field, see 1.3.3 Domain above.If the domain field is set to "Auto", the API attempts to match lexicals from any of several permitted domains. When the
input_code_systemfield is included, this cross-domain search is limited to only those domains relevant to the identified system. For more information on term-based matching across multiple domains, see 4.2 Auto Domain Resolution below. -
Code-based matching: When code-based matching, the domain field's value is ignored and the API can return a lexical from any IMO clinical domain. This field must still be included with an allowed value in order to receive a valid response.
-
-
input_term: When term-based matching, this is the title of a medical term that you want to normalize to a lexical. This value may include any number of words up to a total of 500 characters, but should be limited to a single medical term without context. For guidelines on populating this field, see 4.1.1 Input Term Values below.
The input term is not used for code-based matching. When code-based matching, you may still want to include an input term if using term-based matching as a backup (i.e. match_field_pref="input_code_first"), but otherwise you can exclude the input term.
-
input_code and input_code_system: When code-based matching, this is the clinical code that you want to normalize to a lexical and its corresponding code system. If supplying an input code, you must also always supply its input code system.
These fields are not directly used for term-based matching. When term-based matching, you may exclude these fields, but you may still want to include them for any of several reasons:
-
Code-based matching as a backup: When term-based matching, you may want to include an input code and system if your request is using code-based matching as a backup (i.e. match_field_pref="input_term_first"). For this use-case, the input code should represent the clinical code that you believe best maps to your
input_term. -
Discrepancy Checking: When term-based matching, if your request is using discrepancy checking (i.e. preferences.discrepancy_check = true), the response will include an
items.discrepancyobject reporting whether there is a mismatch between the supplied input code and the codes mapped to the highest scoring lexical returned for the normalization record. For more information, see 4.12 Discrepancy Checking below. -
Auto Domain Resolution: When term-based matching, if a normalization record's
domainis set to "Auto" and also specifies an input_code_system, then the API can only return lexicals from those domains relevant to the identified system. For this use-case, only the input_code_system is required and the input_code field may be excluded. For more information on term-based matching across multiple domains, see 4.2 Auto Domain Resolution below.
-
-
context: This object may supply a number of fields providing additional context for the normalization record. The fields you include for a normalization record may vary depending on purpose:
-
AI Analysis: When term-based matching, if AI Enhancement is enabled for your Client ID, AI models can analyze the
source_textfield to better understand the context of the input term and find optimal lexical matches. For guidelines on populating this field, see 4.1.2 Source Text Values below. For more information on how this field is used, see 4.4 Input Term Transformation and 4.7 AI Context Analysis below. -
Record Tracking: In all situations, the
use_count,application_id,facility_id,encounter_id,document_id, andproject_idfields enable you to track any applicable record details from partner applications in the normalization record. These fields are not used for lexical matching, but they are always echoed back in the response. -
Lab Domain: When term-based matching in the Lab domain, the API considers association with the
unit_of_measure,order_name,loinc_component,loinc_property,loinc_time,sample_type,loinc_scale, andloinc_methodfields when evaluating lexicals as optimal matches for the input term. For more information, see 4.6 Lab Context Analysis below. -
Allergen Domain: When term-based matching in the Allergen domain, when the
reactionandseverityfields are specified, each lexical returned in the response populates fields describing SNOMED International code mappings corresponding to the specified reaction (mappings.reaction_mappings) and/or severity (mappings.severity_mappings). These fields do not impact which lexicals are returned in the response. For more information on how these fields are used, see 5.5 Allergen Domain below.
-
1.3.7 Score
When performing normalization, this is a decimal value representing the IMO Precision Normalize API's confidence in a match between a lexical and a normalization record's supplied input. This is a value from 0 to 1, specified using up to 3 decimal places. Higher scores indicate a better match, with a value of 1 representing an exact match.
For each normalization record in a response payload, the items.score field states the score assigned to each returned lexical. When term-based matching, the items array may return multiple lexical matches with varying degrees of confidence, sorted in descending order by score. When code-based matching, the items array returns at most a single lexical match with a score of 1.
How you should interpret the score for a given lexical match depends on your risk tolerance and use case. For example, data used for a clinical end-user application (e.g. interoperability messages) requires a higher degree of scrutiny than those that will be used for aggregate data analytics. As a general rule of thumb, IMO recommends that you accept lexical matches used for clinical end-user applications at 0.98 or above, and for aggregate data analytics at 0.90 or above.
You might also adopt a workflow incorporating manual review of lexical matches according to the following recommended guidelines:
- 1.0 – 0.98: Automatically accept without review.
- 0.90 – 0.979: Automatically accept after minimal review.
- 0.85 - 0.899: Additional clinical review needed. The effort to rationalize information may not be worth the number of records managed.
- < 0.85: Accept only in exceptional cases. Efforts to rationalize the information may be costly.
2 Getting Started
The following sections provide basic guidance on getting started with the IMO Precision Normalize API:
- 2.1 Prerequisites
- 2.2 Base URL and Environments
- 2.3 Authentication
- 2.4 Payload Summary
- 2.5 Match Field Preference
2.1 Prerequisites
Before working with the IMO Precision Normalize API, you may need to obtain or confirm access to each of the following:
2.1.1 Client ID and Secret
Authentication for the IMO Precision Normalize API is performed using OAuth 2.0 Bearer tokens, as described in 2.3 Authentication below. In order to retrieve a Bearer token, you will first need to obtain a Client ID and Secret, either from IMO Health Customer Support or by manually creating a Trial App from the Developer Portal.
To create a trial app and generate your own Client ID and Secret, perform the following steps:
-
Log in to the Developer Portal.
If you do not have login credentials for the portal, please contact IMO Health Customer Support for assistance. -
At the upper-right corner of the portal, click the Key (My Credentials) icon.
The Credentials screen appears. -
Click the +New Trial button.
The Create Trial App screen appears. -
Enter a Name for your application and in the API Products section, select the Normalize option.
-
At the bottom-right corner of the screen, click the Create Trial App button.
The Credentials screen appears and displays a notification that your Trial App will shortly be created. -
After several minutes, Refresh the credentials screen.
The new Trial App appears as an entry in a tabular interface. -
Beneath the Operations column, click the Eye (View) icon next to your Trial App.
The Trial <Name> screen appears. -
In the Credential section, click the Show links next to the Client Key and Client Secret entries.
Record the displayed values. You may supply these values as your Client ID and Secret when performing authentication, as described 2.3 Authentication below.
2.1.2 USCDI Access
In order to view USCDI (United States Core Data for Interoperability) code mappings for IMO lexicals or to filter lexicals by USCDI fields, your organization must confirm your USCDI licensing with IMO Health. Once confirmed, USCDI access can be granted per Client ID. If your Client ID has not yet been granted USCDI access, in response payloads the mappings object will exclude the uscdi field for returned lexicals and you will receive an error if you attempt to use the filters preference to filter results by USCDI fields.
2.1.3 AI Enhancement Access
The normalization process can optionally employ AI models to help optimize lexical matching by performing contextual analysis and term transformation. For the Classic endpoint, this functionality is referred to as "AI Enhancement" and you must coordinate with IMO Health to enable this feature for your Client ID.
2.2 Base URL and Environments
The IMO Precision Normalize API includes the following environments and corresponding base URLs:
-
Sandbox: When performing initial integration testing, you should send requests to the Sandbox environment. This is a scaled-down version of the Production environment intended for application development requests that are not considered against usage metering. Requests to the Sandbox environment are sent to the following base URL:
https://api-sandbox.imohealth.com/
-
Production: After integration testing, you should send all requests pertaining to normal operations to the Production environment. Requests to the Product environment are sent to the following base URL:
https://api.imohealth.com/
2.3 Authentication
The IMO Precision Normalize API performs authentication using OAuth 2.0 bearer tokens, which you must supply in the Authorization header of all normalization requests. You can retrieve a Bearer token using the following operation, the body of which must supply a valid Client ID and Secret, as described in 2.1 Prerequisites above:
POST /oauth/token
The response body will supply a Bearer token (access_token) and a time until expiry in seconds (expires_in). IMO Bearer tokens expire anywhere from 16 to 24 hours after retrieval, depending on how recently the token cache has been refreshed. For a full description of this operation, please refer to the REFERENCE DOCUMENTATION tab.
The following snippet demonstrates a cURL request to the authentication endpoint:
curl -u ": " --data "grant_type=client_credentials&audience=https://api.imohealth.com" "https://api.imohealth.com/oauth/token"
A response payload to the above request would appear similar to the following:
{
"access_token": ,
"scope": "normalizeresults normalize nlp.deidentification.read nlp nlp.fhir.read normalize.enrichment.problem",
"expires_in": 86400,
"token_type": "Bearer"
}
2.4 Payload Summary
The following sections summarize the basic structure of request and response payloads for Classic normalization operations. This summary briefly describes each available payload field and its purpose in order to provide you with some initial context for when they are discussed in other portions of this guide. For an exhausitive description of each available payload field, please refer to the REFERENCE DOCUMENTATION tab.
2.4.1 Request Payload
| Description | Request Structure |
|---|---|
|
{
client_request_id,
session_id,
preferences: {
match_field_pref,
threshold,
discrepancy_check,
size,
distinct_field,
transformations: [...],
filters: [...],
use_custom_maps,
use_domain_relevance_filter,
use_semantic_match
},
requests: [
{
record_id,
domain,
input_term,
input_code,
input_code_system,
context: {
source_text,
use_count,
application_id,
facility_id,
encounter_id,
document_id,
project_id,
unit_of_measure,
order_name,
loinc_component,
loinc_property,
loinc_time,
sample_type,
loinc_scale,
loinc_method,
reaction,
severity
}
}
]
}
|
2.4.2 Response Payload
| Description | Response Structure |
|---|---|
|
{
summary: {count, error count},
request_id,
client_request_id,
session_id,
response_time,
requests: [
{
record_id,
domain,
input_code,
input_code_system,
input_term,
transformed_term,
context: {...},
response: {
match_field,
domain,
custom_mapped,
transformed_term,
explanation,
match_includes_assumptions,
error_message: [...],
items: [
{
lexical_code,
lexical_title,
default_lexical_code,
default_lexical_title,
score,
certainty,
metadata: {
mappings: {...},
flags: {...},
subdomains: [...]
},
discrepancy: {...}
}
],
loinc_parts: {...}
}
}
],
preferences: {...}
}
|
2.4.3 Response Metadata Mappings
For each lexical returned in an IMO Precision Normalize API response payload, the metadata.mappings object provides a breakdown of the clinical codes mapped to the default variant of that lexical. Each field in the mappings object corresponds to a particular code system supported by the lexical's domain and defines a child object that may contain up to two fields:
-
codes: If the code system has one or more codes mapped to the lexical, then its object defines a codes array containing one object for each mapped code from that system. If the code system has no codes mapped to the lexical, its codes array is sent blank and the
map_contextfield may supply an explanation.For example, in the followings mappings object, the snomedInternational field defines a codes array identifying a single mapped code from the SNOMED International code system:
"metadata": { "mappings": { "snomedInternational": { "codes": [ { "code": "29857009", "map_type": "Preferred primary", "mesh_code": "D002637", "relationship_type": "Same as", "title": "Chest pain" } ] }, ... -
map_context: If the code system has no codes mapped to the lexical, then its object may include a map_context field describing the reason for the lack of code mappings. For example, in the following mappings object, the icd10cm field reports that the ICD-10-CM code system had no code mappings for the lexical:
"metadata": { "mappings": { "icd10cm": { "codes": [], "map_context": "INSUFFICIENT INFORMATION" }, ...The map_context field is always excluded for code systems with at least one mapping for the lexical. If map_context is included, it will supply one of the following values:
- INSUFFICIENT INFORMATION - The lexical does not represent a specific enough clinical concept to assign a code from the system.
- NON-CODEABLE - The lexical is not codeable to the code system.
- NO MATCH - No reaction match was found in the Allergen domain.
The content supplied in each codes object depends on the applicable code system. For details on the fields available in each system's codes object, please refer to the REFERENCE DOCUMENTATION tab.
2.5 Match Field Preference
When defining a request payload, a particularly imporant consideration is the preferences.match_field_pref field, which determines the method the API will use to identify lexical matches for all normalization records suppplied in the request. Your value for this field determines whether the API performs term-based matching, code-based matching, or attempts one method before falling back to the other.
The match_field_pref field can be set to any of the following values:
-
input_term - The API will perform term-based matching only. For this option, each normalization record must include the
input_termfield. The input_code field is ignored for lexical matching. For details on how the API performs term-based matching, see 4 Term-Based Matching below. -
input_code - The API will perform code-based matching only. For this option, each normalization record must include the
input_codeandinput_code_systemfields. The input_term field is ignored for lexical matching. For details on how the API performs code-based matching, see 3 Code-Based Matching below. -
input_term_first - The API will first attempt term-based matching. If no term-based lexical matches within the specified
thresholdare found or if the request did not include a valid input term, then the API will attempt code-based matching. If even one term-based match within the threshold was found, then code-based matching is skipped.For this option, each normalization record must include either:
input_term; bothinput_code and input_code_system; or all three fields.This is the default value if match_field_pref is excluded from the request.
-
input_code_first - The API will first attempt code-based matching. If no code-based lexical match is found or if the request did not include a valid input code and system, then the API will attempt term-based matching. If a code-based match was found, then term-based matching is skipped.
For this option, each normalization record must include either:
input_term; bothinput_code and input_code_system; or all three fields.
The match_field_pref field is a request-level preference, meaning one of the above values applies to all normalization records in the entire request. However, by using one of the "first" approaches (e.g. input_term_first), you have the flexibility to define payloads that include a mix of normalization records intended for either matching method.
When using a "first" value, if a given normalization record in your payload includes only the input_term field or only the input_code and input_code_system fields, then for that record the API will attempt only the one possible normalization method and skip the other. If instead you supply all three of the input_term, input_code, and input_system fields for a normalization record, then a "first" approach allows the API to use either the term or code as a backup for normalization if one of the supplied input values turns out to be invalid.
When supplying all three of the input_term, input_code, and input_system fields, keep in mind that the domain value supplied for the normalization record applies only when term-based matching and should be specified as appropriate for your input_term. Code-based matching may return a lexical from any domain, regardless of the specified domain.
3 Code-Based Matching
In the IMO Precision Normalize API, code-based matching attempts to normalize a supplied clinical code by returning the one IMO lexical that best represents its clinical concept. Code-based matching is commonly used to confirm the correct title of a clinical concept for which you possess the code or when you want to view corresponding codes from alternate clinical code systems.
In order to perform code-based matching, in your request payload, a normalization record must specify both an input_code and input_code_system. The response will return a single lexical mapped to the supplied code, providing both a normalized title for the clinical concept and a list of all other clinical codes mapped to that lexical from every applicable code system. When code-based matching, the API can return a lexical from any domain, regardless of the endpoint or the normalization record's domain preference.
The following sections describe code-based matching in detail:
- 3.1 Code-Based Matching Logic
- 3.2 Code-Based Matching Request Payload
- 3.3 Code-Based matching Response Payload
3.1 Code-Based Matching Logic
When performing code-based matching for a normalization record, the API performs the following steps:
-
Validate the Input: The API confirms that the normalization record supplied a valid
input_codeandinput_code_system. The input_code_system must be one of the following values representing a single industry standard clinical code system, and the input code should be a single alphanumeric identifier from the specified system:ICD-10-CM | ICD-9-CM | SNOMED CT | ICD-10-PCS | LOINC | CPT | HCPCS | RXNORM | NDC | CVX | UMLS | IMO
For example, if your input_code_system was "ICD-10-CM", you might specify an input_code of "R07.9", which represents the clinical concept "Chest pain, unspecified".
Note: For the "IMO" input code system, the input_code value can be the Lexical Code for any IMO lexical. The API will attempt to identify and return the indicated lexical. Lexicals codes can be found in IMO Precision Normalize API response payloads and a number of other IMO tools.
-
Match a Clinical Code: The API attempts to find an exact match between the supplied
input_codeand IMO's library of clinical codes. The supplied code must belong to the specifiedinput_code_systemand it must exactly match a formal identifier from that system. The match is not case-sensitive.The API will parse out any preceding or trailing space included in the input_code field, but otherwise the supplied string is matched as-is. A single additional or misentered character will prevent matching. For example, " r07.9 " would result in a valid code match, but any of the following values would not: "r 07.9", "-r07.9", "1. r07.9", "r7.9", "r07.90"
-
Choose the best Lexical: The API returns the one lexical mapped to the matched code that has been identified by IMO's subject matter experts as best representing the same clinical concept. In the response payload, the lexical match is assigned a
scoreof 1.In general, this will be a lexical whose relationship to the code has a Map Type of "Preferred Primary" and a Relationship Type of "Same as". This may be a lexical from any domain, regardless of the
domainvalue supplied in the request.
Exception - Retired Code Matching
IMO Health takes great care to update our clinical code library to account for newly added and retired codes. When a Problem domain clinical code is retired, IMO Health maps the retired code to its closest active equivalent. If a normalization record specifies a retired Problem domain code, the response will return the lexical associated with the closest active equivalent code. When this occurs, the response payload will not appear any different, but you will notice that the mappings object does not return the actual input_code supplied in the request, but instead its active equivalent. Response payloads never return retired clinical codes.
Retired code matching is only applicable to the Problem domain. A normalization record that specifies a retired code from any system unsupported by the Problem domain will fail to match a lexical.
3.2 Code-Based Matching Request Payload
The following example request payload performs code-based matching for two normalizations records, respectively seeking normalization for the ICD-10-CM code "R07.9" and the CPT code "71047":
{
"client_request_id": "A5B2C1D9",
"preferences": {
"match_field_pref": "input_code"
},
"requests": [
{
"record_id": "ABCD1234",
"domain": "Problem",
"input_code": "R07.9",
"input_code_system": "ICD-10-CM"
},
{
"record_id": "4321ZYXW",
"domain": "Problem",
"input_code": "71047",
"input_code_system": "CPT"
}
]
}
Each normalization record included the mandatory input_code, input_code_system, and domain fields. The domain field must always be included with a valid value, even though it is ignored for code-based matching. The examples above specify a domain value of "Problem", but a code-based matching result is the same regardless of the specified domain.
The preferences.match_field_pref value of "input_code" indicates that the API should attempt only code-based matching for this request's normalization records. For code-based matching, all other preferences fields and the context object are ignored for purposes of lexical matching, and so were excluded from this payload. We could alternatively have opted to supply a context object in order to include the the optional record tracking fields (use_count, application_id, facility_id, encounter_id, document_id, project_id).
The input_term field is not used for code-based matching and so was excluded. Alternatively, if we were using a match_field_pref of "input_code_first", we could have opted to supply an input_term in order to use term-based matching as a backup. When using "input_code_first", keep in mind that the domain value still applies when term-based matching and should specify a value appropriate to the supplied input_term.
3.3 Code-Based Matching Response Payload
The following is a response payload for the code-based matching request defined above:
Code-Based Matching Response
{
"summary": {
"count": 2,
"error_count": 0
},
"request_id": "67676ab7-ab6a-7b67-67a6-b7a6b7ab6aba",
"client_request_id": "A5B2C1D9",
"response_time": 7,
"requests": [
{
"record_id": "ABCD1234",
"domain": "Problem",
"input_code": "R07.9",
"input_code_system": "ICD-10-CM",
"transformed_term": "",
"response": {
"match_field": "input_code",
"domain": "problem",
"custom_mapped": false,
"transformed_term": "",
"explanation": "",
"items": [
{
"lexical_code": "732485",
"lexical_title": "Chest pain, unspecified",
"default_lexical_code": "85191",
"default_lexical_title": "Chest pain",
"score": 1,
"certainty": "",
"metadata": {
"mappings": {
"icd10cm": {
"codes": [
{
"code": "R07.9",
"code_metadata": {
"ccsr": [
{
"ccsr_category": "CIR012",
"ccsr_description": "Nonspecific chest pain"
}
],
"hcc": []
},
"map_type": "Preferred primary",
"relationship_type": "Same as",
"title": "Chest pain, unspecified"
}
]
},
"icd9cm": {
"codes": [
{
"code": "786.50",
"map_type": "Preferred primary",
"title": "Chest pain, unspecified"
}
]
},
"snomedInternational": {
"codes": [
{
"code": "29857009",
"map_type": "Preferred primary",
"mesh_code": "D002637",
"relationship_type": "Same as",
"title": "Chest pain"
}
]
},
"umls": {
"codes": [
{
"code": "C0008031",
"title": "Chest Pain"
}
]
}
},
"flags": {
"age_indicator": "",
"is_icd10cm_refinable": true,
"sex_indicator": ""
}
}
}
]
}
},
{
"record_id": "4321ZYXW",
"domain": "Problem",
"input_code": "71047",
"input_code_system": "CPT",
"transformed_term": "",
"response": {
"match_field": "input_code",
"domain": "procedure",
"custom_mapped": false,
"transformed_term": "",
"explanation": "",
"items": [
{
"lexical_code": "1064351",
"lexical_title": "X-ray of chest, three views",
"default_lexical_code": "1064351",
"default_lexical_title": "X-ray of chest, three views",
"score": 1,
"certainty": "",
"metadata": {
"mappings": {
"cpt": {
"codes": [
{
"code": "71047",
"long_title": "Radiologic examination, chest; 3 views",
"map_type": "Preferred primary",
"title": "X-ray exam chest 3 views"
}
]
},
"hcpcs": {
"codes": []
},
"icd10pcs": {
"codes": [
{
"code": "BW03ZZZ",
"code_metadata": {
"ccsr": [
{
"ccsr_category": "IMG009",
"ccsr_description": "Plain radiography"
}
]
},
"long_title": "Plain radiography of chest",
"map_type": "Preferred primary",
"relationship_group": "0",
"title": "Plain radiography of chest"
}
]
},
"loinc": {
"codes": [
{
"code": "36298-8",
"map_type": "Preferred primary",
"title": "Views 3:Find:Pt:Chest:Doc:XR"
}
]
},
"snomedInternational": {
"codes": [
{
"code": "399208008",
"map_type": "Preferred primary",
"mesh_code": "",
"title": "Plain X-ray of chest"
}
]
},
"umls": {
"codes": [
{
"code": "C0039985",
"title": "Plain chest X-ray"
},
{
"code": "C1524624",
"title": "Views 3:Find:Pt:Chest:Doc:XR"
},
{
"code": "C2457026",
"title": "Plain Radiography of Chest"
}
]
}
},
"flags": {
"is_chargeable": false,
"is_historical": true,
"is_orderable": true,
"is_performable": true,
"is_resultable": false,
"sex_indicator": ""
}
}
}
]
}
}
],
"preferences": {
"match_field_pref": "input_code",
"size": 3
}
}
In the response, the requests array returned one object corresponding to each normalization record supplied in the request. In each of these objects, the items array includes one child object describing the lexical that was matched to the supplied input_code. The items.default_lexical_title states the IMO normalized text for the clinical concept represented by the input_code, and the items.metadata.mappings array lists each of the clinical codes mapped to the lexical from all applicable code systems.
For the first record, the API identified the input code of "R07.9" as a valid identifier for the input code system of "ICD-10-CM", and then returned lexical "732485 - Chest pain, unspecified" from the Problem domain as the best representation of the applicable clinical concept.
For the second record, the API identified the input code of "71047" as a valid identifier for the input code system of "CPT", and then returned lexical "1064351 - X-ray of chest, three views" from the Procedure domain as the best representation of the applicable clinical concept.
4 Term-Based Matching
In the IMO Precision Normalize API, term-based matching attempts to normalize a supplied input term by returning one or more IMO lexicals that best match the clinical intent of the input. Term-based matching is most commonly used to translate a medical term found in patient data to a standardized lexical title and to identify the codes associated with the corresponding clinical concept.
In order to perform term-based matching, in your request payload, a normalization record must specify an input_term and may optionally include additional context that may assist in finding optimal lexical matches. The response will return one or more lexicals matched with varying degrees of confidence to the supplied term, each providing a normalized title for a clinical concept and a list of all clinical codes mapped to that lexical from every applicable code system. The domain specified for each normalization record determines which lexicals the API can return.
When performing term-based matching for a normalization record, the API considers the following factors:
- 4.1 Request Input for Term-Based Matching
- 4.2 Auto Domain resolution
- 4.3 Custom Lexical Mappings
- 4.4 Input Term Transformation
- 4.5 Input Term Matching
- 4.6 Lab Context Analysis
- 4.7 AI Context Analysis
- 4.8 USCDI Filters
- 4.9 Distinct Field Check
- 4.10 Candidate Lexical Ranking
- 4.11 Size and Threshold Limits
- 4.12 Discrepancy Checking
4.1 Request Input for Term-Based Matching
The following fields from the request payload are relevant to term-based matching:
-
preferences: This request-level object defines a number of optional term-matching preferences applicable to all normalization records included in the request payload:
- size: Specifies the maximum quantity of lexical matches that should be returned for each normalization record. See 4.11 Size and Threshold Limits below.
- threshold: Specifies a minimum score that a lexical match must have in order to be returned in the result. See 4.11 Size and Threshold Limits below.
- discrepancy_check: Determines whether the response should report whether there is a mismatch between any supplied
input_codeand the highest scoring lexical returned for the normalization record. See 4.12 Discrepancy Checking below. - distinct_field: Determines whether the response is permitted to return multiple lexicals linked to the same default variant. See 4.9 Distinct Field Check below.
- transformations: Defines one or more search and replace operations that should be performed on each input_term before attempting to match lexicals. See 4.4 Input Term Transformation below.
- filters: Defines USCDI filter criteria that limits which lexicals can be returned in the results. See 4.8 USCDI Filters below.
- use_custom_maps: Determines whether the API compares the supplied input with your organization's predefined custom lexical mappings. See 4.3 Custom Lexical Mappings below.
- use_domain_relevance_filter: When matching Problem domain lexicals, this preference determines whether the API should discard any input term deemed irrelevant to the Problem domain. See 4.5 Input Term Matching below.
- use_semantic_match: When matching Problem domain lexicals, this preference determines whether the API can match candidate lexicals using semantic variations of the
input_termand rank candidate lexicals based on their semantic relevance to the input term. See 4.5 Input Term Matching and 4.10 Candidate Lexical Ranking below.
-
input_term: For each normalization record, this field specifies the title of a medical term that you want to normalize to a lexical. This is required for term-based matching. For guidelines on populating this field, see 4.1.1 Input Term Values below.
-
domain: For each normalization record, this field specifies the domain from which the API can match lexicals to the
input_term. This is required for term-based matching.The domain field may specify either a single IMO domain (Problem, Procedure, Medication, Lab, Allergen, Anatomical Site) or a value of "Auto". If set to "Auto", the API attempts to match lexicals from any of several permitted domains, as described in 4.2 Auto Domain Resolution below.
-
context: For each normalization record, this object may supply additional context used to match lexicals to the
input_term. The fields you include for a normalization record may vary depending on your purpose:-
AI Enhancement: If AI Enhancement is enabled for your Client ID, the
source_textfield is used for limited AI context analysis and term transformation. For guidelines on populating this field, see 4.1.2 Source Text Values below. For details on how this field is used, see 4.4 Input Term Transformation and 4.7 AI Context Analysis below. -
Lab Domain: For the Lab domain, the
unit_of_measure,order_name,loinc_component,loinc_property,loinc_time,sample_type,loinc_scale, andloinc_methodfields are used to identify lexical matches. See 4.3 Custom Lexical Mappings and 4.6 Lab Context Analysis below.
-
4.1.1 Input Term Values
The input_term field should describe a discrete medical problem, complaint, symptom, or finding. It should refer to a single problem "entity" with no extraneous words or context. When supplying an input term, please keep in mind the following considerations:
-
You may include any number of words up to a total of 500 characters.
-
Exclude special characters.
-
Avoid acronyms and abbreviations when possible.
-
Avoid sending vague terms like "Vaccination", "Follow-up", "General health", and "Mood".
-
Split conjunctive terms into separate normalization records.
For example, "Right knee effusion and chronic bursitis" should be split into two separate input terms: "right knee effusion" and "chronic bursitis".
-
For Lab domain lexical matching, the input term should ideally specify a LOINC standard long common name or short common name. If these are unavailable, the input term may instead describe a particular test or observation.
-
For Medication domain lexical matching, the input term should ideally specify a combination of RxNorm term types (e.g. brand, ingredient, strength, dose, etc).
Good Input Term examples:
- Chest pain
- Muscular pain in legs
- Diabetes mellitus type 2 with CKD
- Constipation due to pain medication
- Hyperlipidemia
- Lung nodule
- Headaches
Bad Input Term examples:
- I discussed the various treatment options including the option to do nothing at all. I reviewed the side effects of all medications prescribed by me as listed in the PDR and package insert.
- Family History
- Pre-Surgical Preparation
- 1. Left ear fullness and presumed Sudden Hearing Loss in Left Ear:
- 1. Increase dose of BuSpar to 10 mg TID
- Oral Health
4.1.2 Source Text Values
In the context object, the source_text field may supply the sentence or surrounding text in which the input_term was found. When supplying source text, please keep in mind the following considerations:
-
Include Relevant Context Only
- Include only the sentences directly related to the input term.
- Include any modifiers specifying chronicity, laterality, severity, or treatment details.
- Include any assertion status applicable to the input term (i.e. present, negated, uncertain).
- Avoid any billing details, timestamps, or other boilerplate text.
- Avoid large, unrelated narrative text blocks.
-
Pre-process for Quality
- Try use any applicable units consistently.
- Try to use consistent whitespace guidelines for word or paragraph separation.
- Remove any junk or irrelevant phrases.
- De-identify any protected health information.
- Chunk long stretches of text into structured sections.
-
Limit Context Size: To help reduce context rot, the optimal size for the source text should be between 500 - 1,000 characters or < 1,000 tokens.
-
Escape Sequences: For complex textual input requiring multiple lines, use the following escape sequences as needed:
- \n for newline
- \t for tab
- \r for carriage return
- \\ for backslash
Good Source Text examples
- Example 1
- Input term: Musculoskeletal pain
- Context: Sharp pain likely musculoskeletal, possibly related to weightlifting. - Modify exercise routine by reducing upper extremity weightlifting and incorporating swimming and walking.
- Example 2
- Input term: Alzheimer's disease
- Context: Moderate Alzheimer's and dementia confirmed. Late onset Alzheimer's noted.
- Example 3
- Input term: Excessive facial hair growth
- Context: Likely related to PCOS and hormonal imbalance - Prescribe Spironolactone 50 mg twice daily for six months, monitor response and adjust dose if necessary.
Bad Source Text examples
- Example 1
- Input term: Dyspnea
- Context: Slight elevation noted, possibly related to dehydration or fasting. - Repeat hemoglobin test in 6 weeks.
- Example 2
- Input term: Abdominal Pain
- Context: The chest discomfort could be related to a number of conditions, including heart disease. The presence of a systolic murmur is concerning and requires further investigation.
4.2 Auto Domain Resolution
When a normalization record's domain is set to "Auto", the API will perform the entire term-based matching process separately for each of the Problem, Procedure, Medication, and Lab domains according to all normal factors. If the normalization record included a valid input_code_system, then this process excludes any domains that do not support the specified system (see 1.2.3 Domain). The Allergen and Anatomical Site domains are always excluded for auto domain resolution.
After completing term-based matching in each applicable domain, the response identifies the one domain in which the highest scoring lexical match was found and then returns only lexicals from that one domain within the scope of all other normal term-based matching factors. All lexicals returned for a given normalization record always belong to the same domain.
For example, consider a situation in which a normalization record supplies a domain of "Auto" and an input_code_system of "SNOMED US", which is only supported by the Problem and Procedure domains. In the Problem domain, the API identifies 3 candidate lexical matches with scores of 0.98, 0.8. and 0.6. In the Procedure domain, the API identifies 1 candidate lexical match with a score of 0.99. In the response, the API returns the 1 lexical match from the Procedure domain and discards all Problem domain candidates.
4.3 Custom Lexical Mappings
If the request's preferences.use_custom_maps field is set to "true" or excluded, the API begins the term-based matching process for each normalization record by checking for a match between the supplied input and your organization's predefined custom lexical mappings. Custom lexical mappings are defined from IMO Studio using the Manage Terms interface. For most domains, each custom lexical mapping defines an equivalency between a custom term description and a single IMO lexical. For Lab domain lexicals, each custom lexical mapping is defined for a specific combination of term description, order name, and unit of measure.
To check for custom lexical mappings, the API attempts to find an exact match between the supplied input_term value and a term description used for one of your custom lexical mappings. The API will parse out any preceding or trailing space included in the input_term field, but otherwise the value is matched as-is. A single additional or misentered character will prevent matching. For example, for a custom mapping term description of "bad back", an input term of " bad back " would be a valid match, but any of the following values would not: "b ad back", "-bad back", "1. bad back", "bad back ache". When checking Lab domain lexicals, the custom lexical mapping must match all three of the included input_term, context.order_name, and context.unit_of_measure fields.
If a match is found with a custom lexical mapping, the term-based matching process halts here and returns only the one lexical identified by the mapping. In the response payload, the lexical match is assigned a score of 1 and the response.custom_mapped field returns a value of "true". If no match is found with a custom lexical mapping, term-based matching proceeds using the other factors described in this guide and the response.custom_mapped field returns a value of "false".
When applicable, the check for custom lexical mappings occurs as the very first action of the term-based matching process using the exact value supplied in the input_term field, before any input term transformations are applied.
4.4 Input Term Transformation
Term-based matching may perform any of the following actions to transform each normalization record's supplied input_term. When multiple transformations are applicable, these actions are applied in the following sequence:
When an input term is transformed for any of these reasons, in the response, the normalization record's transformed_term field reports the final state of the term, which may have been arrived at after performing multiple transformation actions. The response.explanation field will report any decisions taken by the API to transform the term due to spelling mistakes or AI term transformation, but this field does not describe preference transformations.
4.4.1 Preference Transformations
...
"preferences": {
"transformations": [
{
"type": "string_replace",
"location": "*",
"from": "poc",
"to": "point of care",
"case_sensitive": false
},
{
"from": ["(NORTH)", "1. ", "2. "],
"to": ""
}
],
...
The request's preferences.transformations array may include one or more objects defining search and replace operations that should be performed on each normalization record's supplied input term before attempting to match lexicals. Preference transformations are often used to remove or correct expected errors and extraneous content from your input terms, such as department names or unexpanded acronyms. If these operations result in changes to the input term, then lexical matching proceeds using the revised input term text. If no changes are made to the input term, then lexical matching proceeds using the initially supplied input term text.
In each transformations object, the following fields define the parameters of a single search and replace operation:
-
type: One of the following values determining how many strings to search for:
- string_replace - Search for a single string in the input term. The from value must define a single string that will be transformed to the to value.
- multiple_string_replace - Search for multiple strings in the input term. The from value must define an array of one or more strings, any and all of which will be transformed to the to value. If type is excluded, this is the default value.
-
location: One of the following values determining the portion of the input term that will be searched for any of the from strings:
- beginning - Search only at the beginning of the input term.
- end - Search only at the end of the input term.
- * - Search anywhere in the input term. This option may identify multiple string matches in the input term. If location is excluded, this is the default value.
-
from: One or more strings to find in the input term. If type is set to "string_replace", this should be a single string value. If type is set to "multiple_string_replace", this should be an array of one or more strings.
Only whole string matching is supported. For example, "blue" does not match "blueish". When the search location is "beginning" or "end", the API may find a match by parsing out any preceding or trailing space in the input term, but otherwise the beginning/end of the input term must match a from string exactly. When the search location is "*", the API may also find matches by parsing out any extraneous special characters not included in the from strings.
-
to: The replacement string. Text matched to any of the from strings in the designated location will be replaced with this to string. Setting the to field to a blank string ("") deletes the matched text. If to is excluded, this is set to a blank string by default.
-
case_sensitive: Determines whether from strings are matched to input term text on a case-sensitive basis. If set to "false", the search is not case-sensitive, meaning "blue" matches "Blue". If set to "true, the search is case-sensitive, meaning "blue" will not match "Blue". Regardless of this setting, the replacement to string is always applied using the entered case. If case_sensitive is excluded, this is set to "false" by default.
When multiple transformations objects are included, all specified operations are performed in order from top to bottom, with each subsequent transformation taking as input the result of the the previous transformation. For example, consider an initial input term of "quick brown fox". If you define two transformations objects, with the topmost changing "brown" to "red" and the bottom changing "red" to "purple", the final transformed term will be "quick purple fox".
4.4.2 Spelling Mistakes
Before attempting to match lexicals to a normalization record, the API will correct any common spelling mistakes identified in the input term. For example, a value of "chast pain" will be corrected to "chest pain".
4.4.3 AI Term Transformation
For the Classic endpoint, AI term transformation is only available if AI Enhancement is enabled for your Client ID. If enabled, AI term transformation is only used as a backup failover when the input term cannot be matched to any lexical with a high degree of confidence.
When applicable, the API can choose to expand a low-scoring pool of candidate lexicals by using AI models to revise the input term to a more relevant medical term and attempting to match lexicals against that term. For example, an input term of "busted clavicle" would not in itself match well to any IMO lexical, but an AI model would be able to infer that this phrase may refer to the medical term "Clavicle Fracture" and so transform it. When a normalization record includes the source_text field, the AI models can also use this context to help decide which clinical concept was implied by the input term.
4.5 Input Term Matching
To build a list of candidate lexical matches with a normalization record's input term, a major component of the term-based matching process involves comparing the text of the supplied input_term (or transformed input term) to IMO lexical Titles. This process may involve several techniques:
-
Simple text matching: The API can look for text matches between a lexical's title and either the entire text of the input term or individual words within it. This process is assisted by lookups to internal libraries that help map common input text patterns to lexical titles, such as certain acronyms (e.g. "ADD" interpreted as "Attention deficit disorder") and numeric representations (e.g. "II" interpreted as "2").
For Lab domain lexical matching, the input term is also compared with LOINC standard long common names and short common names, which the API can map to IMO lexicals.
-
Semantic matching: For Problem domain lexical matching only, if the
use_semantic_matchpreference is set to "true", the API can find matches with lexical titles by trying semantic variations of the input term. This technique does not literally transform the input term, but instead attempts to match variations of the input text using different words for the same concepts and excluding potentially irrelevant noise. For example, an input term of "pelvic rim fracture" could be matched to a lexical titled "Pelvic ring fracture".If the
use_semantic_matchpreference is set to "false", lexical matches are more restricted to the exact wording of the input term. For example, if set to "false", the sample "pelvic rim fracture" input term might be matched to a conceptually unrelated lexical like "Fracture of rim of glenoid fossa". By default, use_semantic_match is set to "false", which improves performance. -
Domain Relevance Filter: For Problem domain lexical matching only, if the
use_domain_relevance_filterpreference is set to "true", the API will fail return any lexicals if the input term is deemed irrelevant to the clinical domain. This process is sometimes referred to as "junk detection" and prevents the API from returning lexicals that may share superficial textual similarities with the input term, but are otherwise unrelated. For example, if a normalization record is erroneously sent with an input term of "misc", the domain relevance filter prevents the API from returning a lexical such as "Miscellaneous certificate requested".If the input term is deemed irrelevant by the domain relevance filter, the
response.explanationfield will report the following value:"No identifiable problem domain clinical concept in input term - returning no results."
If the
use_domain_relevance_filterpreference is set to "false", the API is permitted to return very low confidence lexical matches like the one described above based on superficial textual similarities. By default, use_domain_relevance_filter is set to "false".
4.6 Lab Context Analysis
...
"context": {
"order_name": "Anemia Profile A",
"unit_of_measure": "%",
"loinc_component": "Eosinophils",
"loinc_property": "NFr",
"loinc_time": "Pt",
"sample_type": "Bld",
"loinc_scale": "Qn",
"loinc_method": "Automated count"
}
...
A normalization record's context object may include a number of fields used specifically for identifying and ranking Lab domain lexicals as potential matches. When matching Lab domain lexicals, the input_term is typically interpreted as all or part of a LOINC long common name, a LOINC short name, or a generic reference to a particular test or observation. When an exact lexical match cannot be identified with the input term, the API can also evaluate lexical matches based on their association with each of the supplied Lab-relevant context fields.
Two of the Lab-relevant context fields are used for comparison with compendium entries (unit_of_measure, order_name), while the others each represent part of a LOINC fully specifed name (FSN) (loinc_component, loinc_property, loinc_time, sample_type, loinc_scale, loinc_method). The API identifies and ranks candidate lexicals based on their association with each of the supplied context values, with more field matches corresponding to a higher lexical ranking. These context fields are ignored when evaluating lexicals from any domain other than Lab.
The following are individual descriptions for each of the Lab-relevant context fields:
- unit_of_measure: One or more units of measurement used to report quantitative results. For example, "mg/dL", "mmol/L", "%", and "#/mm3". These units translate to what LOINC refers to as a "Property" (e.g. "mass concentration", "#/volume").
- order_name: The name of the lab order that produced the result. This is sometimes called a "request" and for data in HL7 messages is found in the OBR segment. An order may be a panel that produces many results (e.g. a basic metabolic panel), but in cases where a lab order has only one result, the order name and result are the same.
- loinc_component: The "Component/Analyte" part of the LOINC code that you believe best maps to the input term.
- loinc_property: The "Property" part of the LOINC code that you believe best maps to the input term.
- loinc_time: The "Time Aspect" part of the LOINC code that you believe best maps to the input term.
- sample_type: The "System" part of the LOINC code that you believe best maps to the input term. This identifies a type of sample or specimen.
- loinc_scale: The "Scale" part of the LOINC code that you believe best maps to the input term.
- loinc_method: The "Method" part of the LOINC code that you believe best maps to the input term.
4.6.1 LOINC FSN Part Guidelines
When supplying LOINC fully specified name (FSN) parts in your context object, take care to specify only official terms that correspond exactly to a Part Name (e.g. Ser/Plas), Part Display Name (e.g. Serum or Plasma), or Short Name (e.g. SerPI) documented in the published LOINC part hierarchy. Any extraneous noise or unofficial terminology supplied in these fields could confuse the normalization result. If you are uncertain of the LOINC part names you possess, it is usually better to supply them as input_term text instead. Input term matching has much more flexibility than the exact pattern matching analysis used by the API for LOINC parts.
In the context object, you may choose to include fields for some or all parts of a complete LOINC FSN. You should ideally include as many parts as you possess with full confidence, as this usually results in a more reliable match. If you include only some LOINC parts, the API may choose to assume the remaining parts based on association frequency mappings derived by IMO's subject matter experts. If such assumptions were involved in a lexical match, the response.match_includes_assumptions field will return a value of "true".
4.7 AI Context Analysis
...
"context": {
"source_text": "Moderate Alzheimer's and dementia confirmed. Late onset Alzheimer's noted"
}
...
For the Classic endpoint, AI context analyis is only available if AI Enhancement is enabled for your Client ID. If enabled, AI analysis is used as a backup failover when the input term alone cannot be matched to any lexical with a high degree of confidence. When applicable, the API analyzes the context.source_text field to help interpret the input term and better understand its clinical intent. The understanding derived from this analysis enables the API to identify and rank lexicals as more optimal matches for the input term.
4.8 USCDI Filters
...
"preferences": {
"filters": [
{
"field": "uscdi.profiles.valueset_oid",
"operator": "eq",
"value": "2.16.840.1.113762.1.4.1186.8"
},
{
"field": "uscdi.profiles.data_class",
"operator": "eq",
"value": "Medications"
}
],
...
The request's preferences.filters array may include one or more objects each defining a filter criterion for USCDI code mappings that limits which lexicals can be returned in the results. When USCDI filter criteria is defined for a request, a lexical can only be returned if it is mapped to a USCDI code that meets all supplied criteria. USCDI filters can only be defined if your organization has confirmed your USCDI licensing with IMO Health, as described in 2.1.2 USCDI Access. If you include the filters array without confirming your licensing, the response will return an error.
A maximum of 4 filter objects may be included in the filters array, with each object typically filtering on a different USCDI field. Multiple filter objects are applied as AND statements, meaning a lexical will only be returned if it matches all criteria defined in every object.
In each filters object, the following fields define the parameters of a single filter criterion:
-
field: The USCDI field for which you want to define a filter criterion. This must be one of the following values:
uscdi.profiles.valueset_oid | uscdi.profiles.hrsn_domain | uscdi.profiles.data_element | uscdi.profiles.data_class
-
operator: The comparison operator to apply to the value for the applicable field. Currently, only "eq" (equals) is supported, meaning the field must exactly match the value.
-
value: A single, standard USCDI value for the specified field. The supplied value must correspond exactly to a supported field value documented in the official USCDI specification, including casing.
For the uscdi.profiles.valueset_oid field, only the following values are supported:
2.16.840.1.113762.1.4.1186.8 | 2.16.840.1.113762.1.4.1186.8 | 2.16.840.1.113883.4.642.3.208 | 2.16.840.1.113883.4.642.40.2.48.8 | 2.16.840.1.113883.4.642.40.2.48.21 | 2.16. | 40.1.113883.4.642.40.2.48.21 | 2.16.840.1.113883.4.642.40.2.48.26 | 2.16.840.1.113883.4.642.40.2.48.22 | 2.16.840.1.113883.4.642.40.2.48.24 | 2.16.840.1.113762.1.4. | 247.146 | 2.16.840.1.113762.1.4.1247.83 | 2.16.840.1.113762.1.4.1247.242 | 2.16.840.1.113762.1.4.1247.157 | 2.16.840.1.113762.1.4.1247.3 | 2.16.840.1.113762.1.4.1247.23 | 2.16.840.1.113762.1.4.1010.6 | 2.16.840.1.113762.1.4.1186.8 | 2.16.840.1.113883.4.642.3.232
4.9 Distinct Field Check
The request's preferences.distinct_field field can be used to limit the results for each normalization record to only one match per default lexical. In other words, this preferences determines whether a normalize record can return multiple lexicals linked to the same default_lexical_code.
In any response, the items array for each normalization record lists one or more objects representing lexicals matched to the input. Each of these objects returns unique identifiers for both the lexical that directly matched the input (items.lexical_code) as well as its default variant (items.default_lexical_code). The distinct_field preference enables you to specify which of these fields should be used to determine whether a given lexical match is unique, and so filter out any "duplicates".
The distinct_field preference can be set to either of the following values:
-
lexical_code - The API uses the lexical_code field to determine whether a candidate lexical match is unique. This option effectively does not filter candidate lexicals at all and simply allows the API to return lexicals regardless of their linked default_lexical_code. This means that a normalization record can return multiple lexical matches linked to the same default_lexical_code.
This is the default value if distinct_field is excluded from the request.
-
default_lexical_code - The API uses the default_lexical_code field to determine whether a candidate lexical match is unique. When multiple lexicals matches are linked to the same default_lexical_code, the response can include only the highest scoring match linked to that code. The response may still include other lexical matches linked to different default_lexical_code values.
In effect, this option ensures that a normalization record will only return one matched lexical per default_lexical_code.
For example, consider a situation in which a normalization record has the following candidate lexical matches:
| Lexical Code/Lexical Title | Default Lexical Code/Default Lexical Title | Score |
|---|---|---|
| 324992 - Feeling unwell | 324999 - Feeling poorly | 0.998 |
| 324999 - Feeling poorly | 324999 - Feeling poorly | 0.887 |
| 325751 - Generally unwell | 325751 - Generally unwell | 0.856 |
If distinct_field were set to "lexical_code", then all three candidate lexicals could be returned as separate results if size and threshold limits permitted. If distinct_field were instead set to "default_lexical_code", then only lexicals 324992 and 325751 would remain candidates. Lexical 324999 could not be returned as a separate result, as it would be filtered out as a lower scoring duplicate linked to the same default lexical as another result, even though it is itself the applicable default lexical.
| distinct_field = lexical_code | distinct_field = default_lexical_code |
|---|---|
{
"lexical_code": "324992",
"lexical_title": "Feeling unwell",
"default_lexical_code": "324999",
"default_lexical_title": "Feeling poorly",
"score": 0.998,
...
},
{
"lexical_code": "324999",
"lexical_title": "Feeling poorly",
"default_lexical_code": "324999",
"default_lexical_title": "Feeling poorly",
"score": 0.887,
...
},
{
"lexical_code": "325751",
"lexical_title": "Generally unwell",
"default_lexical_code": "325751",
"default_lexical_title": "Generally unwell",
"score": 0.856,
...
} |
{
"lexical_code": "324992",
"lexical_title": "Feeling unwell",
"default_lexical_code": "324999",
"default_lexical_title": "Feeling poorly",
"score": 0.998,
...
},
{
"lexical_code": "325751",
"lexical_title": "Generally unwell",
"default_lexical_code": "325751",
"default_lexical_title": "Generally unwell",
"score": 0.856,
...
} |
4.10 Candidate Lexical Ranking
After compiling a list of candidate lexical matches for a normalization record, the API ranks all candidates with respect to one another in terms of relative confidence in the match.
If the use_semantic_match preference is set to "true", ranking involves the use of an AI model to evaluate the semantic relevance of each candidate lexical to the input_term and any supplied source_text. This process judges how well each candidate lexical represents the clinical intent of the input and then adjusts their relative rankings accordingly. Considering semantic relevance helps prevent the API from returning "false positive" lexicals that superficially resemble the input text, but not the intent. If the use_semantic_match preference is set to "false", semantic relevance is not considered for candidate lexical ranking.
At the end of this ranking process, a final score is assigned to each candidate lexical representing the degree of confidence in the lexical match to the normalization record. This score is taken into account when considering the size and threshold limits described below.
4.11 Size and Threshold Limits
To determine the finalized list of lexical matches to return for a normalization record, the API trims the ranked list of candidate lexicals established in 4.10 Candidate Lexical Ranking according to the following request preferences:
-
preferences.threshold: A decimal value defining the minimum score that a lexical match must have in order to be returned in the result. Any candidate lexicals with a score below this value are discarded.
This is a value from 0-1, specified using up to 3 decimal places. A Classic normalization request has a default threshold of 0.
-
preferences.size: An integer defining the maximum quantity of lexical matches that can be returned for each normalization record. If the quantity of candidate lexicals meeting the threshold limit is greater than the specified size, the API retains only the highest scoring lexicals up to the size limit. When the API must choose between candidate lexicals with equal scores, the response returns the more concise lexical.
A Classic normalization request has a default size of 1, but supports from 1-20.
For example, consider a situation in which a normalization record has the following ranked list of candidate lexicals:
| Rank | Candidate Lexical | Score |
|---|---|---|
| 1 | 52807 - Itch | 0.995 |
| 2 | 52808 - Itching | 0.980 |
| 3 | 52810 - Pruritus | 0.860 |
| 4 | 732950 - Pruritus, unspecified | 0.750 |
| 5 | 52876 - Mad itch | 0.640 |
Based on these candidates, below are three possible normalization responses based on different sets of request preferences:
-
threshold=0.700, size=3: The response would return three lexicals: 52807, 52808, and 52810. The threshold limit included 4 candidate lexicals, but the size limit forced the API to drop the 4th and 5th ranked candidates.
"items": [ {"lexical_code": "52807", "lexical_title": "Itch", "score": 0.995, ...}, {"lexical_code": "52808", "lexical_title": "Itching", "score": 0.980, ...}, {"lexical_code": "52810", "lexical_title": "Pruritus", "score": 0.860, ...} ] -
threshold=0.750, size=5: The response would return four lexicals: 52807, 52808, 52810, and 732950. The size limit allowed for 5 lexicals, but the threshold limit forced the API to drop the 5th ranked candidate.
"items": [ {"lexical_code": "52807", "lexical_title": "Itch", "score": 0.995, ...}, {"lexical_code": "52808", "lexical_title": "Itching", "score": 0.980, ...}, {"lexical_code": "52810", "lexical_title": "Pruritus", "score": 0.860, ...}, {"lexical_code": "732950", "lexical_title": "Pruritus, unspecified", "score": 0.750, ...} ] -
threshold=0.996, size=5: The response would return no lexicals as no candidate met the threshold limit.
"items": []
4.12 Discrepancy Checking
...
"items": [
{
"lexical_code": "85191",
...
"metadata": {
"mappings": {...},
"flags": {...}
},
"discrepancy": {
"checked": true,
"found": true,
"type": "Coding",
"message": "Input code does not match with input term result"
}
},
...
If the request's preferences.discrepancy_check field was set to "true", then in the response the first lexical returned in the items array for each normalization record includes a discrepancy object reporting whether there is a mismatch between any supplied input code and the codes mapped to that lexical. This object is only returned for the normalization record's highest scoring lexical match.
The discrepancy object includes the following fields:
-
checked: A boolean value indicating whether a discrepancy check was performed for the lexical. This is set to "true" as long as the normalization record included both an
input_codeandinput_code_system. This is set to "false" if the record was missing either of these fields, or if the lexical was returned by code-based matching. -
found: When checked is true, this is a boolean value indicating whether the API found a discrepancy between the returned lexical and the supplied
input_code. A value of "true" indicates a disrepancy, meaning the request input_code does not appear in theitems.metadata.mappingsobject for the lexical. A value of "false" indicates no discrepancy, meaning the input code does appear in the mappings object.The found field is always set to "false" if checked is "false", or if the input_code or input_code_system were invalid or excluded.
-
type: When found is "true", this is always set to "Coding". When found is false, this is always sent with an empty string.
-
message: When found is "true", this is always set to the following value:
"Input code does not match with input term result"
When found is "false", the message field may alternatively be set to any of the following values:
- Blank - Indicates that the lexical was returned by code-based matching while the
match_field_prefpreference was set to "input_code". - Discrepancy check not performed: unable to normalize input_term - An edge case that occurs when the lexical was returned by code-based matching and the
match_field_prefpreference was set to "input_code_first". - Discrepancy check not performed: Missing <field> - Indicates that the lexical was returned by term-based matching and the request was missing the identified <field>, either
input_codeorinput_code_system.
- Blank - Indicates that the lexical was returned by code-based matching while the
5 Classic Term Normalization Requests
The following sections describe the basic request-response patterns applicable to Classic term normalization for each supported domain. In each of the examples in this section, it is assumed that AI Enhancement is disabled for your Client ID, as this is the most common usage pattern. If you are using AI Enhancement, your request payloads should also include the context.source_text field, populated as described in section 4.1.2 Source Text Values.
Each of the examples in this section have preferences.match_field_pref set to "input_term", indicating that the API should attempt only term-based matching for the request's normalization records.
- 5.1 Problem Domain
- 5.2 Procedure Domain
- 5.3 Medication Domain
- 5.4 Lab Domain
- 5.5 Allergen Domain
- 5.6 Anatomical Site Domain
5.1 Problem Domain
The following sections demonstrate an example Classic term normalization request and response for the Problem domain:
5.1.1 Problem Request Payload
The following example request payload performs Problem domain term-based matching for three normalizations records, respectively seeking normalization for the terms "chast pain", "pelvic rim fracture", and the erroneously included "misc:":
{
"client_request_id": "54QR32ST",
"preferences": {
"match_field_pref": "input_term",
"use_domain_relevance_filter": true,
"use_semantic_match": true
},
"requests": [
{
"record_id": "PRLMRC01",
"domain": "Problem",
"input_term": "chast pain"
},
{
"record_id": "PRLMRC02",
"domain": "Problem",
"input_term": "pelvic rim fracture"
},
{
"record_id": "PRLMRC03",
"domain": "Problem",
"input_term": "misc:"
}
]
}
Each normalization record included the mandatory input_term and domain fields, but excluded the context object as we are not using AI Enhancement. We alternatively could have opted to include the context object in order to provide the optional record tracking fields (use_count, application_id, facility_id, encounter_id, document_id, project_id), but these are not used for lexical matching.
In the preferences object, the optional use_domain_relevance_filter and use_semantic_match preferences are set to "true", which is recommended for Problem domain normalization records to help ensure the most relevant lexical matches. Semantic matching generally produces better lexical matches and reduces normalization failures, while domain relevance filtering reduces false positives by discarding erroneous input terms that are clinically irrelevant. For larger requests, you may opt to improve performance by setting either of these values to "false". You may also want to set use_domain_relevance_filter to "false" if you want to retrieve the broadest possible lexical matches, even when the match is based on superficial textual similarities for a term that might otherwise have been discarded as "junk". Both of these preferences are ignored when matching lexicals from any domain other than Problem.
By excluding all other preferences fields, this simple request accepted the default values for the use_custom_maps (true), size (1), threshold (0), discrepancy_check (false), and distinct_field (lexical_code) preferences; performed no manual transformations; and opted not to apply USCDI filters.
The input_code and input_code_system fields are not used for term-based matching and so were excluded. Alternatively, if preferences.discrepancy_check was set to "true", we could have included an input code and system in order to perform discrepancy checking against the results.
5.1.2 Problem Response Payload
The following is a response payload for the Problem domain request defined above:
Problem Normalization Response
{
"summary": {
"count": 3,
"error_count": 0
},
"request_id": "d96431d3-43c3-63e1-e9af-94a6d0d67c2c",
"client_request_id": "54QR32ST",
"response_time": 1338,
"requests": [
{
"record_id": "PRLMRC01",
"domain": "Problem",
"input_term": "chast pain",
"transformed_term": "chest pain",
"response": {
"match_field": "input_term",
"domain": "problem",
"custom_mapped": false,
"transformed_term": "chest pain",
"explanation": "Transformed unrecognized word 'chast pain' to 'chest pain'.",
"items": [
{
"lexical_code": "85191",
"lexical_title": "Chest pain",
"default_lexical_code": "85191",
"default_lexical_title": "Chest pain",
"score": 1,
"certainty": "",
"metadata": {
"mappings": {
"icd10cm": {
"codes": [
{
"code": "R07.9",
"code_metadata": {
"ccsr": [
{
"ccsr_category": "CIR012",
"ccsr_description": "Nonspecific chest pain"
}
],
"hcc": []
},
"map_type": "Preferred primary",
"relationship_type": "Same as",
"title": "Chest pain, unspecified"
}
]
},
"icd9cm": {
"codes": [
{
"code": "786.50",
"map_type": "Preferred primary",
"title": "Chest pain, unspecified"
}
]
},
"snomedInternational": {
"codes": [
{
"code": "29857009",
"map_type": "Preferred primary",
"mesh_code": "D002637",
"relationship_type": "Same as",
"title": "Chest pain"
}
]
},
"umls": {
"codes": [
{
"code": "C0008031",
"title": "Chest Pain"
}
]
}
},
"flags": {
"age_indicator": "",
"is_icd10cm_refinable": true,
"sex_indicator": ""
}
}
}
]
}
},
{
"record_id": "PRLMRC02",
"domain": "Problem",
"input_term": "pelvic rim fracture",
"response": {
"match_field": "input_term",
"domain": "problem",
"custom_mapped": false,
"explanation": "",
"items": [
{
"lexical_code": "687371",
"lexical_title": "Pelvic ring fracture",
"default_lexical_code": "687371",
"default_lexical_title": "Pelvic ring fracture",
"score": 0.996,
"certainty": "",
"metadata": {
"mappings": {
"icd10cm": {
"codes": [
{
"code": "S32.810A",
"code_metadata": {
"ccsr": [
{
"ccsr_category": "INJ003",
"ccsr_description": "Fracture of torso, initial encounter"
}
],
"hcc": [
{
"hcc_factors": {
"community_fbdual_aged": "0.5610",
"community_fbdual_disabled": "0.5700",
"community_nondual_aged": "0.4670",
"community_nondual_disabled": "0.5610",
"community_pbdual_aged": "0.4990",
"community_pbdual_disabled": "0.5270",
"institutional": "0.0890"
},
"hcc_model_category": "402",
"hcc_version": "v28"
}
]
},
"map_type": "Preferred primary",
"relationship_type": "Broader than",
"title": "Multiple fractures of pelvis with stable disruption of pelvic ring, initial encounter for closed fracture"
}
]
},
"icd9cm": {
"codes": [
{
"code": "808.8",
"map_type": "Preferred primary",
"title": "Unspecified closed fracture of pelvis"
}
]
},
"snomedInternational": {
"codes": [
{
"code": "77493009",
"map_type": "Preferred primary",
"mesh_code": "",
"relationship_type": "Narrower than",
"title": "Fracture of pelvis"
}
]
},
"umls": {
"codes": [
{
"code": "C0149531",
"title": "Fracture of pelvis"
},
{
"code": "C2838495",
"title": "Multiple fractures of pelvis with stable disruption of pelvic ring, initial encounter for closed fracture"
}
]
}
},
"flags": {
"age_indicator": "",
"is_icd10cm_refinable": true,
"sex_indicator": ""
}
}
}
]
}
},
{
"record_id": "PRLMRC03",
"domain": "Problem",
"input_term": "misc:",
"response": {
"match_field": "input_term",
"domain": "problem",
"custom_mapped": false,
"explanation": "No identifiable problem domain clinical concept in input term - returning no results.",
"items": []
}
}
],
"preferences": {
"match_field_pref": "input_term",
"use_domain_relevance_filter": true,
"use_semantic_match": true
}
}
In the response, the requests array returned one object corresponding to each normalization record supplied in the request. In each of these objects, the items array includes one child object describing the highest scoring lexical that was matched to the supplied input_term. For each lexical, the items.default_lexical_title states the IMO normalized text for the corresponding clinical concept, and the items.metadata.mappings array lists each of the clinical codes mapped to that lexical from all applicable code systems.
For the first record, the API determined that the input term of "chast pain" was a spelling mistake, correcting it to "chest pain" and reporting the new transformed_term used for lexical matching. This resulted in a top-match with lexical "85191 - Chest Pain".
For the second record, because use_semantic_match was set to "true", the API was able to reconsider the input term "pelvic rim fracture" and interpret "rim" as "ring". This resulted in a top-match with lexical "687371 - Pelvic ring fracture".
For the third record, because use_domain_relevance_filter was set to "true", the API decided that the input term "misc:" was irrelevant to the Problem domain and discarded it as junk, returning no results.
Response payloads for Problem domain lexicals have the following following distinguishing aspect compared with other domains:
items.metadata.flags- The flags object always includes the age_indicator, is_icd10cm_refinable, and sex_indicator fields.
5.2 Procedure Domain
The following sections demonstrate an example Classic term normalization request and response for the Procedure domain:
5.2.1 Procedure Request Payload
The following example request payload performs Procedure domain term-based matching for two normalizations records, respectively seeking normalization for the terms "EGD with biopsy using cold forceps" and "endoscopy":
{
"client_request_id": "9874ABCD",
"preferences": {
"match_field_pref": "input_term"
},
"requests": [
{
"record_id": "PRCDRC01",
"domain": "Procedure",
"input_term": "EGD with biopsy using cold forceps"
},
{
"record_id": "PRCDRC02",
"domain": "Procedure",
"input_term": "endoscopy"
}
]
}
Each normalization record included the mandatory input_term and domain fields, but excluded the context object as we are not using AI Enhancement. We alternatively could have opted to include the context object in order to provide the optional record tracking fields (use_count, application_id, facility_id, encounter_id, document_id, project_id), but these are not used for lexical matching.
By excluding most preferences fields, this simple request accepted the default values for the use_custom_maps (true), size (1), threshold (0), discrepancy_check (false), and distinct_field (lexical_code) preferences; performed no manual transformations; and opted not to apply USCDI filters. The excluded use_domain_relevance_filter and use_semantic_match preferences are not applicable when matching lexicals from the Procedure domain.
The input_code and input_code_system fields are not used for term-based matching and so were excluded. Alternatively, if preferences.discrepancy_check was set to "true", we could have included an input code and system in order to perform discrepancy checking against the results.
5.2.2 Procedure Response Payload
The following is a response payload for the Procedure domain request defined above:
Procedure Normalization Response
{
"summary": {
"count": 2,
"error_count": 0
},
"request_id": "5bfcffdf-2c28-ab61-0540-77b8ad22dfbf",
"client_request_id": "9874ABCD",
"response_time": 160,
"requests": [
{
"record_id": "PRCDRC01",
"domain": "Procedure",
"input_term": "EGD with biopsy using cold forceps",
"response": {
"match_field": "input_term",
"domain": "procedure",
"custom_mapped": false,
"explanation": "",
"items": [
{
"lexical_code": "1527590739",
"lexical_title": "Esophagogastroduodenoscopy (EGD) with biopsy using cold forceps",
"default_lexical_code": "1527590739",
"default_lexical_title": "Esophagogastroduodenoscopy (EGD) with biopsy using cold forceps",
"score": 1,
"certainty": "",
"metadata": {
"mappings": {
"cpt": {
"codes": [
{
"code": "43239",
"long_title": "Esophagogastroduodenoscopy, flexible, transoral; with biopsy, single or multiple",
"map_type": "Preferred primary",
"title": "EGD biopsy single/multiple"
}
]
},
"hcpcs": {
"codes": []
},
"icd10pcs": {
"codes": []
},
"loinc": {
"codes": []
},
"snomedInternational": {
"codes": [
{
"code": "76009000",
"map_type": "Preferred primary",
"mesh_code": "D016145",
"title": "Esophagogastroduodenoscopy"
},
{
"code": "445982009",
"map_type": "Non-preferred primary",
"mesh_code": "",
"title": "Endoscopy and biopsy of upper gastrointestinal tract"
}
]
},
"umls": {
"codes": [
{
"code": "C0079304",
"title": "Esophagogastroduodenoscopy"
},
{
"code": "C2960784",
"title": "Endoscopy and biopsy of upper gastrointestinal tract"
}
]
}
},
"flags": {
"is_chargeable": false,
"is_historical": true,
"is_orderable": true,
"is_performable": true,
"is_resultable": false,
"sex_indicator": ""
},
"subdomains": [
"endoscopy procedure",
"surgical procedure"
]
}
}
]
}
},
{
"record_id": "PRCDRC02",
"domain": "Procedure",
"input_term": "endoscopy",
"response": {
"match_field": "input_term",
"domain": "procedure",
"custom_mapped": false,
"explanation": "",
"items": [
{
"lexical_code": "1002071",
"lexical_title": "Endoscopy",
"default_lexical_code": "1002071",
"default_lexical_title": "Endoscopy",
"score": 1,
"certainty": "",
"metadata": {
"mappings": {
"cpt": {
"codes": []
},
"hcpcs": {
"codes": []
},
"icd10pcs": {
"codes": []
},
"loinc": {
"codes": []
},
"snomedInternational": {
"codes": [
{
"code": "423827005",
"map_type": "Preferred primary",
"mesh_code": "D004724",
"title": "Endoscopy"
}
]
},
"umls": {
"codes": [
{
"code": "C0014245",
"title": "Endoscopy (procedure)"
},
{
"code": "C0586186",
"title": "Clinical procedure report"
},
{
"code": "C1647891",
"title": "Specimen obtained by surgical procedure"
},
{
"code": "C1831145",
"title": "Study report:Find:Pt:{Setting}:Doc:{Role}"
}
]
}
},
"flags": {
"is_chargeable": false,
"is_historical": true,
"is_orderable": true,
"is_performable": false,
"is_resultable": false,
"sex_indicator": ""
},
"subdomains": [
"endoscopy procedure"
]
}
}
]
}
}
],
"preferences": {
"match_field_pref": "input_term"
}
}
In the response, the requests array returned one object corresponding to each normalization record supplied in the request. In each of these objects, the items array includes one child object describing the highest scoring lexical that was matched to the supplied input_term. For each lexical, the items.default_lexical_title states the IMO normalized text for the corresponding clinical concept, and the items.metadata.mappings array lists each of the clinical codes mapped to that lexical from all applicable code systems.
For the first record, the input term "EGD with biopsy using cold forceps" provided a non-standardized description for a common procedure, which the API was able to normalize to the lexical "1527590739 - Esophagogastroduodenoscopy (EGD) with biopsy using cold forceps".
For the second record, the input term "endoscopy" exactly matched the lexical "1002071 - Endoscopy".
Response payloads for Procedure domain lexicals have the following distinguishing aspects compared with other domains:
-
items.metadata.flags- The flags object includes the is_chargeable, is_historical, is_orderable, is_performable, and is_resultable fields. -
items.metadata.subdomains- The subdomains array will be included if the lexical is associated with any clinically meaningful classifications (e.g. "surgical procedure", "endoscopy procedure"). This array is excluded if the no subdomains are associated with the lexical.
5.3 Medication Domain
The following sections demonstrate an example Classic term normalization request and response for the Medication domain:
5.3.1 Medication Request Payload
The following example request payload performs Medication domain term-based matching for two normalizations records, respectively seeking normalization for the terms "tylenol 325 mg oral tab" and "aspirin":
{
"client_request_id": "9874ABCD",
"preferences": {
"match_field_pref": "input_term"
},
"requests": [
{
"record_id": "MEDIRC01",
"domain": "Medication",
"input_term": "tylenol 325 mg oral tab"
},
{
"record_id": "MEDIRC02",
"domain": "Medication",
"input_term": "aspirin"
}
]
}
Each normalization record included the mandatory input_term and domain fields, but excluded the context object as we are not using AI Enhancement. We alternatively could have opted to include the context object in order to provide the optional record tracking fields (use_count, application_id, facility_id, encounter_id, document_id, project_id), but these are not used for lexical matching.
By excluding most preferences fields, this simple request accepted the default values for the use_custom_maps (true), size (1), threshold (0), discrepancy_check (false), and distinct_field (lexical_code) preferences; performed no manual transformations; and opted not to apply USCDI filters. The excluded use_domain_relevance_filter and use_semantic_match preferences are not applicable when matching lexicals from the Medication domain.
The input_code and input_code_system fields are not used for term-based matching and so were excluded. Alternatively, if preferences.discrepancy_check was set to "true", we could have included an input code and system in order to perform discrepancy checking against the results.
5.3.2 Medication Response Payload
The following is a response payload for the Medication domain request defined above:
Medication Normalization Response
{
"summary": {
"count": 2,
"error_count": 0
},
"request_id": "3a915399-e8d3-25d2-8872-f9a7f79c9604",
"client_request_id": "9874ABCD",
"response_time": 323,
"requests": [
{
"record_id": "MEDIRC01",
"domain": "Medication",
"input_term": "tylenol 325 mg oral tab",
"response": {
"match_field": "input_term",
"domain": "medication",
"custom_mapped": false,
"explanation": "",
"items": [
{
"lexical_code": "1495390380",
"lexical_title": "Acetaminophen 325 MG Oral Tablet [Tylenol]",
"default_lexical_code": "1495390380",
"default_lexical_title": "Acetaminophen 325 MG Oral Tablet [Tylenol]",
"score": 0.99,
"certainty": "",
"metadata": {
"mappings": {
"cvx": {
"codes": []
},
"fda_biosimilar": {
"bla_number": "",
"ref_product_proper_name": "",
"ref_product_proprietary_name": ""
},
"ndc": {
"codes": [
{
"ndc_code": "50580-458",
"ndc_metadata": [
{
"active_ingredients": [
{
"name": "ACETAMINOPHEN",
"strength": "325 mg/1"
}
],
"brand_name": "tylenol regular strength",
"dosage_form": "tablet, film coated",
"generic_name": "acetaminophen",
"labeler_name": "kenvue brands llc",
"pharm_class": [],
"route": [
"ORAL"
]
}
],
"ndc_package_codes": [
{
"description": "10 BLISTER PACK in 1 CARTON / 10 TABLET, FILM COATED in 1 BLISTER PACK",
"package_ndc": "50580045811"
},
{
"description": "1 BOTTLE, PLASTIC in 1 CARTON / 50 TABLET, FILM COATED in 1 BOTTLE, PLASTIC",
"package_ndc": "50580045850"
}
]
},
{
"ndc_code": "50580-496",
"ndc_metadata": [
{
"active_ingredients": [
{
"name": "ACETAMINOPHEN",
"strength": "325 mg/1"
}
],
"brand_name": "tylenol regular strength",
"dosage_form": "tablet",
"generic_name": "acetaminophen",
"labeler_name": "kenvue brands llc",
"pharm_class": [],
"route": [
"ORAL"
]
}
],
"ndc_package_codes": [
{
"description": "1 BOTTLE, PLASTIC in 1 CARTON / 100 TABLET in 1 BOTTLE, PLASTIC",
"package_ndc": "50580049660"
},
{
"description": "1 BOTTLE, PLASTIC in 1 CARTON / 100 TABLET in 1 BOTTLE, PLASTIC",
"package_ndc": "50580049698"
}
]
},
{
"ndc_code": "50580-495",
"ndc_metadata": [
{
"active_ingredients": [
{
"name": "ACETAMINOPHEN",
"strength": "325 mg/1"
}
],
"brand_name": "tylenol regular strength",
"dosage_form": "tablet",
"generic_name": "acetaminophen",
"labeler_name": "kenvue brands llc",
"pharm_class": [],
"route": [
"ORAL"
]
}
],
"ndc_package_codes": [
{
"description": "1 BOTTLE in 1 CARTON / 100 TABLET in 1 BOTTLE",
"package_ndc": "50580049501"
}
]
},
{
"ndc_code": "50580-475",
"ndc_metadata": [
{
"active_ingredients": [
{
"name": "ACETAMINOPHEN",
"strength": "325 mg/1"
}
],
"brand_name": "tylenol regular strength",
"dosage_form": "tablet, film coated",
"generic_name": "acetaminophen",
"labeler_name": "kenvue brands llc",
"pharm_class": [],
"route": [
"ORAL"
]
}
],
"ndc_package_codes": [
{
"description": "1 BOTTLE in 1 CARTON / 1000 TABLET, FILM COATED in 1 BOTTLE",
"package_ndc": "50580047510"
},
{
"description": "10 BLISTER PACK in 1 CARTON / 10 TABLET, FILM COATED in 1 BLISTER PACK",
"package_ndc": "50580047511"
},
{
"description": "1 BOTTLE in 1 CARTON / 50 TABLET, FILM COATED in 1 BOTTLE",
"package_ndc": "50580047550"
}
]
}
]
},
"rxnorm": {
"codes": [
{
"rxnorm_code": "209387",
"rxnorm_titles": [
{
"title": "tylenol regular strength 325 mg oral tablet",
"title_type": "PSN"
},
{
"title": "acetaminophen 325 mg oral tablet [tylenol]",
"title_type": "SBD"
},
{
"title": "apap 325 mg oral tablet [tylenol]",
"title_type": "SY"
},
{
"title": "tylenol 325 mg oral tablet",
"title_type": "SY"
}
]
}
]
},
"umls": {
"codes": []
}
}
}
}
]
}
},
{
"record_id": "MEDIRC02",
"domain": "Medication",
"input_term": "aspirin",
"response": {
"match_field": "input_term",
"domain": "medication",
"custom_mapped": false,
"explanation": "",
"items": [
{
"lexical_code": "125475",
"lexical_title": "aspirin",
"default_lexical_code": "125475",
"default_lexical_title": "aspirin",
"score": 1,
"certainty": "",
"metadata": {
"mappings": {
"cvx": {
"codes": []
},
"fda_biosimilar": {
"bla_number": "",
"ref_product_proper_name": "",
"ref_product_proprietary_name": ""
},
"ndc": {
"codes": [],
"map_context": "Insufficient information or not codeable."
},
"rxnorm": {
"codes": [
{
"rxnorm_code": "1191",
"rxnorm_titles": [
{
"title": "aspirin",
"title_type": "IN"
}
]
}
]
},
"umls": {
"codes": [
{
"code": "C0004057",
"title": "aspirin"
}
]
}
}
}
}
]
}
}
],
"preferences": {
"match_field_pref": "input_term"
}
}
In the response, the requests array returned one object corresponding to each normalization record supplied in the request. In each of these objects, the items array includes one child object describing the highest scoring lexical that was matched to the supplied input_term. For each lexical, the items.default_lexical_title states the IMO normalized text for the corresponding clinical concept, and the items.metadata.mappings array lists each of the clinical codes mapped to that lexical from all applicable code systems.
For the first record, the input term "tylenol 325 mg oral tab" supplied a common brand name and abbreviated dose form, which the API was able to normalize to the lexical "1495390380 - Acetaminophen 325 MG Oral Tablet [Tylenol]".
For the second record, the input term "aspirin" exactly matched lexical "125475 - aspirin".
Response payloads for Medication domain lexicals have the following distinguishing aspect compared with other domains:
items.metadata.flags- The flags field is excluded entirely for Medication domain lexicals.
5.4 Lab Domain
The following sections demonstrate an example Classic term normalization request and response for the Lab domain:
5.4.1 Lab Request Payload
The following example request payload performs Lab domain term-based matching for three normalizations records, respectively seeking normalization for the terms "Creatinine, Urine, g/24h", "eos", and "Neutrophils":
{
"client_request_id": "456POI",
"preferences": {
"match_field_pref": "input_term"
},
"requests": [
{
"record_id": "LABREC01",
"domain": "Lab",
"input_term": "Creatinine, Urine, g/24h"
},
{
"record_id": "LABREC02",
"domain": "Lab",
"input_term": "eos",
"context": {
"order_name": "Anemia Profile A",
"unit_of_measure": "%"
}
},
{
"record_id": "LABREC03",
"domain": "Lab",
"input_term": "Neutrophils",
"context": {
"loinc_component": "Neutrophils/leukocytes",
"loinc_property": "NFr",
"loinc_time": "Pt",
"sample_type": "Bld",
"loinc_scale": "Qn"
}
}
]
}
Each normalization record included the mandatory input_term field and domain fields. Two of the records included a context object supplying fields that could help the API match the input with compendium entries or parts of a LOINC fully specified name. For details on how these context fields should be populated for Lab domain term-matching, see 4.6 Lab Context Analysis above. The context objects could also have opted to include the optional record tracking fields (use_count, application_id, facility_id, encounter_id, document_id, project_id), but these are not used for lexical matching.
By excluding most preferences fields, this simple request accepted the default values for the use_custom_maps (true), size (1), threshold (0), discrepancy_check (false), and distinct_field (lexical_code) preferences; performed no manual transformations; and opted not to apply USCDI filters. The excluded use_domain_relevance_filter and use_semantic_match preferences are not applicable when matching lexicals from the Lab domain.
The input_code and input_code_system fields are not used for term-based matching and so were excluded. Alternatively, if preferences.discrepancy_check was set to "true", we could have included an input code and system in order to perform discrepancy checking against the results.
5.4.2 Lab Response Payload
The following is a response payload for the Lab domain request defined above:
Lab Normalization Response
{
"summary": {
"count": 3,
"error_count": 0
},
"request_id": "a0c0427b-ef5c-7272-21ea-881d47d114aa",
"client_request_id": "456POI",
"response_time": 104,
"requests": [
{
"record_id": "LABREC01",
"domain": "Lab",
"input_term": "Creatinine, Urine, g/24h",
"response": {
"match_field": "input_term",
"domain": "lab",
"custom_mapped": false,
"explanation": "",
"match_includes_assumptions": false,
"items": [
{
"lexical_code": "30985558",
"lexical_title": "24 hour urine creatinine measurement (mass/time)",
"default_lexical_code": "30985558",
"default_lexical_title": "24 hour urine creatinine measurement (mass/time)",
"score": 1,
"certainty": "",
"metadata": {
"mappings": {
"cpt": {
"codes": [
{
"code": "82570",
"long_title": "Creatinine; other source",
"map_type": "Preferred primary",
"title": "Assay of urine creatinine"
}
]
},
"hcpcs": {
"codes": []
},
"icd10pcs": {
"codes": []
},
"loinc": {
"codes": [
{
"code": "2162-6",
"map_type": "Preferred primary",
"title": "Creatinine:MRat:24H:Urine:Qn"
}
]
},
"snomedInternational": {
"codes": [
{
"code": "8879006",
"map_type": "Preferred primary",
"mesh_code": "",
"title": "Creatinine measurement, 24 hour urine"
}
]
},
"umls": {
"codes": [
{
"code": "C0201978",
"title": "Creatinine measurement, 24 hour urine"
},
{
"code": "C0364296",
"title": "Creatinine [Mass/time] in 24 hour Urine"
}
]
}
},
"flags": {
"sex_indicator": ""
},
"subdomains": [
"lab and anatomic pathology procedure"
]
}
}
]
}
},
{
"record_id": "LABREC02",
"domain": "Lab",
"input_term": "eos",
"context": {
"order_name": "Anemia Profile A",
"unit_of_measure": "%"
},
"response": {
"match_field": "input_term",
"domain": "lab",
"custom_mapped": false,
"explanation": "",
"match_includes_assumptions": false,
"items": [
{
"lexical_code": "44874687",
"lexical_title": "Automated blood eosinophil count as percentage of total leukocytes",
"default_lexical_code": "44874687",
"default_lexical_title": "Automated blood eosinophil count as percentage of total leukocytes",
"score": 1,
"certainty": "",
"metadata": {
"mappings": {
"cpt": {
"codes": [
{
"code": "85004",
"long_title": "Blood count; automated differential WBC count",
"map_type": "Preferred primary",
"title": "Automated diff WBC count"
},
{
"code": "85048",
"long_title": "Blood count; leukocyte (WBC), automated",
"map_type": "Other preferred primary",
"title": "Automated leukocyte count"
}
]
},
"hcpcs": {
"codes": []
},
"icd10pcs": {
"codes": []
},
"loinc": {
"codes": [
{
"code": "713-8",
"map_type": "Preferred primary",
"title": "Eosinophils/Leukocytes:NFr:Pt:Bld:Qn:Automated count"
}
]
},
"snomedInternational": {
"codes": [
{
"code": "310540006",
"map_type": "Preferred primary",
"mesh_code": "",
"title": "Eosinophil percent differential count"
}
]
},
"umls": {
"codes": [
{
"code": "C0362902",
"title": "Eosinophils/Leukocytes:NFr:Pt:Bld:Qn:Automated count"
},
{
"code": "C1171399",
"title": "Eosinophil percent differential count (procedure)"
}
]
}
},
"flags": {
"sex_indicator": ""
}
}
}
]
}
},
{
"record_id": "LABREC03",
"domain": "Lab",
"input_term": "Neutrophils",
"context": {
"loinc_component": "Neutrophils/leukocytes",
"loinc_property": "NFr",
"loinc_scale": "Qn",
"loinc_time": "Pt",
"sample_type": "Bld"
},
"response": {
"match_field": "input_term",
"domain": "lab",
"custom_mapped": false,
"explanation": "",
"match_includes_assumptions": false,
"items": [
{
"lexical_code": "30985709",
"lexical_title": "Blood neutrophils/100 leukocytes",
"default_lexical_code": "30985709",
"default_lexical_title": "Blood neutrophils/100 leukocytes",
"score": 0.98,
"certainty": "",
"metadata": {
"mappings": {
"cpt": {
"codes": [
{
"code": "85004",
"long_title": "Blood count; automated differential WBC count",
"map_type": "Preferred primary",
"title": "Automated diff WBC count"
}
]
},
"hcpcs": {
"codes": []
},
"icd10pcs": {
"codes": []
},
"loinc": {
"codes": [
{
"code": "26511-6",
"map_type": "Preferred primary",
"title": "Neutrophils/Leukocytes:NFr:Pt:Bld:Qn"
}
]
},
"snomedInternational": {
"codes": [
{
"code": "271035003",
"map_type": "Preferred primary",
"mesh_code": "",
"title": "Neutrophil percent differential count"
}
]
},
"umls": {
"codes": [
{
"code": "C0942471",
"title": "Neutrophils/Leukocytes:NFr:Pt:Bld:Qn"
},
{
"code": "C1318430",
"title": "Neutrophil percent differential count"
}
]
}
},
"flags": {
"sex_indicator": ""
}
}
}
],
"loinc_parts": {
"component": {
"part_name": "Neutrophils/leukocytes",
"part_number": "LP286655-8"
},
"property": {
"part_name": "Number Fraction",
"part_number": "LP6838-9"
},
"sample_type": {
"part_name": "Blood",
"part_number": "LP7057-5"
},
"scale": {
"part_name": "Qn",
"part_number": "LP7753-9"
},
"time": {
"part_name": "Point in time (spot)",
"part_number": "LP6960-1"
}
}
}
}
],
"preferences": {
"match_field_pref": "input_term"
}
}
In the response, the requests array returned one object corresponding to each normalization record supplied in the request. In each of these objects, the items array includes one child object describing the highest scoring lexical that was matched to the supplied input_term and context. For each lexical, the items.default_lexical_title states the IMO normalized text for the corresponding clinical concept, and the items.metadata.mappings array lists each of the clinical codes mapped to that lexical from all applicable code systems.
For the first record, the standalone input term "Creatinine, Urine, g/24h" was sufficiently detailed that it resulted in an exact match with the lexical "30985558 - 24 hour urine creatinine measurement (mass/time)".
For the second record, the input term "eos" was extremely vague and could not on its own be confidently matched to a lexical, but the supplied unit_of_measure and order_name provided enough context for compendium entry comparison, resulting in an exact match with lexical "44874687 - Automated blood eosinophil count as percentage of total leukocytes".
For the third record, the input term "Neutrophils" on its own had many potential low-confidence lexical matches, but the supplied LOINC code parts (loinc_component, loinc_property, loinc_time, sample_type, loinc_scale) enabled a very high-confidence match with lexical "30985709 - Blood neutrophils/100 leukocytes".
Lab domain normalization is unique in that it may return lexicals from several different IMO content domains, especially Procedure. When you perform an explicit request to the "Lab" domain, you are actually invoking a special cross-domain lexical matching process that takes into consideration factors like compendium entry and LOINC part matching. As a result, the actual lexicals returned may populate different response payload fields, as appropriate for their domain. The items.metadata.mappings and items.metadata.flags objects will populate fields for whichever code systems and flags are applicable to the lexical's domain, and the items.metadata.subdomains array may be included if the lexical is from the Procedure domain. Whatever the actual domain of a returned lexical, each normalization record's domain field will still report a value of "Lab".
Response payloads for Lab domain requests have one other distinguishing aspect compared with other domains:
response.loinc_parts- This object identifies any resolved LOINC parts used for lexical matching. This object is only included when one or more of the LOINC parts included in the context object were resolved and the normalization result was derived from them.
5.5 Allergen Domain
The following sections demonstrate an example Classic term normalization request and response for the Allergen domain:
5.5.1 Allergen Request Payload
The following example request payload performs Allergen domain term-based matching for two normalizations records, respectively seeking normalization for the terms "cat dander" and "peanut":
{
"client_request_id": "9874ABCD",
"preferences": {
"match_field_pref": "input_term"
},
"requests": [
{
"record_id": "ALERRC01",
"domain": "Allergen",
"input_term": "cat dander",
"context": {
"reaction": "Eye Swelling",
"severity": "Mild"
}
},
{
"record_id": "ALERRC02",
"domain": "Allergen",
"input_term": "Peanut"
}
]
}
Each normalization record included the mandatory input_term field and domain fields. One of the records included a context object supplying the reaction and severity applicable to the input term allergen. The context objects could also have opted to include the optional record tracking fields (use_count, application_id, facility_id, encounter_id, document_id, project_id), but these are not used for lexical matching.
By excluding most preferences fields, this simple request accepted the default values for the use_custom_maps (true), size (1), threshold (0), discrepancy_check (false), and distinct_field (lexical_code) preferences; performed no manual transformations; and opted not to apply USCDI filters. The excluded use_domain_relevance_filter and use_semantic_match preferences are not applicable when matching lexicals from the Allergen domain.
The input_code and input_code_system fields are not used for term-based matching and so were excluded. Alternatively, if preferences.discrepancy_check was set to "true", we could have included an input code and system in order to perform discrepancy checking against the results.
Allergen Reaction and Severity
For allergen domain requests, the reaction and severity fields are optional fields used to return additional SNOMED International code mappings corresponding to the supplied reaction and severity descriptions. When included, these fields are treated as additional code lookup requests distinct from the input term itself. Any supplied reaction or severity values are not used for lexical matching against the input term, and the returned reaction and severity code mappings are not dependent on the lexical matched to the input term.
An allergen domain request may include either, both, or neither of the reaction and severity fields. If included, these fields should be populated as follows:
-
reaction: Any brief description of an allergen reaction, such as "rash", "hives", or "anaphylaxis". This should be thought of as a second input term that the API will use to perform an additional limited normalization operation for the Problem domain.
-
severity: One of the following values indicating the severity of the allergic reaction applicable to the input term: Mild | Moderate | Severe | Unknown
5.5.2 Allergen Response Payload
The following is a response payload for the Allergen domain request defined above:
Allergen Normalization Response
{
"summary": {
"count": 2,
"error_count": 0
},
"request_id": "6de5e674-69d8-a708-d124-dcf8094857c8",
"client_request_id": "9874ABCD",
"response_time": 75,
"requests": [
{
"record_id": "ALERRC01",
"domain": "Allergen",
"input_term": "cat dander",
"context": {
"reaction": "Eye Swelling",
"severity": "Mild"
},
"response": {
"match_field": "input_term",
"domain": "allergen",
"custom_mapped": false,
"explanation": "",
"items": [
{
"lexical_code": "21904967",
"lexical_title": "Cat dander",
"default_lexical_code": "21904967",
"default_lexical_title": "Cat dander",
"score": 1,
"certainty": "",
"metadata": {
"mappings": {
"reaction_mappings": {
"snomedInternational": {
"codes": [
{
"code": "267041004",
"map_type": "Preferred primary",
"title": "Swelling around eyes"
}
]
}
},
"rxnorm": {
"codes": []
},
"severity_mappings": {
"snomedInternational": {
"codes": [
{
"code": "255604002",
"map_type": "Preferred primary",
"title": "Mild"
}
]
}
},
"snomedInternational": {
"codes": [
{
"code": "260152009",
"map_type": "Preferred primary",
"title": "Cat dander"
}
]
},
"umls": {
"codes": [
{
"code": "C0440456",
"title": "Cat dander"
}
]
}
},
"flags": {
"allergen_categories": [
"Environmental Allergen"
]
}
}
}
]
}
},
{
"record_id": "ALERRC02",
"domain": "Allergen",
"input_term": "Peanut",
"transformed_term": "",
"response": {
"match_field": "input_term",
"domain": "allergen",
"custom_mapped": true,
"transformed_term": "",
"explanation": "",
"items": [
{
"lexical_code": "25605230",
"lexical_title": "Peanut oil",
"default_lexical_code": "25605230",
"default_lexical_title": "Peanut oil",
"score": 1,
"certainty": "",
"metadata": {
"mappings": {
"reaction_mappings": {
"snomedInternational": {
"codes": []
}
},
"rxnorm": {
"codes": []
},
"severity_mappings": {
"snomedInternational": {
"codes": []
}
},
"snomedInternational": {
"codes": [
{
"code": "417889008",
"map_type": "Preferred primary",
"title": "Arachis oil"
}
]
},
"umls": {
"codes": [
{
"code": "C0052300",
"title": "peanut oil"
}
]
}
},
"flags": {
"allergen_categories": [
"Food Allergen"
]
}
}
}
]
}
}
],
"preferences": {
"match_field_pref": "input_term"
}
}
In the response, the requests array returned one object corresponding to each normalization record supplied in the request. In each of these objects, the items array includes one child object describing the highest scoring lexical that was matched to the supplied input_term and context. For each lexical, the items.default_lexical_title states the IMO normalized text for the corresponding clinical concept, and the items.metadata.mappings array lists each of the clinical codes mapped to that lexical from all applicable code systems.
For the first record, the input term "cat dander" exactly matched the lexical "21904967 - Cat dander". Because the request included the severity and reaction fields, in the mappings array, the reaction_mappings and severity_mappings fields returned matched SNOMED International codes. For severity_mappings, the returned code is based on a simple lookup for each supported request value. For reaction_mappings, the returned code is identified from the top Problem domain lexical match resulting from an additional limited normalization operation performed on the request's reaction value itself.
For the second record, the input term "peanut" provided a non-standardized description for a common allergen, which the API was able to normalize to the lexical "25605230 - Peanut oil". Because the request excluded the severity and reaction fields, in the mappings array, the reaction_mappings and severity_mappings fields are blank.
Response payloads for Allergen domain lexicals have the following distinguishing aspects compared with other domains:
-
reaction_mappingsandseverity_mappings- These fields are only returned in reponse payloads for Allergen domain lexicals. -
items.metadata.flags- The flags object includes the allergen_categories array. This array specifies one or more categories applicable to the allergen source, use, or properties. These values align with the 2023 HL7 categories in the "AllergyIntoleranceCategory" value set for HL7 FHIR version 5.0.0.
5.6 Anatomical Site Domain
The following sections demonstrate an example Classic term normalization request and response for the Anatomical Site domain:
5.6.1 Anatomical Site Request Payload
The following example request payload performs Anatomical Site domain term-based matching for two normalizations records, respectively seeking normalization for the terms "left eyelid" and "RUQ":
{
"client_request_id": "45hg65we",
"preferences": {
"match_field_pref": "input_term"
},
"requests": [
{
"record_id": "ANATRC01",
"domain": "Anatomical Site",
"input_term": "left eyelid"
},
{
"record_id": "ANATRC02",
"domain": "Anatomical Site",
"input_term": "leg, lower, right"
}
]
}
Each normalization record included the mandatory input_term and domain fields, but excluded the context object as we are not using AI Enhancement. We alternatively could have opted to include the context object in order to provide the optional record tracking fields (use_count, application_id, facility_id, encounter_id, document_id, project_id), but these are not used for lexical matching.
By excluding most preferences fields, this simple request accepted the default values for the use_custom_maps (true), size (1), threshold (0), discrepancy_check (false), and distinct_field (lexical_code) preferences; performed no manual transformations; and opted not to apply USCDI filters. The excluded use_domain_relevance_filter and use_semantic_match preferences are not applicable when matching lexicals from the Anatomical Site domain.
The input_code and input_code_system fields are not used for term-based matching and so were excluded. Alternatively, if preferences.discrepancy_check was set to "true", we could have included an input code and system in order to perform discrepancy checking against the results.
5.6.2 Anatomical Site Response Payload
The following is a response payload for the Anatomical Site domain request defined above:
Anatomical Site Normalization Response
{
"summary": {
"count": 2,
"error_count": 0
},
"request_id": "a1437944-1cd2-1346-a92a-750227005d5a",
"client_request_id": "45hg65we",
"response_time": 20,
"requests": [
{
"record_id": "ANATRC01",
"domain": "Anatomical Site",
"input_term": "left eyelid",
"response": {
"match_field": "input_term",
"domain": "anatomical site",
"custom_mapped": false,
"explanation": "",
"items": [
{
"lexical_code": "83323216",
"lexical_title": "Eyelid of left eye",
"default_lexical_code": "83323216",
"default_lexical_title": "Eyelid of left eye",
"score": 0.653,
"certainty": "",
"metadata": {
"mappings": {
"snomedInternational": {
"codes": [
{
"code": "80243003",
"map_type": "Preferred primary",
"title": "Eyelid structure"
},
{
"code": "423781004",
"map_type": "Non-preferred primary",
"title": "Structure of left half of face"
}
]
},
"umls": {
"codes": [
{
"code": "C0230026",
"title": "Left side of face"
},
{
"code": "C0015426",
"title": "Eyelid structure"
}
]
}
}
}
}
]
}
},
{
"record_id": "ANATRC02",
"domain": "Anatomical Site",
"input_term": "leg, lower, right",
"response": {
"match_field": "input_term",
"domain": "anatomical site",
"custom_mapped": false,
"explanation": "",
"items": [
{
"lexical_code": "66940923",
"lexical_title": "Right lower leg",
"default_lexical_code": "66940923",
"default_lexical_title": "Right lower leg",
"score": 0.997,
"certainty": "",
"metadata": {
"mappings": {
"snomedInternational": {
"codes": [
{
"code": "32696007",
"map_type": "Preferred primary",
"title": "Structure of right lower leg"
}
]
},
"umls": {
"codes": [
{
"code": "C0230442",
"title": "Structure of right lower leg"
}
]
}
}
}
}
]
}
}
],
"preferences": {
"match_field_pref": "input_term"
}
}
In the response, the requests array returned one object corresponding to each normalization record supplied in the request. In each of these objects, the items array includes one child object describing the highest scoring lexical that was matched to the supplied input_term and context. For each lexical, the items.default_lexical_title states the IMO normalized text for the corresponding clinical concept, and the items.metadata.mappings array lists each of the clinical codes mapped to that lexical from all applicable code systems.
For the first record, the input term "left eyelid" supplied a non-standardized description for a distinct body part, which the API was able to normalize to the lexical "83323216 - Eyelid of left eye".
For the second record, the API was able to resequence the words in the input term "leg, lower, right" to find a match with the lexical "66940923 - Right lower leg".
Response payloads for Anatomical Site domain lexicals have the following distinguishing aspects compared with other domains:
items.metadata.flags- The flags field is excluded entirely for Anatomical Site domain lexicals.
6 Error Messages
...
"requests": [
{
"record_id": "10001",
"domain": "",
"input_term": "chest pain",
"response": {
"match_field": "",
"domain": "",
"custom_mapped": false,
"explanation": "",
"error_message": [
"E003: Missing domain"
],
"items": []
}
},
...
In any response payload, the presence of a response.error_message array for a normalization record indicates that the API encountered one or more errors that either prevented normalization entirely or impacted the result. If included, each string in the error_message array describes a distinct error, stated as an error code followed by a description.
Error codes beginning with an "E", "R", or "N" indicate fatal errors that prevent normalization entirely and are always accompanied by a blank items array. Error codes beginning with a "W" indicate warnings that may impact the results, but do not in themselves prevent lexical matches from being returned. The error_message field does not appear in situations where the normalization record was valid, but the API was simply unable to find a lexical match within the request threshold.
If present, the error_message array may include any of the following values:
-
Validation Errors (E): These errors indicate a basic problem with the data supplied in the normalization record:
- E001: Missing record id - The
record_idfield was either excluded or sent blank. - E002: Missing input term - The
input_termfield was either excluded or sent blank while thematch_field_prefpreference was set to "input_term". - E003: Missing domain - The
domainfield was either excluded or sent blank. - E004: Invalid domain field <value> - The
domainfield was sent with the indicated invalid <value> instead of a recognized domain. - E005: Missing input code - The
input_codefield was either excluded or sent blank while thematch_field_prefpreference was set to "input_code". - E006: Missing input code system - The
input_code_systemfield was either excluded or sent blank while thematch_field_prefpreference was set to "input_code". - E007: Invalid code system: <value> - The
input_code_systemfield was sent with the indicated invalid <value> instead of a recognized clinical code system. - E008: Unknown error - A fallback error when the API cannot process the normalization record and no other validation error applies.
- E009: Input term exceeds the maximum recommended length of 500 characters - The
input_termfield was sent with a value greater than 500 characters while thematch_field_prefpreference was set to "input_term".
- E001: Missing record id - The
-
Retryable Errors (R): These errors likely indicate either an authentication error or a communication problem with the API. If you encounter one of these errors, ensure that your Authorization header supplies a valid Bearer token and then try again:
- R001: Authentication error: invalid token
- R002: Authentication error: invalid scope
- R003: An error occurred while submitting this record for normalization
-
Non-Retryable Errors (N): These errors apply when
domainis set to "auto" and the supplied input could not be normalized to a single domain's lexicals. If you enounter one of these errors, you will likely need to alter your request before trying again:- N001: Unresolvable tied score in the domain - This error indicates that the highest scoring lexical match in two or more domains had the same score. You can try again using a specific domain or after altering your input term.
- N003: An error occurred while performing a term match across multiple domains - A generic fallback error when term-based matching across multiple domains.
- N004: An error occurred while performing a code match across multiple domains - A generic fallback error when code-based matching across multiple domains.
-
Warnings (W): These errors indicate a problem with the request's
preferences.filtersarray. These errors may prevent the USCDI filters from being applied, but they do not otherwise prevent normalization from proceeding. For information on defining USCDI filter criteria, see 4.8 USCDI Filters above:- W010: Maximum number of filters exceeded. The maximum allowed is 4 - The
filtersarray included more than the maximum of 4 objects. - W011: Invalid filter field: <value> - The
filters.fieldwas sent with the indicated invalid <value> instead of a recognized USCDI field name. - W012: Access denied: filtering on field '<value>' is not allowed due to licensing restrictions - This indicates that you included the
filtersarray without having confirmed your USCDI licensing with IMO Health. See 2.1.2 USCDI Access above. - W013: Invalid filter operator: <value> - The
filters.operatorwas sent with the indicated invalid <value>. Currently, only an operator of "eq" is permitted. - W014: Failed to build filter query - A fallback error when the API cannot process the
filtersarray and no other warning applies.
- W010: Maximum number of filters exceeded. The maximum allowed is 4 - The
7 Request Rate and Response Times
In each request to the IMO Precision Normalize API, the requests array can technically contain up to 100 normalization records, but approaching this hard limit will impact response times and is not recommended. When you wish to process large batches of normalization records, for optimal performance each request payoad should include 10 to 25 normalization records. If using semantic matching, 25 normalization records is ideal. These recommendations take into account time to access system resources and will result in a faster overall time to completion than sending the same quantity of normalization records one at a time.
The following table provides Classic endpoint response times for request payloads containing 25 normalization records for different domains. All listed response times are in milliseconds and are based on 95th percentile latency, meaning 95% of the tested requests completed within the supplied duration. Response times are dervied from term-based matching scenarios.
Note: For the Classic endpoint, an SFTP interface is also available for processing larger batches of time-independent normalization records. For information on using the SFTP interface, see 9 SFTP Normalization.
| Domain | Response Times (ms) |
|---|---|
| Problem | 729 |
| Problem - Domain Relevance Filter | 3,500 |
| Problem - Semantic Matching | 6,324 |
| Problem - Relevance + Semantic | 15,500 |
| Problem - AI Enhancement | 15,000 |
| Procedure | 1,200 |
| Medication | 3,000 |
| Lab | 2,000 |
| Allergen | 800 |
| Anatomical Site | 800 |
| Auto | 10,000 |
For the Problem domain, this table includes multiple entries representing requests with different features enabled:
- Problem: Problem domain records with none of the other listed features enabled.
- Problem - Domain Relevance Filter: Problem domain records with
preferences.use_domain_filterset to "true". - Problem - Semantic Matching: Problem domain records with
preferences.use_semantic_matchset to "true". - Problem - Relevance + Semantic: Problem domain records with both
use_domain_filteranduse_semantic_matchset to "true". - Problem - AI Enhancement: Problem domain records with AI Enhancement enabled, and both
use_domain_filteranduse_semantic_matchset to "false".
8 Term Refinement Workflow
Most Problem domain lexicals belong to a Refinement Group, which is a collection of related lexicals that share the same clinical topic and attributes for defining specificity. Within a given refinement group, these related lexicals are organized hierarchically from most to least specific. For example, there is a "Fracture of femur" refinement group, which stratifies its lexicals based on whether they describe laterality and encounter type. This group includes a top-level lexical "20755 - Fracture of femur", which has a much more specific descendent lexical of "1951679 - Closed fracture of shaft of left femur, initial encounter".
Refinement groups can be used to support the term refinement workflow, sometimes also referred to as "post-coordination". This workflow involves generating a session to track the normalization of an input term across multiple requests and endpoints with the goal of identifying the most specific lexical applicable to the relevant clinical concept. The term refinement workflow is particularly relevant for billing related scenarios, where it is usually ideal to supply the most specific billing code applicable to the patient's condition. When you have identified the most specific lexical that accurately describes the clinical intent of your input term, the final step of this workflow is to tell the API which lexical you selected as most applicable. By tying all of these actions together in a single session, IMO Health can analyze your usage patterns in order to improve future normalization results.
The term refinement workflow is specific to the Problem domain and is enabled by the metadata.flags.is_icd10cm_refinable boolean field returned in normalization response payloads for Problem domain lexicals. This field is set to "true" for a lexical that has more specific descendent lexicals within its refinement group, meaning it can be "refined" to another lexical representing a more granular clinical concept within the same topic. This field is set to "false" for lexicals at the lowest level of hierarchy within its refinement group, meaning it represents the most specific level of granularity available for the relevant clinical topic. In the term refinement workflow, the is_icd10cm_refinable flag helps you determine whether a followup request is required in order to identify a more specific lexical for your input term. This flag technically refers to the lexical that directly matched the request input (lexical_code/lexical_title), but the corresponding default variant (default_lexical_code/default_lexical_title) always shares the same refinability, as both variants reference the same clinical concept.
The following steps describe the term refinement workflow in detail:
- Generate a Session
- Send initial Normalization request
- Analyze initial Normalization response
- Send followup Core Search request
- Send Lexical Selection Request
8.1 Generate a Session
Before submitting your initial normalization request, use the following operation to generate a new session and retrieve a corresponding Session ID value, which you will supply in the payload of all subsequent requests for this workflow. Session IDs do not expire and there is no set expectation for how long the entire refinement workflow should take. The Session ID only exists to enable IMO Health to track a normalization record across different requests, from initial creation to final lexical selection.
GET /precision/normalize/session
The response body will include a session_id field containing the identifier for this term refinement session. For a full description of this operation, please refer to the REFERENCE DOCUMENTATION tab.
{
"session_id": "a1bc2def-g34h-5ij5-klm6-7890n2o345pq"
}
8.2 Send initial Normalization request
Use the following operation to submit a normalization request for one or more normalization records:
POST /precision/normalize/v1
In the request payload, the session_id field must specify the Session ID value you retrieved in 8.1 Generate a Session. The rest of the payload should define term-based matching requests for one or more normalization records, as described in 6 Classic Term Normalization Requests above.
As the Session ID is supplied at the request level, the same ID will apply to every normalization record included in your request. In subsequent steps of the term refinement workflow, it is important to use the same Session ID for all requests pertaining to a given normalization record, but you may process records sharing the same Session ID independently.
For example, the following normalization request payload defines an initial normalization request for two normalization records, respectively seeking normalization for the terms "femur fracture" and "knee pain, right, chronic".
{
"client_request_id": "REQ1050",
"session_id": "a1bc2def-g34h-5ij5-klm6-7890n2o345pq",
"preferences": {
"match_field_pref": "input_term"
},
"requests": [
{
"record_id": "PRLMRC10",
"domain": "Problem",
"input_term": "femur fracture"
},
{
"record_id": "PRLMRC11",
"domain": "Problem",
"input_term": "knee pain, right, chronic"
}
]
}
8.3 Analyze initial Normalization response
For each lexical returned in the response to your initial normalization request, review the values returned in the metadata.flags.is_icd10cm_refinable field. Based on the returned value, a followup Core Search request may be warranted to identify more specific lexicals:
-
If set to false, then the returned lexical represents the most specific level of granularity available for the relevant clinical topic. This lexical cannot be further refined.
-
If this field is set to true, then the returned lexical has one or more descendent lexicals within its refinement group representing more specific clinical concepts. You may wish to send a followup Core Search request to further refine this lexical.
For example, for the request provided in the previous step, consider the following response:
Initial Normalization Response
{
"summary": {
"count": 2,
"error_count": 0
},
"request_id": "4b4b4bbb-55d5-666f-h777-jj88j8888ll9",
"client_request_id": "REQ1050",
"session_id": "a1bc2def-g34h-5ij5-klm6-7890n2o345pq",
"response_time": 260,
"requests": [
{
"record_id": "PRLMRC10",
"domain": "Problem",
"input_term": "femur fracture",
"response": {
...
"items": [
{
"lexical_code": "43972",
"lexical_title": "Femur fracture",
"default_lexical_code": "20755",
"default_lexical_title": "Fracture of femur",
...
"metadata": {
"mappings": {...},
"flags": {
"is_icd10cm_refinable": true,
...
}
}
}
]
}
},
{
"record_id": "PRLMRC11",
"domain": "Problem",
"input_term": "knee pain, right, chronic",
"response": {
...
"items": [
{
"lexical_code": "41282150",
"lexical_title": "Chronic pain of right knee",
"default_lexical_code": "41282150",
"default_lexical_title": "Chronic pain of right knee",
...
"metadata": {
"mappings": {...},
"flags": {
"is_icd10cm_refinable": false,
...
}
}
}
]
}
}
]
}
For the first record, the input term "femur fracture" matched lexical "20755 - Fracture of femur", which has is_icd10cm_refinable=true. We decide that the returned lexical is not yet specific enough and we want to send a followup Core Search request to further refine this lexical.
For the second record, the input term "knee pain, right, chronic" matched lexical "41282150 - Chronic pain of right knee", which has is_icd10cm_refinable=false. We determine that this lexical represents an accurate and specific description for the clinical intent of the input term, and so take note of the lexical_code "41282150" for later use in 8.5 Send Lexical Selection Request.
8.4 Send followup Core Search request
When a normalization response payload returns an unrefined lexical with is_icd10cm_refinable=true, you may decide that you want to find a more specific lexical that better represents the clinical intent of the input term. Using the following operation from the IMO Core Search API, you can identify other lexicals from the same refinement group as the unrefined lexical returned in the initial normalization response.
POST /v2/product/{productName}/search
In the request, the payload should specify the same sessionID value you retrived in 8.1 Generate a Session and the searchTerm field should specify the lexical_title or default_lexical_title of the unrefined lexical returned in the initial normalization response. You will send a separate request for each of your unrefined lexicals. For more information on using the IMO Core Search API, please refer to the API Catalog - Core Search page.
The response will typically return several related lexicals from the same clinical topic (i.e. refinement group) representing different variations of laterality, severity, chronicity, encounter type, or any other applicable specificity attributes. Select the one lexical that best represents the clinical intent of the input term and take note of the IMO_lexical_code for use in 8.5 Send Lexical Selection Request.
For example, from the initial normalization response provided in the previous step, we decided that we wished to further refine lexical "20755 - Fracture of femur". We then send a followup Core Search request using a searchTerm of "Fracture of femur". From the lexicals returned in the response, we decide that lexical "1962872 - Closed fracture of left femur, initial encounter" represents an accurate and specific description for the clinical intent of the input term. We then take note of the IMO_lexical_code "1962872" for use in the final step of this workflow.
8.5 Send Lexical Selection Request
For each normalization record, when you have identified the one lexical that best represents the clinical intent of the input term at the appropriate level of specificity, you should then use the following operation to tell the API which lexical you selected:
POST /precision/normalize/event/selection
From the batch of normalization records supplied in the initial normalization request, you can report your selected lexicals either all at once in a single request, or gradually using multiple requests as your complete the refinement process for one or more records at a time. The only restrictions are that the request payload must report exactly one lexical selection per normalization record and that each supplied combination of session_id and record_id must correspond to the initial normalization request.
The request payload must define a JSON object with the following fields. If your selection request is properly processed, the API responds with an HTTP status code of 200 OK and an empty body:
-
session_id: This field must specify the same Session ID value that you retrieved in 8.1 Generate a Session
-
result_selected: This array contains one object for each normalization record whose selected lexical you want to report. Each object must contain the following two fields:
-
record_id: The
record_idvalue supplied for the applicable normalization record in the initial normalization request. -
imo_lexical_code: The
lexical_code,default_lexical_code, orIMO_lexical_codevalue for the lexical you selected as most appropriate for the normalization record.
-
For example, continuing from our refinement examples above, for the normalization record "PRLMRC10" we selected lexical "1962872 - Closed fracture of left femur, initial encounter" and for record "PRLMRC11" we selected lexical "41282150 - Chronic pain of right knee". We decide to report both lexical selections at once, and so we send the following selection request payload:
{
"session_id": "a1bc2def-g34h-5ij5-klm6-7890n2o345pq",
"result_selected": [
{
"record_id": "PRLMRC10",
"imo_lexical_code": "1962872"
},
{
"record_id": "PRLMRC11",
"imo_lexical_code": "41282150"
}
]
}
9 SFTP Normalization
For the Classic normalization endpoint, an SFTP interface is available for processing large batches of time-independent normalization records. The SFTP interface is typically used in workflows involving the collection of large volumes of data over time for periodic normalization all at once.
The following sections describe how to use the SFTP normalization interface:
- 9.1 SFTP Hosts
- 9.2 SFTP Folder and Workflow
- 9.3 SFTP Request Input File
- 9.4 SFTP Response Output File
- 9.5 SFTP Email Notification
9.1 SFTP Hosts
The SFTP normalization interface includes the following two hosts, which you can connect to using any standard SFTP client, such as WinSCP, FileZilla, or Cyberduck:
-
Sandbox: Used for initial integration testing, this is a scaled-down version of Production not considered against usage metering. The Sandbox host uses the following connection parameters:
-
URL: normalize-bulk-sandbox.imohealth.com
-
Port: 22
-
-
Production: After integration testing, you should send all requests pertaining to normal operations to the Production environment. The Production host uses the following connection parameters:
-
URL: normalize-bulk.imohealth.com
-
Port: 22
-
For either environment, your authorization credentials will be the same Client ID (username) and Secret (password) you use for API authentication, as described above in section 2.1.1 Client ID and Secret.
9.2 SFTP Folders and Workflow
To enable SFTP normalization, IMO maintains an Amazon Simple Storage Service (Amazon S3) bucket with one dedicated folder per Client ID. Upon connecting to the Sandbox or Production SFTP host, you will have access to the one client folder associated with your authorization credentials, which contains two subfolders: Input and Output.
To perform an SFTP normalization request, you will use these folders in the following standard steps:
-
SFTP Request Input File: Use an SFTP client to connect to the Sandbox or Production SFTP host and upload a request input file to your Input folder.
You can place your request input file at the root level of the Input folder or you can create subfolders. Each request file defines a metadata line specifying a set of request preferences, and one or more normalization records using most of the same fields as a Classic endpoint API request. For more information on the request file format, see 9.3 SFTP Request Input File below.
-
IMO Precision Normalization: The IMO Precision Normalization engine processes all normalization records submitted in the request input file exactly as if they were included in a request payload for the Classic endpoint. Processing time can take anywhere from several minutes to 12 hours depending on the quantity of submitted records and currently available resources.
When all rows in the entire file have been processed, the IMO Precision Normalize engine takes the following actions:
-
Generate Response: The engine generates a response output file in your Output folder.
The response output filename and subfolder is based on the input file, as described below in 9.2.1 SFTP Filenames.
-
Email Notification: If the request file metadata included a valid email address, the engine sends an email to that address notifying the recipient that a response is available.
The email message identifies the name of the applicable request input file and provides a record processing summary, as described below in 9.5 SFTP Email Notification.
-
-
SFTP Request Output File: Use an SFTP client to connect to the Sandbox or Production SFTP host and download the SFTP response file from your Output folder.
The response file reports the normalization outcome for each of the records supplied in the request. For SFTP normalization, the response always returns only the single highest scoring lexical matched to each normalization record's input. Normalization outcomes are reported using the same fields as a Classic endpoint API response. For more information on the response file format, see 9.4 SFTP Response Output File below.
Any files added to either the Input and Output folders are automatically purged after 30 days. You also have the option of manually deleting any file in either of these folders. If you accidentally delete the Input or Output folder itself, they will automatically regenerate the next time you connect to the SFTP host.
9.2.1 SFTP Filenames
The exact filename and extension for the request input file does not matter, but is restricted to UTF-8 alphanumeric characters, spaces, and any of the following special characters: ! - _ . ' ( )
In your Input folder, you can supply your input files at the root level or you may use subfolders. If using subfolders, the engine will create a corresponding Output subfolder of the same name in which to place the response. In most situations, the response output filename will be identical to the request input file. However, if your request filename includes the word "Input" (case-senstive), the response output file will substitute the word "Output".
For example, consider the following example request Input folder structure and the resulting Output folder:
\Input\test1.txt \Input\June2026\SFTP_Input_06302026_1.txt \Input\June2026\test2.txt\Output\test1.txt \Output\June2026\SFTP_Output_06302026_1.txt \Output\June2026\test2.txt
It is usually recommended to use a unique filename for each request input file, but this is not a hard requirement. The only limitation to keep in mind is that the output filename and path will always be the same for a given input filename, meaning multiple requests using the same input filename will cause previously generated output files to be overwritten.
9.3 SFTP Request Input File
The following sections describe the requirements for an SFTP normalization request input file:
9.3.1 Request File Structure
The SFTP request input file must be a plain-text file adhering to the following format:
# {"domain":"Problem", "file_id": "myfid101", "date": "2026-06-29T22:06:48Z", "match_field_pref": "input_term", "email": "email@domain.com"}
# A second comment. You can add more comment lines, or remove this one.
record_id input_term input_code input_code_system
SFRCD101 chest pain R07.9 ICD-10-CM
-
Metadata: The first line of an SFTP request input file defines the request metadata. This line must begin with a hashtag (#) followed by a JSON object defining several mandatory request parameters and a number of optional request-level preferences. Field sequence within this object does not matter and you may exclude any optional fields, but the entire metadata JSON object must be submitted on a single line.
The metadata object supports many of the same preferences as a Classic endpoint API request's
preferencesobject and are specified using the same field names and syntax. For a list of all supported metadata fields, see 9.3.3 Request Metadata Fields below. -
Comments: Following the metadata line, you may optionally supply any number of additional comment lines prefixed by a hashtag (#). Comment lines are not used for request processing and will not be echoed back in the response.
-
Normalization Record Column Headers: The next line after your metadata and comments must specify a tab-delimited list of column headers for each field that you will use to define your normalization records. Column sequence does not matter and you may exclude any optional columns. You can also choose to include columns headers that will only be used by a portion of the supplied records.
You can supply columns for most of the same fields available when defining normalization records in the
requestsarray of a Classic endpoint API request. Column names are identical to the corresponding API field names, although field names from thecontextobject are supplied without object hierarchy (e.g. "source_text", not "context.source_text"). For a list of all supported record columns, see 9.3.4 Request Record Columns below. -
Normalization Records: Each line after the column headers defines the values for a single normalization record using any of the columns named in the header line. Record values are tab-delimited and must correspond to the column header in the same tab position. If a particular column is not used for a record, you may skip it by supplying a tab without value. If skipping one or more columns at the very end of a record line, you may omit the final tabs.
Each SFTP request input file can include the following quantities of normalization records, depending on the host:
-
Sandbox: The Sandbox environment is limited to a maximum of 50,000 normalization records or 100 million bytes per input file.
-
Production: The Production environment can technically support up to 1,000,000 normalization records or 100 million bytes per input file, but approaching this hard limit will impact response times and is not recommended. As a best practice, IMO recommends supplying no more than 500,000 records per request.
-
9.3.2 Request Metadata Fields
The JSON object supplied in the metadata line of an SFTP request input file can include the following fields:
| Field | Constraints | Description |
|---|---|---|
| file_id |
required string |
A unique identifier for the SFTP request. This may be any string value using any format. This is analagous to the *client_request_id* field used in API request payloads. |
| date |
required string |
The date and time that the SFTP request input file was created, specified in ISO 8601 format. |
| domain |
required string |
When term-based matching, this is a single IMO content domain (Problem, Procedure, Medication, Lab, Allergen, Anatomical Site) from which the API should match lexicals to each normalization record's supplied *input_term*, or a value of "Auto" to use Auto Domain Resolution. When code-based matching, the domain field's value is ignored, but a valid value must still be included in this field. For the SFTP interface, the same domain value is used for all normalization records included in the request input file. |
|
optional string |
A single email address to which a notification email should be sent when the response to your request input file is available. This may be any valid email address, no registration or configuration is necessary. If this field is excluded, no notification email will be sent. | |
|
match_field_prefuse_domain_relevance_filteruse_semantic_matchthresholddiscrepancy_checktransformationsfilters |
optional |
You may include any of these listed preferences, which are named and behave identically to the corresponding fields in a Classic endpoint API request's For full details about each of these fields, please refer to the REFERENCE DOCUMENTATION tab. |
For example, the following metadata line includes the file_id, date, domain, email, match_field_pref, and transformations fields:
# {"file_id": "myfid101", "date": "2026-06-29T22:06:48Z", "domain":"Problem", "email": "email@domain.com", "match_field_pref": "input_term", "transformations": [{"type": "multiple_string_replace","location": "*","from": ["red", "blue"],"to": "red", "case_sensitive": false}]}
The following preferences normally available in Classic endpoint API request payloads are not applicable to SFTP requests:
-
client_request_id: For SFTP requests, the role of this preference as unique request identifier is performed by the
file_idmetadata field. -
session_id: SFTP normalization was not constructed with the term refinement workflow in mind and does not support this preference. However, in the response, the
metadata.flags.is_icd10cm_refinableflag is still returned and behaves as described in 8 Term Refinement Workflow above. -
use_custom_maps: This preference is not supported. For SFTP normalization, this preference is always set to the default value of "true", meaning the engine always checks custom lexical mappings.
-
size: This preference is not supported. For SFTP normalization, this preference is alway set to the default value of 1.
-
distinct_field: This preference is not supported. For SFTP normalization, only one lexical is ever returned per normalization record and so there is no need to distinguish result uniqueness.
9.3.3 Request Record Columns
Normalization records in an SFTP request input file can be defined using columns representing any of the same fields that could be included in the requests array of a Classic endpoint API request, with the exception of domain, encounter_id, document_id, and project_id. Request record columns are named and behave identically to the corresponding fields in API request payloads:
SFTP request input files may include any of the following normalization record columns, which may be provided in any sequence:
record_id, input_term, input_code, input_code_system, source_text, use_count, application_id, facility_id, encounter_id, document_id, project_id, unit_of_measure, order_name, loinc_component, loinc_property, loinc_time, sample_type, loinc_scale, loinc_method, reaction, severity
Keep in mind the following important considerations when defining your column headers and values:
-
The domain field is excluded. For SFTP requests, the metadata line defines a single domain value applicable to all normalization records in the request.
-
Column names are identical to the corresponding field in API requests. Fields from the context object should be identified by field name only, without reference to the containing context object (e.g. "source_text", not "context.source_text"). The context object itself is not represented by a column.
-
You must include at least the following columns:
Excluding a required column header altogether will trigger a response level error, as described in 9.4.1 Response Level Errors. Excluding a required value for an individual record will prevent normalization for only that one record, which will return a fatal error in the
error_messageresponse column.-
The record_id column header must always be present and populated.
-
Your value for the metadata line's match_field_pref preference determines additional column requirements as follows:
-
input_term: The input_term column header must always be present and populated.
-
input_term_first: The input_term column header must always be present, but may be left blank.
Each record must specify either an input_term or both of the input_code and input_code_system columns.
-
input_code: The input_code and input_code_system column headers must always be present and populated.
-
input_code_first: The input_code and input_code_system column headers must always be present, but may be left blank.
Each record must specify either an input_term or both of the input_code and input_code_system columns.
-
-
-
All column headers and values are tab-delimited. Column values must correspond to the header in the same tab position.
-
You may include column headers that are used by only some records in the input file.
To skip a column for a particular record, simply supply a tab without value. If skipping one or more columns at the very end of a record line, you may omit the final tabs.
For example, the following lines define two normalization records using the record_id, input_term, source_text, reaction, and document_id fields. For the first record, we skip the severity by supplying only a tab for that column position. For the second record, we skip the source_text column by supplying only a tab for that column position, and we also omit the final tab for the unused document_id:
record_id input_term source_text severity document_id SFRCD101 chest pain The patient is experiencing chest pain DOCID9731 SFRCD101 peanut oil Moderate
9.4 SFTP Response Output File
The following sections describe the content of an SFTP normalization response output file:
- 9.4.1 Response Level Errors
- 9.4.2 Response File Structure
- 9.4.3 Response Summary Fields
- 9.4.4 Response Record Columns
9.4.1 Response Level Errors
If there is a basic problem with your request input file structure, the entire request will be rejected and no normalization will occur. This situation is analagous to receiving an HTTP status code response of 400 Bad Request. In this situation, the response output file will contain only a metadata line adhering to the following format:
# {"request": {"file_id": "myfid101", "domain": "problem", "date": "2026-06-30T15:09:00Z", "organization_id": "0011A00000bC2DEFG3", "client_id": "AZBYcxdyeWfVgUhTisjSkrLqMp1NOOA2"}, "response": {"batch_id": "1234ab56-a1b2-ab1c-ab1c-abc1234567de", "error_message": "File validation failed with the following errors: <error>"}}
For a response level error, the metadata line consists of a hastag (#) prefixed JSON object that includes the following fields:
- request.file_id, domain, problem: These fields echo back the same field values from your request. If the
response.error_messageis "Invalid metadata format", then these fields are sent blank. - request.organization_id: An Internal IMO identifier for your organization.
- request.client_id: The Client ID value supplied as your Username when connecting to the SFTP Host.
- response.batch_id: An internal identifier for the SFTP normalization request.
- response.error_message: Supplies one of the following <error> values indicating the problem with your request input file:
- Invalid metadata format - Typically indicates that the metadata line contained a JSON syntax error or was missing.
- Invalid domain = <value> - In the metadata line, the
domainfield was sent with the indicated invalid <value> instead of a recognized domain. - Invalid match_field_pref field = <value> - In the metadata line, the
match_field_preffield was sent with the indicated invalid <value> instead of a recognized value. - Invalid date field = <value> - In the metadata line, the
datefield was sent with the indicated invalid <value> instead of a date and time in ISO 8601 format. - Missing required metadata = <value> - The metadata line was missing a required field. The file_id, date, and domain fields are always required.
- Required headers are missing - The record column headers were missing a required column. The
record_idcolumn is always required, andinput_term,input_code, andinput_code_systemmay be required depending on thematch_field_pref, as described in 9.3.3 Request Record Columns above. - Invalid row count - The input file included more normalization record lines than the maximum permitted for the host, as described in 9.3.1 Request File Structure above.
- Invalid file size - The input file size in bytes was greater than the maximum permitted for the host, as described in 9.3.1 Request File Structure above.
9.4.2 Response File Structure
If the request input file passes validation without encountering a response level error, the response output file adheres to the following format. All fields and columns in the response are always provided in the same sequence:
# {"request": {"file_id": "myfid101", "domain": "problem", "date": "2026-07-01T21:47:08.991Z", "debug": false}, "response": {"batch_id": "a123b456-98z7-1a23-98z7-a123bc4d567e"}}
# {"total_records_processed": 4, "total_error_records": 1, "no_match": 2, "total_custom_mappings": 0, "total_match_includes_assumptions": 0, "total_matches_by_domain": {"problem": {"total": 2, "no_match": 0}}, "top_10_most_frequent_terms_with_lowest_score": [], "top_10_terms_with_highest_frequency": []}
# © 2026. IMO Health is a trademark of Intelligent Medical Objects, Inc. All rights reserved.
# <44 more lines...>
record_id input_term input_code input_code_system lexical_code lexical_title default_lexical_code default_lexical_title score certainty metadata domain match_field error_message explanation
SFRCD101 chest pain 85191 Chest pain 85191 Chest pain 1 {<metadata>} problem input_term
SFRCD102 peanut oil 82130103 Adverse effect of peanut oil 82130103 Adverse effect of peanut oil 0.787 {<metadata>} problem input_term
SFRCD103 pizza 0.0
SFRCD104 ["E002: Missing input term"]
-
Metadata: The first line of an SFTP response output file consists of a hastag (#) prefixed JSON object that includes the following metadata fields for the response:
- request.file_id: The same
file_idvalue echoed back from the request input file's metadata line. - request.date: The date and time that the output file was created, specified in ISO 8601 format
- request.debug: Always indicates that debug mode was disabled. This refers to an internal setting only used by IMO employees.
- response.batch_id: An internal unique identifier for the SFTP normalization request.
- request.file_id: The same
-
Response Summary: Following the metadata line, the response includes a hashtag (#) prefixed JSON object providing a processing summary for your normalization records. For a description of each field included in this response summary, see 9.4.3 Response Summary Fields below.
-
Comments: Following the summary line, the response includes 45 hashtag (#) prefixed comments containing legal notices.
-
Normalization Records Column Headers: The next line after the metadata and comments specifies a tab-delimited list of column headers used to describe the normalization outcomes for the records supplied in the request input file. For a breakdown of the columns that may be returned in the response, see 9.4.4 Response Record Columns below.
-
Normalization Records: Each line after the column headers defines the values for a single normalization record's outcome using the columns named in the header line. Record values are tab-delimited and correspond to the column header in the same tab position. If a column is not used for a particular record, then that column position contains only a tab.
An SFTP response output file returns one line for each normalization record included in the request input file. Each line reports one of the following outcomes for the normalization record:
-
lexical match: For SFTP normalization, the response returns only the single highest scoring lexical matched to the record's input. If the API identified a lexical match for the record, the following columns are populated with details describing the match, exactly as they would be for a Classic endpoint API response:
lexical_code, lexical_title, default_lexical_code, default_lexical_title, score, certainty, metadata, domain, match_field, explanation
-
no lexical match: If the record input was valid but no lexical match could be identified, the
scorecolumn returns a value of 0 and all other lexical match columns listed above contain only a tab. -
fatal error: If the request record encountered a fatal error that prevented normalization, the
error_messagecolumn reports the applicable errors and all lexical match columns listed above contains only a tab.For example, this could occur if the record did not supply a required value. The error_message column may report any of the same errors returned in the
response.error_messagearray of an API response, as described in 6 Error Messages above.
-
9.4.3 Response Summary Fields
The JSON object supplied in the response summary line of an SFTP response output file includes the following fields:
| Field | Description |
|---|---|
| total_records_processed | The total quantity of records returned in the response output file. This is the same quantity of normalization records submitted in the request input file. |
| total_error_records | The quantity of records returned in the response output file that include a value in the error_message column. |
| no_match | The quantity of records for which a lexical match could not be returned. This may be due to a fatal error reported in the error_message column, or because no lexical could be matched within the request threshold. |
| total_custom_mappings | The quantity of records with a lexical match that was determined by a custom lexical mapping. |
| total_match_includes_assumptions | The quantity of records with a Lab domain lexical match that required the API to assume some parts of a LOINC fully specified name. In an API response, this situation would result in the response returning a match_includes_assumptions value of "true". |
| total_matches_by_domain |
This object provides a breakdown of lexical match quantities by domain. For example, if 2 normalize records were matched to lexicals from the Problem domain, this object would include the field: "problem": {"total": 2, "no_match": 0}. The total_matches_by_domain object includes one field for each domain from which lexicals were matched. In each domain's object, the |
| top_10_most_frequent_terms_with_lowest_score |
This array reports the top 10 most frequently occurring input terms from all records with a lexical match score below 0.85. This report excludes records with unique input terms or with no lexical match. If the response has no records meeting the reporting criteria, this field is sent as a blank array. This field is always excluded when This array may include up to 10 objects, with each object representing a particular input term shared by two or more records. When more than 10 re-ocurring input terms are available, the array includes only those terms with the highest Each object in this array includes the following fields:
|
| top_10_terms_with_highest_frequency |
This array reports the top 10 most frequently occurring input terms from all records with any lexical match, regardless of score. The only difference between this array and the If the response has no re-ocurring input terms with lexical matches, this field is sent as a blank array. This field is always excluded when |
| top_10_most_frequent_codes_with_no_match |
When This array may include up to 10 objects, with each object representing a valid combination of input code and system shared by two or more records with no lexical match. When more than 10 re-occurring combinations are available, the array includes only those combinations with the highest Each object in this array includes the following fields:
|
| top_10_codes_with_highest_frequency |
When If the response has no re-ocurring combinations of input code and system, this field is sent as a blank array. This field is always excluded if |
9.4.4 Response Record Columns
Normalization records in an SFTP response output file are defined using columns representing the same fields as would appear in the requests array of a Classic endpoint API response. Response record columns are named and behave identically to the corresponding fields in API response payloads.
SFTP response output files may include any of the following normalization record columns, which when applicable are always provided in the same sequence:
record_id, input_term, transformed_term, input_code, input_code_system, <context>, lexical_code, lexical_title, default_lexical_code, default_lexical_title, score, certainty, metadata, discrepancy, domain, match_field, error_message, explanation
-
The record_id, input_term, input_code, and input_code_system columns are always included in the response and echo back the same values from the request record. If a request record had no value for a column, that column position contains only a tab.
-
The transformed_term column is only included in the response if the request metadata line included the
transformationsfield. If present, the response's transformed_term column contains the finalized input term used to match lexicals after the API made any applicable transformations. If no transformation occurred, this column repeats the value from the input_term field.If a lexical match could not be returned for a record for any reason, this column position contains only a tab, regardless of whether a transformation occurred.
-
The <context> placeholder represents one or more columns from the request representing fields from the
contextobject. Each of these columns are only included in the response if they were supplied in the request, and only if at least one request record supplied a value for the column. For each included context column, the response echoes back the value supplied for the request record. If a request record had no value for a column, that column position contains only a tab.If present, context columns are always supplied in the following sequence:
order_name, unit_of_measure, loinc_component, sample_type, loinc_method, loinc_property, loinc_scale, loinc_time, use_count, application_id, facility_id, severity, reaction, source_text
-
The lexical_code, lexical_title, default_lexical_code, and default_lexical_title columns are always included in the response. If a request record has a lexical match, these fields provide the unique identifier and title for both the lexical that directly matched the record input and its default variant.
If a lexical match could not be returned for a record for any reason, these column positions contain only a tab.
-
The score column is always included in the response. If a request record has a lexical match, this field provides a decimal value representing the API's confidence in the lexical match to the record input.
If no lexical match could be identified for an otherwise valid record, this column is sent with a value of 0. For records reporting a fatal error in the
error_messagecolumn, this column position contains only a tab. -
The certainty column is always included in the response, but has been deprecated and always contains an empty string.
-
The metadata column is always included in the response. If a request record has a lexical match, this column contains a JSON object that includes all
metadatafields that would normally be returned in a Classic endpoint API response payload. The entire metadata object is a provided in the response as a single column value.If a lexical match could not be returned for a record for any reason, this column position contains only a tab.
-
The discrepancy column is only included in the response if the request metadata line included the
discrepancyfield set to "true". If present, the discrepancy column contains a JSON object including alldiscrepancyfields normally returned in a Classic endpoint API response payload to report discrepancies between the supplied input code and the matched lexical. The entire discpreancy object is a provided in the response as a single column value.If a lexical match could not be returned for a record for any reason, this column position contains only a tab.
-
The domain column is always included in the response. If a request record has a lexical match, this column identifies the domain to which the matched lexical belongs.
If a lexical match could not be returned for a record for any reason, this column position contains only a tab.
-
The match_field column is always included in the response. If a request record has a lexical match, this column identifies whether the lexical was matched as a result of term-based matching (input_term) or case-based matching (input_code).
If a lexical match could not be returned for a record for any reason, this column position contains only a tab.
-
The error_message column is always included in the response. This column only has a value if the API encountered one or more errors when processing a record. If no error was encountered, this column position contains only a tab.
This column may report any of the same errors returned in the
response.error_messagearray of an API response, as described in 6 Error Messages above. -
The explanation column is always included in the response. This column may report one or more semi-colon separated explanations for decisions taken by the API to interpret or transform the input term, if applicable. If no explanation is required or if a lexical match could not be returned for a record for any reason, this column position contains only a tab.
9.5 SFTP Email Notification
After uploading an SFTP request input file, if the metadata line included a valid email address, then the IMO Precision Normalize engine will send an email to that address when the response output file is available for download. This notification email includes the following information. The content of the Subject and Message Body varies depending on whether the input file was successfully validated without encountering a response level error:
-
Sender: noreplynormalize@imo-online.com
-
Subject:
-
Failure: Processing status for File <RequestInputFileName>
-
Success: File "<RequestInputFileName>" Has Been Normalized Successfully!
-
-
Message Body:
-
Failure:
IMO Precision Normalize has completed processing your file, <RequestInputFileName> and it's ready to be picked up. The file can be retrieved using your organization's SFTP credentials. Please contact IMO Health customer Support if you have any further questions via CustomerSupport@imohealth.com
-
Success: The summary object includes the same content as the output file's response summary line, described in 9.4.3 Response Summary Fields above.
The input file "<RequestInputFileName>" has been normalized successfully and it is ready for download. Here is the summary of the result: { "total_records_processed": 4, "total_error_records": 1, "no_match": 2, "total_custom_mappings": 0, "total_match_includes_assumptions": 0, "total_matches_by_domain": { "problem": { "total": 2, "no_match": 0 } }, "top_10_most_frequent_terms_with_lowest_score": [], "top_10_terms_with_highest_frequency": [] } Please contact IMO Health Customer Support if you have any questions via CustomerSupport@imohealth.com
-
IMO Health Customer Support
IMO Health® Customer Support
Phone: (847) 613-6655
Email: CustomerSupport@imohealth.com
Web: www.imohealth.com
Disclaimers
Advisory Notice
While making all reasonable efforts to ensure accuracy, Intelligent Medical Objects, Inc. assumes no responsibility for errors that may appear in the IMO Health® Precision Normalize user documentation or product. In addition, Intelligent Medical Objects, Inc. assumes no liability with respect to accuracy of codes or data herein.
The information contained in the IMO Precision Normalize user guide is intended to supplement the knowledge of physicians and other health care professionals. This information is advisory only and is not intended to replace sound clinical judgment in the delivery of health care services.
Requirements for Implementation
The license agreement for the IMO Precision Normalize states that this product must be implemented according to the requirements specified in the IMO Precision Normalize documentation. In addition to the requirements set forth herein and any implementation guides or other documentation provided by IMO Health®, additional requirements for implementing IMO Precision Normalize are as follows:
-
The disclaimer notice listed in this document must be included in documentation given to the end user.
-
The copyright statement in the copyright file must be listed on all printed reports that are generated using the IMO Precision Normalize data. For example:
Copyright 2026 Intelligent Medical Objects, Inc. All rights reserved
Notices
The information inside of this guide is confidential and proprietary. Any use of this outside an agreement or engagement with IMO Health® is prohibited.
RxNorm® is a registered trademark of the National Library of Medicine.
LOINC® is a registered United States trademarks of Regenstrief Institute, Inc.
SNOMED and SNOMED CT are registered trademarks of SNOMED International. All rights reserved.
This product includes SNOMED Clinical Terms (SNOMED CT) which is used by permission of SNOMED International.
This material includes ICD-O-3 codes used by permission of WHO, from: International Classification of Diseases for Oncology, Third Edition.
Current Procedural Terminology. CPT® is a registered trademark of the American Medical Association. All rights reserved. Applicable FARS/DFARS Restrictions Apply to Government Use.
Fee schedules, relative value units, conversion factors and/or related components are not assigned by the AMA, are not part of CPT and the AMA is not recommending their use.
The AMA does not directly or indirectly practice medicine or dispense medical services.
The AMA assumes no liability for data contained or not contained herein.
The responsibility for the content of any National Correct Coding Policy included in this product is with the Centers for Medicare and Medicaid Services and no endorsement by the AMA is intended or should be implied. The AMA disclaims responsibility for any consequences or liability to or related to any use, nonuse or interpretation of information contained in this product.
Users of the IMO Behavioral Health add-on may have access to DSM-5 content. The DSM-5 content is reprinted with permission from the Diagnostic and Statistical Manual of Mental Disorders, Fifth Edition TM. Copyright © 2022 American Psychiatric Association ("APA"). All Rights Reserved.
Unless authorized in writing by the APA, DSM-5 content may be reproduced or used in a manner inconsistent with the APA's copyright. This prohibition applies to unauthorized uses or reproductions in any form.
*DSM and DSM-5 are registered trademarks of the American Psychiatric Association, and are used with permission herein. Use of these terms is prohibited without permission of the American Psychiatric Association. Use of this trademark does not constitute endorsement of this product by the American Psychiatric Association.
Use of DSM-5 Content requires appropriate End-Users licenses from the American Psychiatric Association. Additional fees may apply.
UMLS Knowledge Sources [dataset on the Internet]. Release 2024AA. Bethesda (MD): National Library of Medicine (US); 2024 May 6 [cited 2024 Jul 15]. Available from: http://www.nlm.nih.gov/research/umls/licensedcontent/umlsknowledgesources.html
© 2026. IMO Health is a trademark of Intelligent Medical Objects, Inc. All rights reserved
IMO Health® confidential information, not to be shared with third party without IMO Health® consent.