Each non-pharmacy EOB can produce one or more Procedure resources conforming to the US Core 6.1 Procedure profile. The Da Vinci PDex Procedure mapping serves as a loose starting point, with additional logic for item-level extraction and procedural code classification.
#Code sources
Procedure codes are extracted from two locations on each EOB:
eob.procedure[] — explicit procedures the payer coded on the claim, trusted as-is
eob.item[].productOrService — line-item codes filtered to procedural services only (surgeries, imaging, therapeutic interventions, diagnostics)
Non-procedural services — E/M visits, lab tests, supplies, drugs, and transport — are excluded from item-level extraction. Recognized procedural code systems include CPT, HCPCS, ICD-10-PCS, and CDT.
#Deduplication
Procedures are deduplicated differently depending on their source.
Explicit procedures from eob.procedure[] (Phase 1) are not deduplicated — each entry is trusted as a distinct procedure.
Item-level procedures (Phase 2) are deduplicated by base code + service date, so the same code on different dates produces distinct Procedure resources (separate sessions), while the same code on the same date is collapsed.
Cross-phase deduplication skips item-level codes that were already extracted from eob.procedure[].
Several signals override this default collapsing:
- Distinct procedure modifiers — CMS modifiers like
59 (distinct procedural service), 50 (bilateral), 76/77 (repeat procedure) indicate genuinely separate procedures even with the same code and date
- Body site — the same code on the same date but on different body sites (e.g., dental procedures on different teeth) produces distinct Procedures
- Oral/dental claims — each line item on an
oral claim type is treated as a separate procedure, since dental claims typically represent one procedure per tooth/site
#Code normalization
Some payers concatenate modifiers onto CPT codes (e.g., 72100TC, 7210026). The pipeline extracts the base 5-digit code before classification and deduplication. Category III CPT codes (4 digits + T, e.g., 0296T) are also recognized as procedural. Contradictory data-absent-reason extensions are stripped when a valid code exists.
#Deterministic IDs
Procedure IDs are deterministic UUIDv5 hashes derived from the EOB ID and a stable key — the payer-assigned sequence number for explicit procedures, or the base code + date for item-level procedures. This ensures idempotent output across re-syncs even if array order changes.
ID = UUIDv5(destinationPatientId, eobId + ":procedure:" + key)
#Encounter linkage
Every generated Procedure includes an encounter reference pointing to the Encounter generated from the same EOB. Generated Conditions are also appended to the Encounter's reasonReference, creating a bidirectional link between the visit and its clinical context.
The procedure date is resolved with fallback logic and sentinel date filtering:
- Explicit procedures:
procedure.date → billablePeriod.start
- Item-level:
item.servicedDate → item.servicedPeriod.start → billablePeriod.start
- Sentinel dates (1900-01-01, 2078-12-31, 9999-12-31) are skipped at each candidate
- Missing: Data Absent Reason extension when status is
completed (US Core us-core-7 invariant)
#Payer data quality
Payers frequently miscategorize CDT (dental) codes under CPT or HCPCS system URIs. The pipeline detects CDT codes by pattern (e.g., D2740) regardless of the declared code system, ensuring dental procedures are correctly identified and generated.