Schema Care

Code System Mapping in Extracted Data

By Schema CarePublished Updated

Code system mapping in extracted data links each printed code to the standard system it belongs to, such as ICD-10-CM, CPT, HCPCS, NDC or CARC, checks it against that system's release, and stores it cleanly. Dates and amounts get normalized first, and any code that fails a check keeps its printed value and goes to a person.

This post describes how to build that layer in your own pipeline. All values in the examples are fictional, and the tables are teaching examples, not output from any product.

Which code systems appear in extracted medical data?

Extracted medical data usually carries seven code systems. Claims carry ICD-10-CM diagnoses, CPT procedures and HCPCS Level II codes, and sometimes NDC drug codes. EOBs and remittances carry CARC and RARC codes. Lab reports may print LOINC codes. Clinical documents can also reference RxNorm or SNOMED CT concepts.

Each system has an owner and a shape you can test:

Code systemWhat it identifiesShapePrimary source
ICD-10-CMDiagnoses3 to 7 charactersCMS ICD-10 code files and the FY 2026 ICD-10-CM Official Guidelines
CPT (HCPCS Level I)Procedures and servicesFive characters, numeric or alphanumericAMA overview of CPT codes
HCPCS Level IIItems and services CPT does not coverOne letter and four digitsCMS HCPCS overview
NDCDrug products and packages10 digits in three segments; 11 digits in HIPAA transactionsFDA presentation on the format of the National Drug Code
CARCWhy a claim or line was paid differently than billedShort code paired with a group code such as CO or PRX12 Claim Adjustment Reason Codes list
RARCExtra explanation or alerts on a remittanceLetter and digitsX12 Remittance Advice Remark Codes list
LOINCLaboratory test orders and resultsSet by the LOINC tableNLM page on LOINC

The sources add detail that matters for validation. The ICD-10-CM guidelines say codes have 3, 4, 5, 6 or 7 characters, and that a code is invalid if it is not coded to the full number of characters it requires. The AMA says CPT Category I codes are numeric, while Category II and Category III codes are alphanumeric. The FDA presentation names three 10-digit layouts in use, 4-4-2, 5-3-2 and 5-4-1, and says HIPAA transactions use an 11-digit 5-4-2 layout made by adding a leading zero to the short segment.

Two clinical terminologies appear less often on billing paperwork but often in records. The NLM overview of RxNorm describes it as a normalized naming system for generic and branded drugs, with an identifier called an RXCUI for each concept. The NLM SNOMED CT page says SNOMED CT is owned by SNOMED International and reaches licensees of the NLM UMLS Metathesaurus. Neither is printed on a typical claim form, so map to them only when a downstream system asks.

Lab test names and their LOINC codes have their own rules, covered in the guide to mapping lab test names to LOINC.

Validating extracted codes against code system releases

Validating an extracted code takes three checks in order: a format check against the system's pattern, an existence check against a specific release, and a date check that the code was valid on the date of service. A code can pass the first check and fail the second, and a real code can still be wrong for the year.

The format check is cheap and catches any reading error that breaks a code's shape. Strip spaces, then test the shape: one letter and four digits for HCPCS Level II, five characters for CPT, 3 to 7 characters for ICD-10-CM. The AMA gives Category I CPT codes a numeric range of 00100 to 99499, so a procedure read as "9921B" on a line that should hold a Category I code fails at once.

The existence check needs the code file. The CMS ICD-10 page publishes code files by fiscal year, and says the 2027 files cover discharges and encounters from October 1, 2026 through September 30, 2027. For a quick lookup during development, the NLM Clinical Table Search Service for ICD-10-CM returns matching codes for a search term, though its page does not state which code year it uses. For production, load the release files yourself so you know exactly which year each answer came from.

The date check is the one most pipelines skip. The CMS page lists April 1 updates as well as October 1 ones, and both CARC and RARC entries on the X12 lists carry a start date and, when retired, a stop date. Store the release you validated against next to every code, and validate against the release that covered the date of service, not today's.

Ten extracted values, before and after

The table below follows ten fictional values from raw text to a normalized value and a validation result.

FieldRaw text on the pageNormalized valueValidation result
Date of service10/02/262026-10-02Valid date; two-digit year expanded by rule, flagged for review
Statement dateOct 9, 20262026-10-09Valid date
Billed amount$1,250.00"1250.00"Pass
Patient balance(45.10)"-45.10"Pass; parentheses read as a credit
ICD-10-CMJ06.9J06.9 (J069 for transmission)Exists in the release
ICD-10-CMS52.5S52.5Fail: only longer codes exist under S52.5
CPT9921399213Format pass; existence checked against the licensed file
NDC1234-5678-9001234567890Format pass; not found in the NDC directory, flagged
CARCCO-45group CO, reason 45Exists, no stop date
CARCCO 15group CO, reason 15Exists but stopped 05/01/2018, flagged

