Skip to main content

1. The “Paperwork Tax”

Every insurance claim tells two stories. The billing story: a list of CPT, ICD-10, and HCPCS codes, optimized for reimbursement. The clinical story: what actually happened to the patient and why. The gap between these two stories is where billions of dollars in administrative waste, payment delays, and fraud live. A CPT code for an “Office Visit” doesn’t explain why the patient was there. An ICD-10 code for “M05.79” means “Rheumatoid arthritis with rheumatoid factor, multiple sites” - but only if you know ICD-10. And a HCPCS J-code for a biologic drug tells you the molecule, not whether it was clinically appropriate for the patient’s condition. Bridging this divide starts with a basic but powerful step: standardizing the codes. OMOP’s vocabulary structure maps billing codes (ICD-10-CM, CPT-4, HCPCS) to clinically rich standard concepts (SNOMED for conditions/procedures, RxNorm for drugs) via “Maps to” relationships. Once standardized, you can start asking clinical questions about administrative data. OMOPHub makes this standardization step fast and programmatic. It’s a REST API for the OHDSI ATHENA vocabularies - so instead of maintaining a local vocabulary database, you look up a billing code, get its standard OMOP concept, and immediately have access to the clinical hierarchy, relationships, and cross-vocabulary mappings. The pattern: billing code → OMOPHub search → standard concept ID → clinical context. What OMOPHub does not do: it doesn’t determine medical necessity, detect fraud, or adjudicate claims. Those require clinical rules engines, indication databases (like FDB or DrugBank), and CMS edit tables (like CCI/NCCI). OMOPHub handles the vocabulary layer - translating billing codes into a standardized clinical language that those downstream systems can work with.

2. The Core Concept: Reconstructing the Clinical Event

An insurance claim is a bundle of billing codes representing a clinical encounter. OMOPHub helps you unpack that bundle into standardized clinical components:
  • Procedure performed → CPT-4 code → maps to SNOMED Procedure concept
  • Diagnosis justifying the procedure → ICD-10-CM code → maps to SNOMED Condition concept
  • Drug or device administered → HCPCS J-code or NDC → maps to RxNorm Drug concept
The “Maps to” relationships in the OMOP vocabulary are the bridge. Multiple billing codes can map to the same standard concept (many-to-one), and a single billing code can occasionally map to multiple standard concepts (one-to-many). OMOPHub’s search and mappings APIs let you traverse these relationships programmatically. Once you have standard concept IDs, you can:
  • Look up concept hierarchies (is this drug an anti-TNF agent?)
  • Check concept relationships (what ingredient does this drug contain?)
  • Compare across claims (different billing codes, same clinical event)
This standardization is the foundation. Everything else - necessity review, fraud detection, risk adjustment - builds on top of it.

3. Use Case A: Standardizing a Claim for Medical Necessity Review

Medical necessity review asks: is this billed drug clinically appropriate for this diagnosed condition? The first step is standardizing both the drug and the diagnosis. The Scenario: A claim arrives with HCPCS code J0135 (Adalimumab/Humira) and ICD-10-CM code M05.79 (Rheumatoid arthritis with rheumatoid factor, multiple sites). You need to resolve both to standard OMOP concepts. Code Snippet: Standardizing Billing Codes via OMOPHub
pip install omophub
Python
import omophub

client = omophub.OMOPHub()

# Billing codes from the claim
claim_drug_code = "J0135"       # HCPCS: Adalimumab injection
claim_diag_code = "M05.79"     # ICD-10-CM: RA with rheumatoid factor, multiple sites

print("Standardizing claim billing codes...\n")

# --- Step 1: Resolve the drug (HCPCS → RxNorm) ---
print(f"Drug: HCPCS {claim_drug_code}")
try:
    # Search for the HCPCS code in OMOPHub
    drug_search = client.search.basic(
        claim_drug_code,
        vocabulary_ids=["HCPCS"],
        page_size=1,
    )
    drug_candidates = drug_search.get("concepts", []) if drug_search else []

    drug_standard_id = None
    if drug_candidates:
        hcpcs_concept = drug_candidates[0]
        hcpcs_id = hcpcs_concept["concept_id"]
        print(f"  Found: {hcpcs_concept.get('concept_name')} (OMOP ID: {hcpcs_id})")

        # Get the "Maps to" standard concept
        drug_mappings = client.mappings.get(hcpcs_id, target_vocabulary="RxNorm")
        drug_map_list = (
            drug_mappings if isinstance(drug_mappings, list)
            else drug_mappings.get("concepts", drug_mappings.get("mappings", []))
        ) if drug_mappings else []

        if drug_map_list:
            standard_drug = drug_map_list[0]
            drug_standard_id = standard_drug["concept_id"]
            print(f"  -> Standard RxNorm: {standard_drug.get('concept_name')} (ID: {drug_standard_id})")
        else:
            print(f"  -> No RxNorm mapping found. Checking if already standard...")
            # HCPCS drug codes sometimes are their own standard concept
            if hcpcs_concept.get("standard_concept") == "S":
                drug_standard_id = hcpcs_id
                print(f"  -> Using HCPCS concept as standard (ID: {drug_standard_id})")
    else:
        print(f"  Not found in OMOPHub")

