Skip to main content

Commercial auth workflow and EOB posting

Outcome

Commercial payer auths route to the right channel (EDI 278, portal, manual). Commercial EOB posting splits patient-responsibility correctly into deductible/coinsurance and tags carrier write-offs.

Prerequisites

Auth workflow routing

Commercial payers often publish authorizations through proprietary portals (UHC, Availity, Aetna) or accept only phone / fax. Running every submit through the X12 278 generator was forging EDI payloads the payer never asked for.

AuthRequestService.submit consults config.payer_program_config.auth_workflow and picks one of three branches:

auth_workflowBehaviour
EDI_278 (default)generate278() + markSubmitted('SUBMITTED') with full X12 payload.
PORTALSkip 278 generation, markSubmitted('MANUAL_PENDING'), submitted_x12 = NULL. Operator submits via auth_portal_url.
MANUALSame as PORTAL but no URL. Fax / phone / paper.

When a payer has no payer_program_config row at all, the resolver returns null and the service falls back to EDI_278 — this keeps pre-config Medicaid payers on the 278 path without requiring a seed update.

Onboard a commercial payer to PORTAL

  1. Insert (or UPSERT) a config.payer_program_config row with:

    FieldValue
    auth_workflow'PORTAL'
    auth_portal_url'<payer's authorizations URL>' (CHECK constraint rejects NULL)
    auth_turnaround_days<payer SLA>
  2. Existing DRAFT auth requests for that payer will switch paths on the next submit call. In-flight SUBMITTED requests continue their existing lifecycle.

To return to EDI_278:

UPDATE config.payer_program_config
SET auth_workflow = 'EDI_278', auth_portal_url = NULL
WHERE payer_id = '<payer-id>';

Commercial EOB posting

RemittancePoster reads rcm_master.payer.payer_type via resolvePayerContext. For commercial payers it does two things differently from Medicaid/Medicare:

WhatCommercialMedicaid/Medicare
PR adjustments splitPR-1 → DEDUCTIBLE, PR-2 → COINSURANCE, other PR → PATIENT_RESPONSIBILITYSingle PATIENT_RESPONSIBILITY bucket
CO-45 rows tagadjustment_source = 'COMMERCIAL_CONTRACT'NULL

This split lets carrier write-off reports filter via ix_remit_adj_source.

Carrier write-off by payer this quarter

SELECT p.name AS payer,
SUM(a.amount_cents) / 100.0 AS contractual_writeoff_usd
FROM billing.remittance_adjustment a
JOIN billing.remittance_claim rc
ON rc.remit_claim_id = a.remit_claim_id
JOIN billing.remittance r
ON r.remit_id = rc.remit_id
JOIN rcm_master.payer p
ON p.payer_id = r.payer_id
WHERE a.adjustment_source = 'COMMERCIAL_CONTRACT'
AND r.received_at >= date_trunc('quarter', now())
GROUP BY p.name
ORDER BY contractual_writeoff_usd DESC;

Non-CO-45 CO rows (CO-97 duplicate, CO-29 timely filing, etc.) remain adjustment_source = NULL — they are denials, not contractual write-offs, and belong to the denial-management flow.

Validation

CheckExpected
payer_program_config.auth_workflow for the payermatches the operational reality (EDI_278 / PORTAL / MANUAL)
Commercial 835 postsPR splits into DEDUCTIBLE / COINSURANCE rows
CO-45 rows on commercialadjustment_source = COMMERCIAL_CONTRACT
Auth submit on PORTAL workflowauth_request.status = MANUAL_PENDING, submitted_x12 NULL

Troubleshooting

SymptomCauseFix
Submit still generates 278 for a PORTAL payerpayer_program_config.auth_workflow not flippedUpdate to PORTAL and confirm with psql.
Operator reports no portal URLauth_portal_url NULLRequired for PORTAL — set it (CHECK constraint enforces).
PR rows post as single PATIENT_RESPONSIBILITY for commercialpayer.payer_type is wrongUpdate rcm_master.payer.payer_type to a commercial value.
CO-45 not taggedMigration 094 not applied for tenantRun migration fan-out.

Cross-references

Next

3.7 — Auto-correction operator playbook