The S52.5 row shows why a format check is not enough. The string has a valid ICD-10-CM shape, but a search of the NLM ICD-10-CM service for S52.5 returns hundreds of longer codes, such as S52.501A, and not S52.5 itself. The X12 list shows reason 15 with a stop date of 05/01/2018, so it should not appear on a recent remittance.

Normalizing dates and amounts before mapping codes

Normalizing dates and amounts means turning printed text into one machine format before any code is mapped. Dates become ISO-style calendar dates such as 2026-10-02, and amounts become exact decimals such as 1250.00. Codes depend on dates, so a date that is wrong makes every later code check wrong too.

For dates, use the full-date form in RFC 3339 on date and time on the internet: a four-digit year, a two-digit month and a two-digit day, joined by hyphens. Four rules cover most printed forms:

  1. Parse with an explicit list of the formats you expect per document type. Never let a library guess.
  2. Treat 10/02/26 as ambiguous. Expand two-digit years with a written rule, and flag the result for review when the date drives a code year or a filing deadline.
  3. Keep date ranges as two fields, a start and an end, even when the page prints one string.
  4. Store the raw text beside the normalized value, so a reviewer can see what the page actually said.

For amounts, avoid floating-point numbers. RFC 8259 on JSON notes that implementations commonly use IEEE 754 double precision and may approximate numbers outside that precision. Money should be exact, so send amounts as decimal strings or as integer cents, with the currency named once. Strip currency symbols and thousands separators, read parentheses or a trailing CR as a credit when the document uses that convention, and keep the sign rules per document type.

Lab results add units, which need their own conversion rules. The guide to normalizing lab result units covers that work.

What should code mapping do with an unknown or retired code?

Code mapping should never replace an unknown or retired code with a guess. Keep the printed value exactly as read, mark it as failing validation with the reason, and send it to a person. A guessed code that looks valid is worse than a blank, because nothing downstream will question it.

Three cases need different handling:

  • Unknown code. The value has the right shape but no match in the release. Often the page was misread, as with a 6 read as a G. The reviewer checks the page and either corrects the reading or confirms the printed code.
  • Incomplete code. The value exists only as a category heading, like S52.5. The ICD-10-CM guidelines call such a code invalid. The fix comes from the document or the coder, never from picking the first longer match.
  • Retired code. The value existed but has a stop date before the date of service. On an old EOB this may be correct for its time. Record the release that contained it.

A useful rule is that mapping code may add facts but never overwrite them. It can add a description, a release year or a crosswalk target. It cannot change the printed code itself. The same rule applies to remittance codes, whose meaning is covered in the guide to remittance advice remark codes.

Flagged values need a route to a person and back. The guide to confidence scores in API responses shows one way to mark a field for review in a response, and the guide to webhooks for document processing covers how a caller learns that the review is finished. The decision about which code to bill belongs to coding staff, which the post on medical coding automation discusses.

Schema Care handles the reading half of this problem. It reads diagnosis and procedure codes from claims and remark codes from EOBs, scores its confidence in each field, and sends the uncertain ones to a reviewer who sees the value highlighted on the page, as the human review steps show. The validation layer described here is yours to build: Schema Care offers no API, SDK, webhooks, FHIR output, 835 output or 837 output.

Code system mapping tables and their upkeep

Code system mapping tables need an owner and a calendar. Each system releases on its own schedule, so a crosswalk loaded once and never refreshed slowly turns valid codes into errors and lets retired ones through. Assign one person or team to each system, and record which release every table holds.

The schedules come from the publishers:

Code systemHow often it changes, per its publisher
ICD-10-CMFiscal-year files starting October 1, with April 1 updates also listed on the CMS ICD-10 page
CPTThe AMA says the CPT Editorial Panel meets three times a year
HCPCS Level IICMS links a HCPCS quarterly update file
NDCThe FDA NDC Directory page says the directory is updated daily
RxNormNLM releases the full set on the first Monday of each month, with weekly updates
CARC and RARCEach X12 entry has start, last modified and stop dates

One change is far ahead but large. The FDA NDC Directory page says a final rule adopts a uniform 12-digit NDC format and takes effect March 7, 2033. Any table or column that assumes 10 or 11 digits will need work before then.

Practical upkeep habits:

  • Load release files into versioned tables, one version per release, rather than overwriting.
  • Keep old versions, because old documents need old releases.
  • Rerun validation on held items after each new release. A code that failed last week may exist now.
  • Log every crosswalk change with who made it and when, so a later question about a mapping has an answer.
  • Respect licenses. CPT is maintained by the AMA, and NLM distributes SNOMED CT through UMLS licensing, so check terms before loading them into a product.

All posts in APIs, FHIR and Integration