except omophub.APIError as e:
    print(f"  API error: {e.message}")

# --- Step 2: Resolve the diagnosis (ICD-10-CM → SNOMED) ---
print(f"\nDiagnosis: ICD-10-CM {claim_diag_code}")
try:
    diag_search = client.search.basic(
        claim_diag_code,
        vocabulary_ids=["ICD10CM"],
        page_size=1,
    )
    diag_candidates = diag_search.get("concepts", []) if diag_search else []

    diag_standard_id = None
    if diag_candidates:
        icd_concept = diag_candidates[0]
        icd_id = icd_concept["concept_id"]
        print(f"  Found: {icd_concept.get('concept_name')} (OMOP ID: {icd_id})")

        # Get the "Maps to" standard SNOMED concept
        diag_mappings = client.mappings.get(icd_id, target_vocabulary="SNOMED")
        diag_map_list = (
            diag_mappings if isinstance(diag_mappings, list)
            else diag_mappings.get("concepts", diag_mappings.get("mappings", []))
        ) if diag_mappings else []

        if diag_map_list:
            standard_diag = diag_map_list[0]
            diag_standard_id = standard_diag["concept_id"]
            print(f"  -> Standard SNOMED: {standard_diag.get('concept_name')} (ID: {diag_standard_id})")
        else:
            print(f"  -> No SNOMED mapping found")
    else:
        print(f"  Not found in OMOPHub")

except omophub.APIError as e:
    print(f"  API error: {e.message}")

# --- Step 3: Explore relationships (for context, NOT for necessity determination) ---
if drug_standard_id:
    print(f"\nDrug concept relationships:")
    try:
        drug_rels = client.concepts.relationships(drug_standard_id)
        rel_list = (
            drug_rels if isinstance(drug_rels, list)
            else drug_rels.get("relationships", [])
        ) if drug_rels else []
        for rel in rel_list[:5]:
            print(f"  {rel.get('relationship_id', 'N/A')}: {rel.get('concept_name', 'N/A')}")
        if len(rel_list) > 5:
            print(f"  ... and {len(rel_list) - 5} more relationships")
    except omophub.APIError:
        pass

# --- Important limitation ---
print("\n--- Medical Necessity Determination ---")
print("OMOPHub standardizes billing codes to clinical concepts.")
print("To determine medical necessity (is Adalimumab indicated for RA?),")
print("you need an external drug indications database:")
print("  - FDB First Databank")
print("  - DrugBank")
print("  - DailyMed / FDA label data")
print("  - Medi-Span")
print("OMOP vocabularies do NOT contain 'treats' or 'indicated for' relationships.")
The Key Insight: OMOPHub gets you from billing codes to standard clinical concepts in two API calls per code. That’s the essential first step - without it, you’re comparing HCPCS strings to ICD-10 strings, which tells you nothing clinically. With standardized concepts, you can feed them into an indications database to check medical necessity, or into a risk adjustment model for accurate scoring. OMOPHub handles the translation layer; the clinical decision logic lives elsewhere.

4. Use Case B: Code Standardization for Fraud Detection

Fraud, Waste, and Abuse (FWA) detection - particularly “unbundling” (billing component procedures separately instead of using a comprehensive code) - requires comparing what was billed against what should have been billed. The Scenario: A claim includes CPT 10060 (I&D abscess, simple) and CPT 10061 (I&D abscess, complicated) for the same patient visit. Are these legitimately separate procedures, or is this unbundling? The Reality: This question can’t be answered by vocabulary hierarchies alone. The authoritative source for billing bundling rules is the CMS Correct Coding Initiative (CCI/NCCI) edit tables, which specify exactly which code pairs can and cannot be billed together. OMOP vocabularies don’t contain these rules. Where OMOPHub helps: Standardizing the CPT codes so they can be looked up against CCI edit tables and clinical context.
Python
import omophub

client = omophub.OMOPHub()

# CPT codes from a suspicious claim
claim_cpt_codes = ["10060", "10061"]

print("Standardizing CPT codes for FWA analysis...\n")

standardized = []

