EDI 835 Remittance Guide for Data Engineers
The EDI 835 electronic remittance advice is the foundation of healthcare payment analytics. Learn ERA schema design, CARC/RARC lookup tables, 837-to-835 reconciliation, and dbt models for denial management and payment variance reporting.
What Is EDI 835?
The EDI 835 Health Care Claim Payment/Advice is the X12 5010X221A1 electronic remittance advice (ERA) that payers send to providers after adjudicating claims. It is the downstream counterpart to the 837 claim submission and contains the complete payment story — what was paid, what was adjusted, and the standardized reason codes explaining every variance.
In data warehouses, the 835 is typically the most complex EDI transaction to model because a single 835 file can contain payments for thousands of claims, each with multiple service lines and multiple adjustment reason codes. Understanding the hierarchical structure — financial information (BPR), claim payment (CLP), service line payment (SVC), and adjustment (CAS) segments — is essential for schema design.
EDI 835 Staging DDL
-- EDI 835 Payment Header CREATE TABLE edi_835_payment ( pmt_key UUID PRIMARY KEY DEFAULT gen_random_uuid(), interchange_ctrl_no VARCHAR(9) NOT NULL, pmt_dt DATE NOT NULL, -- BPR02 effective date pmt_amt DECIMAL(12,2) NOT NULL, -- total payment amount pmt_method_cd VARCHAR(3), -- CHK, ACH, NON payer_id VARCHAR(20) NOT NULL, payer_nm VARCHAR(200), payee_npi VARCHAR(10), payee_nm VARCHAR(200), check_eft_nbr VARCHAR(50), rec_creat_ts TIMESTAMP NOT NULL DEFAULT NOW() ); -- EDI 835 Claim Payment CREATE TABLE edi_835_claim ( clm_pmt_key UUID PRIMARY KEY DEFAULT gen_random_uuid(), pmt_key UUID REFERENCES edi_835_payment(pmt_key), clm_id VARCHAR(38) NOT NULL, -- matches 837 CLM01 clm_sts_cd VARCHAR(2) NOT NULL, -- 1=paid, 2=adjusted, 3=denied, 22=reversal charged_amt DECIMAL(12,2) NOT NULL, -- billed amount paid_amt DECIMAL(12,2) NOT NULL, -- amount paid patient_resp_amt DECIMAL(12,2), -- member cost share allowed_amt DECIMAL(12,2), -- contracted allowed mbr_id VARCHAR(20), svc_dt_from DATE, svc_dt_to DATE, rendering_npi VARCHAR(10), payer_clm_ctrl_no VARCHAR(38), -- payer internal reference adj_reason_cd_1 VARCHAR(5), -- primary CARC adj_amt_1 DECIMAL(12,2), adj_reason_cd_2 VARCHAR(5), adj_amt_2 DECIMAL(12,2), adj_reason_cd_3 VARCHAR(5), adj_amt_3 DECIMAL(12,2), remark_cd_1 VARCHAR(5), -- RARC remark_cd_2 VARCHAR(5), rec_creat_ts TIMESTAMP NOT NULL DEFAULT NOW() ); -- CARC Reference Table CREATE TABLE dim_carc ( carc_cd VARCHAR(5) PRIMARY KEY, carc_desc VARCHAR(500) NOT NULL, carc_group_cd VARCHAR(2) NOT NULL, -- CO, PR, OA, PI carc_group_desc VARCHAR(50), is_denial BOOLEAN NOT NULL DEFAULT FALSE, eff_dt DATE, exp_dt DATE ); -- RARC Reference Table CREATE TABLE dim_rarc ( rarc_cd VARCHAR(5) PRIMARY KEY, rarc_desc VARCHAR(500) NOT NULL, rarc_type VARCHAR(10), -- ALERT or INFORMATIONAL eff_dt DATE, exp_dt DATE ); CREATE INDEX idx_835_clm_id ON edi_835_claim(clm_id); CREATE INDEX idx_835_pmt_dt ON edi_835_claim(svc_dt_from); CREATE INDEX idx_835_carc ON edi_835_claim(adj_reason_cd_1);
Payment Reconciliation SQL
837 to 835 Payment Reconciliation
-- Claims submitted but no payment received within SLA
SELECT
c837.clm_id,
c837.billng_prvdr_npi,
c837.mbr_id,
c837.svc_dt_from,
c837.bld_amt,
c835.paid_amt,
c835.clm_sts_cd,
DATEDIFF(day, c837.rec_creat_ts, CURRENT_DATE) AS days_since_submission
FROM edi_837p_claim_header c837
LEFT JOIN edi_835_claim c835 ON c835.clm_id = c837.clm_id
WHERE c837.svc_dt_from >= DATEADD(month, -3, CURRENT_DATE)
AND c835.clm_id IS NULL -- no remittance received
AND DATEDIFF(day, c837.rec_creat_ts, CURRENT_DATE) > 30
ORDER BY c837.bld_amt DESC;Top Denial Reasons by Dollar Amount
SELECT
c.adj_reason_cd_1 AS carc_cd,
d.carc_desc,
d.carc_group_cd,
COUNT(*) AS claim_count,
SUM(c.charged_amt) AS total_charged,
SUM(c.paid_amt) AS total_paid,
SUM(c.charged_amt - c.paid_amt) AS total_adjusted,
ROUND(100.0 * SUM(c.charged_amt - c.paid_amt)
/ NULLIF(SUM(c.charged_amt), 0), 2) AS adjustment_pct
FROM edi_835_claim c
JOIN dim_carc d ON d.carc_cd = c.adj_reason_cd_1
WHERE c.svc_dt_from >= DATEADD(year, -1, CURRENT_DATE)
AND c.adj_reason_cd_1 IS NOT NULL
GROUP BY c.adj_reason_cd_1, d.carc_desc, d.carc_group_cd
ORDER BY total_adjusted DESC
LIMIT 20;Frequently Asked Questions
What is an EDI 835?
The EDI 835 (Health Care Claim Payment/Advice) is the X12 electronic remittance advice (ERA) sent by payers to providers after adjudicating claims. It details how each claim was processed — what was paid, what was adjusted, and why. An 835 corresponds to one or more 837 claim submissions and contains claim-level, service-line-level, and CAS (Claim Adjustment Segment) data explaining every payment variance.
What are CARC codes?
Claim Adjustment Reason Codes (CARCs) are standardized codes published by the Washington Publishing Company that explain why a payment differs from the billed amount. Common CARCs include CO-45 (charge exceeds fee schedule), PR-1 (deductible), PR-2 (coinsurance), PR-3 (copay), CO-97 (bundled service), and CO-4 (service code inconsistent with modifier). CARCs appear in the CAS segment of the 835 and are essential for denial management analytics.
What are RARC codes?
Remittance Advice Remark Codes (RARCs) provide supplemental explanation for CARC adjustments and appear in the MOA and MIA segments of the 835. While CARCs explain the adjustment category, RARCs provide additional context — for example, N130 indicates a contractual adjustment, and MA01 indicates a Medicare secondary payer situation. Store both CARCs and RARCs alongside adjustment amounts for complete denial analytics.
How do I reconcile EDI 837 claims to EDI 835 payments?
Join on clm_id (CLM01 from the 837) to the 835 claim reference number. Key reconciliation checks: billed_amt from 837 should equal charged_amt in 835; claim count in your 837 staging table should match 835 received count within your expected lag period; and check for 837 claims with no corresponding 835 after your payer SLA window as these indicate lost or unreturned claims.
What data type should I use for CARC/RARC codes?
Store CARC and RARC codes as VARCHAR(5) — they are alphanumeric codes like CO-45, PR-1, or N130. Never normalize them to integers as the codes themselves carry semantic meaning used in denial reporting. Build a separate dim_carc and dim_rarc reference table linking each code to its description, group category, and whether it represents a payer adjustment, patient responsibility, or contractual adjustment.
How do I store multiple adjustment codes per service line?
Each service line in an 835 can have multiple CAS segments with multiple CARC/amount pairs. The most common approach is to store up to 3 adjustment reasons as individual columns (adj_reason_cd_1 through adj_reason_cd_3 with corresponding adj_amt_1 through adj_amt_3) in the service line table. For plans with complex multi-code adjustments, use a separate edi_835_adjustment table with a foreign key to the service line, allowing unlimited adjustments per line.