FHIR ConceptMap for Cross-Border Code Translation
FHIR ConceptMap for Cross-Border Code Translation
FHIR promised interoperability. ConceptMap was built to deliver it across coding systems. But almost nobody has implemented it for the actual cross-border use cases that break international patient data every day.
A German hospital discharges a patient. Her summary uses ICD-10-GM diagnosis codes, OPS procedure codes, and PZN drug identifiers. She travels to the United States. The receiving health system speaks ICD-10-CM, CPT, and NDC. The codes are not language problems — they are system problems.
FHIR has a standard mechanism for exactly this: ConceptMap and its companion operation, $translate. The problem isn’t the specification. The problem is that building ConceptMaps at scale — across 47 countries, 18 coding domains, hundreds of coding systems — requires data that most health IT teams don’t have.
This post explains how ConceptMap works, why the cross-border gap exists, and how Atlas MedCode fills it with a FHIR-native $translate endpoint ready to drop into your existing FHIR server.
What is ConceptMap?
ConceptMap is a FHIR R4 resource that defines mappings between concepts in different coding systems. Where a ValueSet says “these codes belong together” and a CodeSystem says “these codes exist,” a ConceptMap says “this code in system A corresponds to that code in system B.”
A minimal ConceptMap has:
- A source ValueSet or URI — the coding system you’re translating from
- A target ValueSet or URI — the coding system you’re translating to
- A set of groups, each containing elements (source codes) and their targets (equivalent codes in the destination system)
- An equivalence for each mapping:
equivalent,wider,narrower,inexact, orunmatched
The $translate operation accepts a code, a source system, and a target system, and returns the mapped code along with the equivalence relationship and any relevant comments.
This is not a new concept. Health IT developers have used ConceptMap for years to translate between SNOMED and ICD-10, or between local coding systems and national standards. What’s new is doing it across national boundaries at scale.
The Cross-Border Gap
The FHIR specification never assumed that code translation would stay within one country. ConceptMap was built with the explicit goal of enabling cross-system translation, including international crosswalks. But in practice, published ConceptMaps stop at national borders.
The National Library of Medicine publishes ConceptMaps between ICD-10-CM and SNOMED CT. CMS publishes mappings between ICD-9-CM and ICD-10-CM. The German BfArM publishes ICD-10-GM. But there is no authoritative cross-walk between ICD-10-GM and ICD-10-CM. No standard ConceptMap exists for OPS-to-CPT, ATC-to-NDC, or FDI-to-CDT dental codes.
The result: every health system that receives international patients builds the same mappings independently — or doesn’t build them at all.
Across 47 countries, 18 medical coding domains, and hundreds of distinct national coding systems, the combinations are not trivially enumerable. A hub-and-spoke architecture — where each national system maps to a canonical pivot code, and all translations go through the pivot — is the only approach that scales to O(n) rather than O(n²) mapping pairs. But that architecture requires curated, validated data for each spoke.
This is the gap Atlas MedCode fills.
How Atlas MedCode Implements $translate
Atlas MedCode exposes a FHIR R4-compliant $translate endpoint at api.translatemed.io/fhir/ConceptMap/$translate. It covers:
- Diagnoses: ICD-10-GM ↔ ICD-10-CM, ICD-10-GM ↔ ICD-11, plus 18 national variants
- Procedures: OPS ↔ CPT, ICD-9-CM-PL ↔ CPT, CCAM ↔ CPT, and other country-pair crosswalks
- Drugs: ATC ↔ NDC, ATC ↔ PZN, ATC ↔ local formulary codes
- Dental: FDI ↔ CDT (Universal Numbering), FDI ↔ Palmer notation
- Lab: LOINC (shared globally, with unit and reference range annotations per country)
Each translation returns a FHIR Parameters resource with the mapped code, the equivalence relationship, the confidence score, and — where the mapping is many-to-one or requires clinical judgment — a human-readable comment explaining the ambiguity.
The endpoint is stateless, token-authenticated, and available on Team and Enterprise plans.
Real Example: Mapping ICD-10-GM J45.0 to ICD-10-CM
ICD-10-GM J45.0 is “predominantly allergic bronchial asthma.” In the German system, asthma is classified by predominant mechanism. ICD-10-CM has no J45.0 — its asthma codes are organized differently, by severity and control status.
Here is a $translate request:
POST /fhir/ConceptMap/$translate
Authorization: Bearer <your-api-key>
Content-Type: application/fhir+json
{
"resourceType": "Parameters",
"parameter": [
{
"name": "code",
"valueCode": "J45.0"
},
{
"name": "system",
"valueUri": "http://fhir.de/CodeSystem/bfarm/icd-10-gm"
},
{
"name": "targetSystem",
"valueUri": "http://hl7.org/fhir/sid/icd-10-cm"
}
]
}
The response:
{
"resourceType": "Parameters",
"parameter": [
{
"name": "result",
"valueBoolean": true
},
{
"name": "match",
"part": [
{
"name": "equivalence",
"valueCode": "wider"
},
{
"name": "concept",
"valueCoding": {
"system": "http://hl7.org/fhir/sid/icd-10-cm",
"code": "J45.20",
"display": "Mild intermittent asthma, uncomplicated"
}
},
{
"name": "source",
"valueUri": "https://api.translatemed.io/fhir/ConceptMap/icd10gm-to-icd10cm"
},
{
"name": "comment",
"valueString": "J45.0 (allergic asthma, GM) maps to J45.20 (mild intermittent, CM) as the closest clinical equivalent. CM requires severity/control status; a more specific mapping may be possible with additional clinical data."
}
]
}
]
}
The wider equivalence tells your system that the source concept is more specific than the target — the German code carries information (allergic mechanism) that CM doesn’t capture in the same way. The comment explains what’s been lost and what additional data might permit a more precise mapping. This is semantically correct FHIR behavior, not a limitation to paper over.
Beyond Diagnosis: Procedures, Drugs, and Dental
The same $translate endpoint handles all supported domains. The coding system URI in the request determines which ConceptMap is invoked.
OPS → CPT (German procedures to US billing codes):
OPS 5-470.10 (appendectomy, laparoscopic, without complications) maps to CPT 44950 or 44970 depending on approach specifics. The endpoint returns both candidates with confidence scores when the mapping is ambiguous.
ATC → NDC (WHO drug classification to US drug identifiers):
ATC code A10BA02 (metformin) maps to a range of NDC codes representing different manufacturers and formulations. The endpoint returns the canonical match with a note that NDC is manufacturer-specific and a current NDC lookup may be needed for dispensing.
FDI → CDT (international dental numbering to US Universal system):
FDI tooth 16 (upper right first molar in international numbering) maps to US tooth 3 in the Universal Numbering System. FDI 46 maps to US 30. These are precise, unambiguous mappings — equivalence is equivalent.
Each domain uses the same FHIR operation signature. Your client code doesn’t change based on what you’re translating. The system URI does the routing.
Integration: Adding $translate to Your FHIR Server
Most FHIR servers support custom operation endpoints via the $ operation convention. Integration requires:
1. Delegate terminology operations to Atlas MedCode
Configure your FHIR server’s terminology service URL to proxy ConceptMap/$translate requests to api.translatemed.io. Firely Server, HAPI FHIR, and Azure Health Data Services all support external terminology service delegation via configuration.
Example HAPI FHIR server configuration:
hapi:
fhir:
tester:
home:
name: Local Tester
server_address: http://localhost:8080/fhir
terminology-service:
url: https://api.translatemed.io/fhir
2. Use the TypeScript SDK for direct integration
If you’re building a FHIR client or middleware layer, the @atlasmedcode/sdk package wraps the $translate operation:
import { AtlasMedCode } from "@atlasmedcode/sdk";
const client = new AtlasMedCode({ apiKey: process.env.ATLAS_API_KEY });
const result = await client.translate({
code: "J45.0",
system: "http://fhir.de/CodeSystem/bfarm/icd-10-gm",
targetSystem: "http://hl7.org/fhir/sid/icd-10-cm",
});
console.log(result.match?.concept.code); // "J45.20"
console.log(result.match?.equivalence); // "wider"
The SDK also exposes searchCodes() for free-text lookup and validateCode() for checking that a code exists in a given system.
3. Handle equivalence in your application logic
Not all translations are equivalent. Build your downstream logic to handle:
equivalent— safe to use directlywider/narrower— use the code, but flag for clinical reviewinexact— requires human confirmation before clinical useunmatched— no mapping exists; escalate to manual review
This is the FHIR standard behavior. Atlas MedCode populates it accurately rather than silently returning best-guess matches.
Start Translating Cross-Border Codes Today
FHIR ConceptMap has always been the right abstraction for cross-border code translation. The missing piece was the data — curated, validated, coverage-verified mappings across 47 countries and 18 medical coding domains.
- Try the API: Interactive documentation and a live test console at api.translatemed.io
- TypeScript SDK:
npm install @atlasmedcode/sdk— FHIR-native client with full type coverage - Coverage details: Supported country pairs, coding systems, and equivalence breakdowns in the developer portal
- Team and Enterprise plans: ConceptMap/$translate is available on Team+ subscriptions; Enterprise adds custom ConceptMap definitions and on-premise deployment
If you’re building international FHIR infrastructure and hitting the cross-border code wall, this is the endpoint you’ve been waiting for.