for cpt_code in claim_cpt_codes:
    try:
        results = client.search.basic(
            cpt_code,
            vocabulary_ids=["CPT4"],
            page_size=1,
        )
        candidates = results.get("concepts", []) if results else []

        if candidates:
            concept = candidates[0]
            omop_id = concept["concept_id"]
            name = concept.get("concept_name", "Unknown")
            print(f"  CPT {cpt_code}: {name} (OMOP ID: {omop_id})")

            standardized.append({
                "cpt_code": cpt_code,
                "omop_id": omop_id,
                "concept_name": name,
            })

            # Get the standard concept mapping (CPT4 → SNOMED Procedure)
            mappings = client.mappings.get(omop_id, target_vocabulary="SNOMED")
            map_list = (
                mappings if isinstance(mappings, list)
                else mappings.get("concepts", mappings.get("mappings", []))
            ) if mappings else []

            if map_list:
                std = map_list[0]
                print(f"    -> SNOMED: {std.get('concept_name')} (ID: {std['concept_id']})")
                standardized[-1]["snomed_id"] = std["concept_id"]
                standardized[-1]["snomed_name"] = std.get("concept_name")
        else:
            print(f"  CPT {cpt_code}: Not found")

    except omophub.APIError as e:
        print(f"  CPT {cpt_code}: API error - {e.message}")

# --- FWA analysis requires external data ---
print("\n--- Unbundling Analysis ---")
print("To determine if these CPT codes represent unbundling:")
print("  1. Look up the code pair in CMS CCI/NCCI edit tables")
print("  2. Check modifier indicators (some pairs are allowed with modifiers)")
print("  3. Review anatomical site documentation")
print()
print("OMOPHub's role: standardize codes so they can be matched against CCI edits.")
print("CCI edit tables must be maintained separately (available from CMS.gov).")

if len(standardized) >= 2:
    print(f"\nCode pair for CCI lookup:")
    print(f"  Column 1: CPT {standardized[0]['cpt_code']} ({standardized[0]['concept_name']})")
    print(f"  Column 2: CPT {standardized[1]['cpt_code']} ({standardized[1]['concept_name']})")
    print(f"  -> Check NCCI PTP edits for this pair")
The Key Insight: OMOPHub standardizes billing codes - that’s its job. Unbundling detection requires CCI edit tables, which are billing policy rules, not vocabulary relationships. The workflow is: OMOPHub resolves codes to standard concepts → CCI edits determine if the code pair is allowed → clinical context (from SNOMED hierarchy) provides supporting evidence. Each tool does what it’s built for.

5. The “Clinical Context” Enrichment Layer

Once billing codes are standardized, OMOPHub’s vocabulary features can add clinical context that pure billing data lacks: Hierarchy for severity inference: A diagnosis of “Type 2 diabetes mellitus with diabetic chronic kidney disease” (a specific SNOMED descendant) tells you more about severity than just “Type 2 diabetes.” OMOPHub’s hierarchy API reveals where a concept sits in the clinical tree - deeper = more specific = often more severe. Relationships for care expectations: Using concepts.relationships(), you can discover what measurements, procedures, or findings are associated with a condition in the OMOP vocabulary. A diabetes diagnosis has relationships to HbA1c measurements, foot exam procedures, and eye exam referrals - all quality metrics that payers track. Cross-vocabulary mapping for completeness: A claim might use ICD-10-CM codes, but quality measures are often defined in SNOMED. OMOPHub’s mappings ensure you can bridge between what was billed and what’s being measured. These enrichments don’t replace clinical judgment or rules engines, but they provide the standardized vocabulary substrate that those systems need to function. The more context you attach to a claim at the vocabulary level, the smarter your downstream analytics become.

6. Conclusion: From Billing Codes to Clinical Understanding

The billing-clinical divide isn’t going away - ICD-10, CPT, and HCPCS serve a different purpose than SNOMED and RxNorm. But the translation between them doesn’t have to be manual. OMOPHub handles the vocabulary translation layer: billing code → search → standard concept ID → hierarchy, relationships, and mappings. This standardization is the prerequisite for every downstream application - medical necessity review (with external indications data), fraud detection (with CCI edit tables), risk adjustment (with clinical severity hierarchies), and quality measurement (with standard measure definitions). The pattern is the same across all these applications: standardize first, analyze second. OMOPHub makes the “standardize first” part fast and programmatic. The “analyze second” part requires domain-specific tools and rules - but they all work better when the vocabulary layer is clean. Start with a real claim. Map its CPT, ICD-10, and HCPCS codes through OMOPHub. See what standard concepts come back, what hierarchies they belong to, and what relationships they have. That clinical context, invisible in the raw billing data, is where the value lives.