This document describes the hierarchical structure and parsing logic for X12 834 Benefit Enrollment transactions in HCCInFHIR.
X12 834 Benefit Enrollment Transaction
══════════════════════════════════════════════════════════════════════════════
┌─────────────────────────────────────────────────────────────────────────────┐
│ INTERCHANGE ENVELOPE (ISA/IEA) │
├─────────────────────────────────────────────────────────────────────────────┤
│ ISA ─── Interchange Control Header │
│ ├── ISA06: Sender ID ──────────────────────────► source │
│ └── ISA09: Date (YYMMDD) ──────────────────────► report_date │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ FUNCTIONAL GROUP (GS/GE) │ │
│ ├─────────────────────────────────────────────────────────────────────────┤ │
│ │ GS ─── Functional Group Header │ │
│ │ ├── GS02: Sender Code ────────────────────────► source (fallback)│ │
│ │ ├── GS04: Date (YYYYMMDD) ────────────────────► report_date │ │
│ │ └── GS08: Version ────────────────────────────► validation │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
│ │ │ TRANSACTION SET (ST/SE) - Loop 0000 │ │ │
│ │ ├─────────────────────────────────────────────────────────────────────┤ │ │
│ │ │ ST*834 ─ Transaction Set Header │ │ │
│ │ │ │ │ │
│ │ │ BGN ───── Beginning Segment │ │ │
│ │ │ └── BGN02: Reference ID ─────────────────► source prefix │ │ │
│ │ │ │ │ │
│ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │
│ │ │ │ SPONSOR/PAYER LOOP - Loop 1000A/1000B │ │ │ │
│ │ │ ├─────────────────────────────────────────────────────────────────┤ │ │ │
│ │ │ │ N1*IN ── Plan/Insurer Name │ │ │ │
│ │ │ │ └── N102: Plan Name ────────────────────► SLA prefix │ │ │ │
│ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │
│ │ │ │ │ │
│ │ │ ╔═════════════════════════════════════════════════════════════════╗ │ │ │
│ │ │ ║ MEMBER LOOP - Loop 2000 (repeats per member) ║ │ │ │
│ │ │ ╠═════════════════════════════════════════════════════════════════╣ │ │ │
│ │ │ ║ ║ │ │ │
│ │ │ ║ INS ───── Member Level Detail (LOOP START TRIGGER) ║ │ │ │
│ │ │ ║ ├── INS03: Maintenance Type ───────► maintenance_type ║ │ │ │
│ │ │ ║ │ (001=Change, 021=Add, 024=Cancel) ║ │ │ │
│ │ │ ║ ├── INS04: Maintenance Reason ─► maintenance_reason ║ │ │ │
│ │ │ ║ ├── INS05: Benefit Status ─────► benefit_status_code ║ │ │ │
│ │ │ ║ └── INS11/12: Death Date ──────► death_date ║ │ │ │
│ │ │ ║ (when INS11=D8, INS12=YYYYMMDD) ║ │ │ │
│ │ │ ║ ║ │ │ │
│ │ │ ║ ┌───────────────────────────────────────────────────────────┐ ║ │ │ │
│ │ │ ║ │ REF SEGMENTS (multiple, various qualifiers) │ ║ │ │ │
│ │ │ ║ ├───────────────────────────────────────────────────────────┤ ║ │ │ │
│ │ │ ║ │ REF*0F ── Subscriber Number ───────────────► member_id │ ║ │ │ │
│ │ │ ║ │ REF*6P ── Medicare Beneficiary ID ─────────► mbi │ ║ │ │ │
│ │ │ ║ │ REF*F6 ── Medicare HICN ───────────────────► hic │ ║ │ │ │
│ │ │ ║ │ REF*1D ── Medicaid ID ─────────────────────► medicaid_id │ ║ │ │ │
│ │ │ ║ │ REF*AB ── Medi-Cal Aid Code ───────────────► aid_code │ ║ │ │ │
│ │ │ ║ │ REF*ABB ─ Medicare Status (QMB/SLMB/QI) ──► dual status │ ║ │ │ │
│ │ │ ║ │ REF*F5 ── Dual Eligibility Code ───────────► dual_elgbl_cd│ ║ │ │ │
│ │ │ ║ │ REF*DY ── CREC Code ───────────────────────► crec │ ║ │ │ │
│ │ │ ║ │ REF*EJ ── Low Income Flag ─────────────────► low_income │ ║ │ │ │
│ │ │ ║ │ │ ║ │ │ │
│ │ │ ║ │ CA DHCS Specific (composite values with semicolons): │ ║ │ │ │
│ │ │ ║ │ REF*23 ── CIN;Card_Issue_Date ────► cin, card_issue_date │ ║ │ │ │
│ │ │ ║ │ REF*3H ── County;AID;Case# ───────► county, aid, case_num │ ║ │ │ │
│ │ │ ║ │ REF*6O ── Address Flags ──────────► res_addr_flag, etc. │ ║ │ │ │
│ │ │ ║ │ REF*DX ── Contract;Carrier;Start ─► fed_contract, carrier │ ║ │ │ │
│ │ │ ║ │ REF*17 ── FAME Dates (composite): │ ║ │ │ │
│ │ │ ║ │ ├── Pos 0: Redetermination ──► fame_redetermination│ ║ │ │ │
│ │ │ ║ │ └── Pos 1: Death Date ───────► fame_death_date │ ║ │ │ │
│ │ │ ║ └───────────────────────────────────────────────────────────┘ ║ │ │ │
│ │ │ ║ ║ │ │ │
│ │ │ ║ ┌───────────────────────────────────────────────────────────┐ ║ │ │ │
│ │ │ ║ │ MEMBER NAME LOOP - Loop 2100A │ ║ │ │ │
│ │ │ ║ ├───────────────────────────────────────────────────────────┤ ║ │ │ │
│ │ │ ║ │ NM1*IL ── Insured/Member Name │ ║ │ │ │
│ │ │ ║ │ ├── NM103: Last Name ────────────► last_name │ ║ │ │ │
│ │ │ ║ │ ├── NM104: First Name ───────────► first_name │ ║ │ │ │
│ │ │ ║ │ ├── NM105: Middle Name ──────────► middle_name │ ║ │ │ │
│ │ │ ║ │ └── NM109: Member ID ────────────► member_id │ ║ │ │ │
│ │ │ ║ │ │ ║ │ │ │
│ │ │ ║ │ PER ───── Contact Information │ ║ │ │ │
│ │ │ ║ │ └── PER*TE: Phone ───────────────► phone │ ║ │ │ │
│ │ │ ║ │ │ ║ │ │ │
│ │ │ ║ │ N3 ────── Street Address │ ║ │ │ │
│ │ │ ║ │ ├── N301: Address Line 1 ────────► address_1 │ ║ │ │ │
│ │ │ ║ │ └── N302: Address Line 2 ────────► address_2 │ ║ │ │ │
│ │ │ ║ │ │ ║ │ │ │
│ │ │ ║ │ N4 ────── City/State/Zip │ ║ │ │ │
│ │ │ ║ │ ├── N401: City ──────────────────► city │ ║ │ │ │
│ │ │ ║ │ ├── N402: State ─────────────────► state │ ║ │ │ │
│ │ │ ║ │ ├── N403: Zip ───────────────────► zip │ ║ │ │ │
│ │ │ ║ │ └── N406*CY: County ─────────────► county_id │ ║ │ │ │
│ │ │ ║ │ │ ║ │ │ │
│ │ │ ║ │ DMG ───── Demographics │ ║ │ │ │
│ │ │ ║ │ ├── DMG02: DOB (YYYYMMDD) ───────► dob │ ║ │ │ │
│ │ │ ║ │ ├── DMG03: Sex (M/F) ────────────► sex │ ║ │ │ │
│ │ │ ║ │ └── DMG05: Race Code ────────────► race (→name) │ ║ │ │ │
│ │ │ ║ │ │ ║ │ │ │
│ │ │ ║ │ LUI ───── Language │ ║ │ │ │
│ │ │ ║ │ └── LUI02: Language Code ────────► language │ ║ │ │ │
│ │ │ ║ └───────────────────────────────────────────────────────────┘ ║ │ │ │
│ │ │ ║ ║ │ │ │
│ │ │ ║ ┌───────────────────────────────────────────────────────────┐ ║ │ │ │
│ │ │ ║ │ MEMBER DATES - Loop 2100A (DTP segments) │ ║ │ │ │
│ │ │ ║ ├───────────────────────────────────────────────────────────┤ ║ │ │ │
│ │ │ ║ │ DTP*348 ─ Coverage Start Date ─────────► coverage_start │ ║ │ │ │
│ │ │ ║ │ DTP*349 ─ Coverage End Date ───────────► coverage_end │ ║ │ │ │
│ │ │ ║ │ (also derives medi_cal_eligibility_status) │ ║ │ │ │
│ │ │ ║ │ DTP*338 ─ Medicare Effective Date ─────► has_medicare │ ║ │ │ │
│ │ │ ║ │ DTP*435 ─ Death Date ──────────────────► death_date │ ║ │ │ │
│ │ │ ║ └───────────────────────────────────────────────────────────┘ ║ │ │ │
│ │ │ ║ ║ │ │ │
│ │ │ ║ ╔═══════════════════════════════════════════════════════════╗ ║ │ │ │
│ │ │ ║ ║ HEALTH COVERAGE LOOP - Loop 2300 (repeats per coverage) ║ ║ │ │ │
│ │ │ ║ ║ (in_hd_loop = True when inside this loop) ║ ║ │ │ │
│ │ │ ║ ╠═══════════════════════════════════════════════════════════╣ ║ │ │ │
│ │ │ ║ ║ ║ ║ │ │ │
│ │ │ ║ ║ HD ────── Health Coverage (LOOP START TRIGGER) ║ ║ │ │ │
│ │ │ ║ ║ ├── HD03: Insurance Line ────► coverage type ║ ║ │ │ │
│ │ │ ║ ║ ├── HD04: Plan Description ──► hcp_code;status ║ ║ │ │ │
│ │ │ ║ ║ │ (parsed for HCP code and status) ║ ║ │ │ │
│ │ │ ║ ║ └── HD06: Insurance Type ────► coverage flags ║ ║ │ │ │
│ │ │ ║ ║ ║ ║ │ │ │
│ │ │ ║ ║ Coverage Detection (keyword scanning): ║ ║ │ │ │
│ │ │ ║ ║ • MEDICARE, MA, PART A/B/C/D ► has_medicare ║ ║ │ │ │
│ │ │ ║ ║ • MEDICAID, MEDI-CAL, LTC ───► has_medicaid ║ ║ │ │ │
│ │ │ ║ ║ • SNP, D-SNP, DSNP ──────────► snp=True ║ ║ │ │ │
│ │ │ ║ ║ • LTC, NURSING HOME, SNF ────► lti=True ║ ║ │ │ │
│ │ │ ║ ║ ║ ║ │ │ │
│ │ │ ║ ║ DTP*348 ─ HCP Coverage Start ──────────► hcp.start_date ║ ║ │ │ │
│ │ │ ║ ║ DTP*349 ─ HCP Coverage End ────────────► hcp.end_date ║ ║ │ │ │
│ │ │ ║ ║ ║ ║ │ │ │
│ │ │ ║ ║ REF*CE ── Aid Codes (in HD loop) ──────► hcp.aid_codes ║ ║ │ │ │
│ │ │ ║ ║ REF*17 ── Client Reporting Cat ────────► client_report ║ ║ │ │ │
│ │ │ ║ ║ ║ ║ │ │ │
│ │ │ ║ ║ AMT ───── Amount ║ ║ │ │ │
│ │ │ ║ ║ ├── AMT01: Qualifier ────────► amount_qualifier ║ ║ │ │ │
│ │ │ ║ ║ └── AMT02: Amount ───────────► amount (float) ║ ║ │ │ │
│ │ │ ║ ║ ║ ║ │ │ │
│ │ │ ║ ║ ──► Each HD creates new HCPContext, saved to hcp_history ║ ║ │ │ │
│ │ │ ║ ╚═══════════════════════════════════════════════════════════╝ ║ │ │ │
│ │ │ ║ ║ │ │ │
│ │ │ ║ ──► On next INS or end of file: finalize member ║ │ │ │
│ │ │ ║ • Calculate age from DOB ║ │ │ │
│ │ │ ║ • Determine dual status (priority logic) ║ │ │ │
│ │ │ ║ • Check new enrollee status ║ │ │ │
│ │ │ ║ • Build HCP history list ║ │ │ │
│ │ │ ║ • Create EnrollmentData object ║ │ │ │
│ │ │ ╚═════════════════════════════════════════════════════════════════╝ │ │ │
│ │ │ │ │ │
│ │ │ SE ─── Transaction Set Trailer │ │ │
│ │ └─────────────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ GE ─── Functional Group Trailer │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ IEA ── Interchange Control Trailer │
└─────────────────────────────────────────────────────────────────────────────┘
┌──────────────┐
│ START │
└──────┬───────┘
│
▼
┌──────────────┐ ISA/GS ┌──────────────┐
│ HEADER │────────────────►│ Parse │
│ PARSING │ │ source, │
└──────────────┘ │ report_date │
│ └──────────────┘
│ BGN/N1*IN
▼
┌──────────────┐
│ PLAN │ ◄─── Detect SLA prefix
│ INFO │
└──────┬───────┘
│
│ INS (Member Loop Start)
▼
┌──────────────┐
│ MEMBER │ ◄─── Create new MemberContext
│ CONTEXT │ in_hd_loop = False
└──────┬───────┘
│
│ REF/NM1/DMG/N3/N4/LUI/DTP/PER
▼
┌──────────────┐
│ MEMBER │ ◄─── Populate member fields
│ DETAILS │
└──────┬───────┘
│
│ HD (Health Coverage Loop Start)
▼
┌──────────────┐
│ HD LOOP │ ◄─── in_hd_loop = True
│ ACTIVE │ Create HCPContext
└──────┬───────┘
│
│ DTP/REF/AMT (within HD loop)
▼
┌──────────────┐
│ HCP │ ◄─── Populate current_hcp
│ DETAILS │
└──────┬───────┘
│
│ Next HD or INS
▼
┌──────────────────────────────────────┐
│ HD? │ INS? │ EOF? │
└───┬───┴───┬────┴───┬─────────────────┘
│ │ │
│ │ ▼
│ │ ┌──────────────┐
│ │ │ FINALIZE │
│ │ │ MEMBER │───► EnrollmentData
│ │ └──────────────┘
│ │
│ ▼
│ ┌──────────────┐
│ │ FINALIZE │───► EnrollmentData
│ │ + NEW │
│ │ MEMBER │───► New MemberContext
│ └──────────────┘
│
▼
┌──────────────┐
│ SAVE HCP │───► Append to hcp_history
│ + NEW HCP │───► New HCPContext
└──────────────┘
The parser uses intelligent logic to determine dual eligibility status with the following priority:
1. REF*F5 (explicit dual_elgbl_cd)
│
▼ if not found
2. REF*AB (Medi-Cal Aid Code mapping)
│ 4N,4P → '02' (QMB Plus)
│ 4M,4O → '01' (QMB Only)
│ 5B,5D → '04' (SLMB Plus)
│ 5A,5C → '03' (SLMB Only)
│ 5E,5F → '06' (QI)
│
▼ if not found
3. REF*ABB (Medicare Status Code mapping)
│ QMB/QMBONLY → '01'
│ QMBPLUS/QMB+ → '02'
│ SLMB/SLMBONLY → '03'
│ SLMBPLUS/SLMB+ → '04'
│ QI/QI1 → '06'
│ QDWI → '05'
│
▼ if not found
4. Both Medicare AND Medicaid coverage detected
│ → '08' (Other Full Dual)
│
▼ if not found
5. Default: '00' (Non-Dual)
All dates are normalized to ISO format (YYYY-MM-DD):
| Input Format | Example | Output |
|---|---|---|
| YYYYMMDD | 20250115 |
2025-01-15 |
| YYMMDD | 250115 |
2025-01-15 |
Race codes from DMG05 are translated using CDC Race and Ethnicity codes:
| Input | Output |
|---|---|
:RET:2135-2 |
Hispanic or Latino |
:RET:2054-5 |
Black or African American |
2106-3 |
White |
AMT segment values are converted to numeric:
| Segment | Fields Extracted |
|---|---|
AMT*R*1237~ |
amount_qualifier='R', amount=1237.0 |
The parser produces EnrollmentData objects with:
Some fields are derived at finalization time:
| Field | Source | Logic |
|---|---|---|
age |
dob |
Calculated from date of birth |
new_enrollee |
coverage_start_date |
True if <= 3 months since start |
medi_cal_eligibility_status |
coverage_end_date, report_date |
“Active” if coverage extends through report month, “Terminated” if ended before |
is_full_benefit_dual |
dual_elgbl_cd |
True if code in {‘02’, ‘04’, ‘08’} |
is_partial_benefit_dual |
dual_elgbl_cd |
True if code in {‘01’, ‘03’, ‘05’, ‘06’} |
Death date can come from multiple sources with the following priority:
| Source | Field | Notes |
|---|---|---|
| INS11/INS12 | death_date |
Primary source when INS11=’D8’ |
| DTP*435 | death_date |
Secondary source, overwrites INS if present |
| REF*17 position 1 | fame_death_date |
FAME system recorded date (separate field) |