Skip to main content

Receivables (835) workspace operator playbook

Outcome

ERA files are uploaded, claims auto-match where the parser is confident, low-confidence and unmatched rows are reviewed and confirmed, exceptions are triaged, and line-level data is exportable for downstream reporting.

Prerequisites

  • remittances.create for upload, remittances.read for review, remittances.update for manual matching.
  • An ERA file (raw X12 835) on hand.

Upload an ERA

  1. Open Receivables in the rcm-app. Click Upload ERA.

  2. Provide the ERA:

    • Paste raw X12 835 into the textarea, or use the .835 / .txt file picker.
    • The dialog refuses anything that doesn't start with ISA.
    • Enter the canonical Payer ID (UUID).
    • Optionally enter a Billing Entity ID to scope the resulting remittance row.
  3. Click Upload & Match. A toast reports <matched>/<total> claims matched; you're auto-redirected to the new remittance detail page.

The route is POST /api/v1/remittances/parse. Server-side it runs parse835processRemittance, which writes the remittance + claims + lines + adjustments into billing.remittance* in a single transaction and emits a REMITTANCE_EVENTS.MATCHED event.

Match-review tabs

The detail page splits matched claims by match_confidence:

TabFilterOperator action
Auto-matchedHIGH or MEDIUM and claim_id setAudit only — read
Review queueLOW and claim_id setAccept (single click) or Re-match
Unmatchedclaim_id IS NULLRun Manual Match
ExceptionsVariance / duplicate / orphan signalsTriage (see below)
AdjustmentsAll CO/PR/OA/PI/CR rowsReference
TraceCheck / EFT trace rowsReference

The Review-queue accept calls POST /api/v1/remittances/claims/:id/confirm, writing a fresh MANUAL audit row in billing.remittance_match and bumping match_confidence to HIGH. Re-match uses the manual-match endpoint with force: true.

Manual matching

  1. Open the Unmatched tab, click Match on a row.

  2. Run the search — the dialog seeds the input with the PCN. Press Enter to fire /api/v1/claims?q=….

  3. Pick a candidate. Each carries Member ID, DOS-from / DOS-to, charged amount, status.

  4. Confirm the match. If totalChargeAmountCents differs from the remittance charged amount by more than $0.01, an amber banner warns — confirm only after eyeballing both rows.

Exceptions triage

GET /api/v1/remittances/:id/variances returns four exception classes:

CategoryTriggerTriage
OVERPAYMENTactual paid > expected by > $1.00Recoupment risk — file a return-of-overpayment with the payer.
UNDERPAYMENTactual paid < expected by > $1.00Hand off to appeals via Denials and appeals; CARCs on the Adjustments tab tell the why.
DUPLICATE_TRNanother remittance for the same payer carries the same TRNInspect the listed peer remittance IDs. If it was a payer reissue, mark remittance_type=REISSUE. Otherwise hold posting on one until resolved.
ORPHAN_PAYMENTunmatched remit_claim with total_paid_cents > 0Run Manual Match — cash is sitting in suspense.

Tolerance is governed by EXCEPTION_TOLERANCE_CENTS (= 100¢). The detector intentionally ignores zero-paid orphans (e.g. CO-only denial remits) so the queue stays focused on cash-at-risk rows.

Line-level CSV export

The detail page Export Lines button hits GET /api/v1/remittances/:id/lines/export and downloads a flattened-per-line CSV with columns:

PCN · Remit Claim ID · Matched Claim ID · Line # · Procedure · Revenue · Units · DOS From · DOS To · Charged ($) · Paid ($) · PR ($) · CO ($) · Match Confidence · Match Method

Claim-level adjustments are reported on the first line of each claim so column totals tie out on a SUM(...) pivot.

Audit + observability

  • Every mutating route emits a REMITTANCE_EVENTS.* envelope through event-bus. MATCHED fires once per processRemittance call.
  • The billing.remittance_match audit table preserves every match decision; superseded_by chains expose the full re-match history.
  • Logs are tagged service: "remittance-service"journalctl -u rcm-core | grep remittance-service is the standard starting point for incident triage.

Validation

CheckExpected
Upload returns 200 with match countYes
Auto-matched rowsSane match confidence
Exceptions tabEmpty or fully triaged before close
remittance_match audit chainComplete history of decisions

Troubleshooting

SymptomCauseFix
"Refused: not an X12 envelope"File doesn't start with ISAEnsure raw 835 (not unwrapped CSV/PDF).
All claims unmatchedWrong payer ID, or PCN format mismatchConfirm payer; check billing.claim.pcn format vs ERA.
Variance flagged but realPayer applied unexpected adjustmentOpen Adjustments tab; route to appeal.
Manual match candidate list emptyPCN search yields zeroSearch by Member ID + DOS instead.

Cross-references

Next

3.9 — Manual auto-correction trigger