Claim Scrubber Software: How to Build a Claims Rules Engine Into Your Product
Nirmitee.io Engineering
Author

Claim scrubber software checks every claim against a set of rules before it is sent, so errors that would cause a rejection or denial are caught and fixed while they are still cheap. A good scrubber is not a single validation pass. It is a claims rules engine with layers, from missing fields to payer requirements to coding edits such as NCCI, and it runs continuously, records every finding, lets authorized people override a rule with a reason, and routes blocked claims to the right person. This guide shows how to build one into an EHR or billing product.
It is based on the scrubber we built into a multi-clinic behavioral health platform that submits professional claims through a national clearinghouse. We describe what we built, what we would add, and the design decisions that turned a validation function into something billers trust.
Key takeaways
- Scrub in layers: structure, identity, payer, coding, and risk. Each layer has different owners and change rates.
- Persist findings, do not just return them. A per-claim snapshot with first-seen dates is what makes a work queue possible.
- Delta-diff the nightly sweep so unchanged claims write nothing and history lives in an append-only event log.
- Overrides need an administrator, a reason and an audit record. Anything less turns the scrubber into a suggestion.
- NCCI and MUE edits are public and quarterly. Load CMS files as versioned reference data rather than writing rules by hand.
- A scrubber failure must never block the save. One broken claim cannot stop the batch.
Why claim scrubbing is worth building well
Every claim that leaves with a fixable error comes back as a 999 or 277CA rejection, or later as a denial on the 835. Rejections cost a resubmission cycle. Denials cost more: someone has to read the reason code, find the cause, correct and appeal or resubmit, and some never get worked at all. A scrubber moves that work to the point where the data is still in front of the person who can fix it.
For software vendors, the scrubber is also one of the most visible parts of the billing product. Practices compare products by clean claim rate and by how much billing staff they need. Generic scrubbers exist as standalone products and inside clearinghouses, and many practices use one. The advantage of building the core into your own product is that it can check things no outside scrubber can see: whether the clinical note is signed, whether the supervisor on a supervised visit is credentialed, whether this client's coverage was verified on the date of service.
The five layers of a claims rules engine
| Layer | What it checks | Examples from our rule set | Changes |
|---|---|---|---|
| 1. Structure | Required claim data exists and is well formed | SL_CPT_REQUIRED, SL_ICD_REQUIRED, SL_POS_REQUIRED, SL_QTY_INVALID, SL_AMT_INVALID | Rarely |
| 2. Identity | Patient, subscriber, billing and rendering provider are complete and consistent | PAT_GENDER_REQUIRED, INS_SUBSCRIBER_ID_REQUIRED, BP_TAXID_MISSING, PROV_NPI_INVALID, PROV_SUPERVISOR_MISMATCH | Rarely |
| 3. Payer | The claim fits the payer: valid payer ID, filing indicator, active policy | INS_PAYER_ID_MISMATCH, INS_FILING_INDICATOR_INVALID, INS_ACTIVE_POLICY_REQUIRED | Monthly |
| 4. Coding | Code pairs, units and modifiers are allowed | NCCI procedure-to-procedure pairs, medically unlikely edit unit limits, modifier rules | Quarterly |
| 5. Risk | Signals that a valid claim is still likely to fail | RISK_TIMELY_FILING, RISK_PRIOR_DENIALS_PAYER, RISK_RESUBMISSION_LINEAGE | Continuously |
Layers one to three catch front-end rejections: the claim will not get past the clearinghouse or the payer's intake. Layer four catches coding denials. Layer five is where a product-embedded scrubber pulls ahead, because risk rules use your own history, such as a payer that has repeatedly denied this code, a resubmission chain that keeps failing, or a claim approaching the payer's filing limit.
Our rule set also has a clinical gate that no outside scrubber can run: NOTE_NOT_APPROVED blocks a claim whose session note is not signed, and a readiness check confirms the rendering clinician's credentials before billing. The provider-identity rules are covered in depth in our guide to rendering vs billing provider.
NCCI and MUE edits: the coding layer
The National Correct Coding Initiative publishes two edit sets that most scrubbers implement. Procedure-to-procedure (PTP) edits define pairs of HCPCS or CPT codes that should not be reported together. Medically unlikely edits (MUEs) define the maximum units of service reported for a code by the same provider, for the same beneficiary, on the same date of service, on the vast majority of appropriate claims. CMS publishes separate Medicare PTP edits, Medicare MUEs and Medicaid NCCI edit files, and updates both quarterly; CMS's own guidance is to replace saved tables completely each quarter.
That shapes the design. NCCI is reference data, not code:
- Load each quarter's files into versioned tables with an effective date range, and keep old versions, because a claim is judged by the edits in force on its date of service.
- Keep Medicare and Medicaid edit sets separate, and let payer configuration choose which applies. Commercial payers often follow NCCI but not always.
- Honor the modifier indicator on PTP pairs: some pairs may be billed together with an appropriate modifier, others never.
- Report the edit and the effective quarter in the finding, so a biller can see why the pair was flagged.
In the behavioral health platform we work on, the coding layer matters less than it does in surgical or multi-procedure specialties, because most sessions bill a single psychotherapy or evaluation code. That is why we built layers one, two, three and five first. For a vendor serving procedural specialties, NCCI belongs in the first release.
Persist findings: the scrub snapshot
The first version of most scrubbers is a function that returns a list of errors when a biller clicks submit. It works until someone asks "how many claims are blocked right now, and since when?" Answering that needs persisted findings.
We keep a one-to-one scrub snapshot per claim, with a row per finding identified by rule code, service line and field. Each finding keeps the date it was first seen. When the claim is scrubbed again, the engine compares the new findings with the stored ones:
- A finding that is still present keeps its original first-seen date.
- A new finding is inserted.
- A finding that disappeared is deleted from the snapshot, and its resolution is recorded as an event on the claim's append-only lifecycle log.
The snapshot always shows the current truth, and the lifecycle log shows the history. The same rule firing twice through two branches of the same check is stored once, because findings are deduplicated on their identity.
When the scrubber runs
| Trigger | Why |
|---|---|
| On claim save | Feedback while the biller is still on the screen |
| Before submission | The hard gate: errors block, warnings inform |
| Nightly sweep of open claims | Data changes elsewhere: a policy ends, a credential expires, a filing limit approaches |
| After reference data updates | A new NCCI quarter or payer rule can change yesterday's verdict |
The nightly sweep is where delta-diffing pays off. Most open claims have not changed since yesterday, so most sweeps write nothing. Without the diff, the sweep rewrites every finding every night and the history becomes noise.
Two reliability rules matter here. A scrub failure on one claim is logged and recorded as "not scrubbed" for that claim, and never breaks the batch or the save path that called it. And the scrubber only reads claims; it never corrects data or changes a claim's state. Fixes stay human, or belong to a separate, explicit automation.
Overrides: the difference between a gate and a suggestion
Real billing has exceptions. A payer accepts a claim the rule says it will not; a clinic has an agreement that makes a warning irrelevant. If the scrubber cannot be overridden, billers route around it. If anyone can override it silently, it stops meaning anything. Our override rules, each an automated test:
- Submitting a claim with errors and no override is refused, and nothing is recorded.
- A non-administrator cannot override.
- An override requires a reason.
- An administrator's override with a reason succeeds and is recorded on both the claim's lifecycle log and the administrative audit trail.
- Overrides are scoped to a rule on a service line, not the whole claim, and can be revoked.
Scoping matters. Overriding "payer ID mismatch on line 1" should not silence a new "missing diagnosis" error on line 2 tomorrow.
See what your claims are failing on. Send us three months of de-identified 999, 277CA and 835 denial data and a description of your current validation, and we will map each rejection and denial reason to the scrubber layer that should have caught it, with the rules to add first. See our RCM software development work or send us the data.
Route blocked claims into a work queue
A finding nobody sees is not useful. When an open claim is blocked, our scrubber creates or updates a work item for billers with a structured reason, so the queue can be filtered and counted. It flags and organizes; it does not transition the claim. The biller sees which rule, which line, which field, and how long it has been blocked.
That turns scrubber output into operational numbers: blocked claims by rule, by payer, by clinic, and by age. Those numbers tell a practice where its data problems are, and tell a product team which rules to improve. It is the same principle we apply to the full claim lifecycle, which we cover in our guide to 837, 835 and 277 integration. Many scrubber rules exist because of eligibility gaps; see why claims get denied.
Learn from denials: close the loop with the 835
A scrubber written once and never revised decays. Payers change their rules, and the only reliable signal is what they reject and deny. Two feedback loops keep the rule set honest:
- Front-end rejections. Every 277CA rejection carries status codes from the X12 claim status category and claim status code lists. Group rejections by code, payer and field each week. A rejection that repeats is a missing rule.
- Denials. Every denial on the 835 carries claim adjustment reason codes. Map the preventable ones, such as missing information, invalid codes and non-covered combinations, to the scrubber layer that should have caught them, and write the rule.
That mapping is also how you prove the scrubber's value. Track the first-pass acceptance rate, rejections per hundred claims by rule, denials that a rule would have prevented, the median time a claim stays blocked, and the override rate per rule. A rule that is overridden most of the time is either wrong or too strict, and should be reviewed. Our payment posting automation guide covers how denial data flows back from the 835.
Test every rule like code
Scrubber rules are code with business consequences, so they get the same discipline:
- One unit test per rule for the failing case and the passing case, keyed by rule code.
- A regression fixture for every real rejection that led to a new rule, so the rule never silently disappears in a refactor.
- Reference data tests that load a sample of each NCCI quarter and assert known pairs and unit limits.
- A dry-run mode for new rules: run them on open claims and report what they would flag before they are allowed to block.
The dry run is the one teams skip and regret. A new error-level rule that fires on a third of open claims on its first night is a support incident, even when the rule is correct.
Performance and scale
A scrubber that runs on every save and every night has to be cheap. Four choices keep it that way. First, scrub per claim with its own error boundary, so cost grows linearly and a bad record never stalls a sweep. Second, load reference data such as payer settings and NCCI tables once per batch, not once per claim. Third, write only deltas: the snapshot comparison means a sweep over thousands of unchanged claims issues almost no writes. Fourth, index findings by organization, rule code and first-seen date, because those are exactly the filters billers and reports use.
Multi-clinic platforms add one more rule. The nightly sweep runs across tenants, often from a background job with no signed-in user, so every query must scope explicitly to the claim's organization rather than rely on a user context. A tenant mix-up in a scrubber is not a wrong warning; it is one clinic's claim data appearing in another clinic's queue.
Build, buy or both
| Option | Strength | Gap |
|---|---|---|
| Clearinghouse edits | Broad payer rule coverage, maintained for you | Runs after the claim leaves your product; cannot see clinical or credential data |
| Standalone scrubber product | Deep coding edits, often including NCCI and payer-specific rules | Another integration and contract; findings live outside your work queue |
| Scrubber built into your product | Sees notes, credentials, eligibility and history; findings drive your own queue | You maintain the rule set and reference data |
Most mature products end up with both: an embedded scrubber for everything only the product can know, plus clearinghouse edits as a last line. The embedded layer is what reduces rework, because it runs where the fix happens. For a view of when deterministic rules beat AI in this space, see when a rules engine wins.
What we learned building it
- Rule codes are an API. Stable, readable codes such as
INS_PAYER_ID_MISMATCHlet the queue, the reports and the support team speak the same language. Never key anything off message text. - Errors and warnings are a product decision. Every rule we made an error had to be something a payer would certainly reject. Everything else is a warning, or billers stop reading.
- History belongs in an event log, not in stale rows. Keeping resolved findings in the snapshot made "what is blocked now" unanswerable.
- Fallbacks hide data problems. We removed defaults such as a default place of service and made the rule fire instead, so the data got fixed at the source.
- Tenant integrity errors are conflicts, not crashes. A claim that does not belong to the caller's clinic returns a clear conflict, never an internal server error.
Claim scrubber checklist
- Rules organized in layers: structure, identity, payer, coding, risk.
- Stable rule codes, severity per rule, and messages that name the field and the person.
- Persisted per-claim findings with first-seen dates.
- Delta-diffed nightly sweep, with history on an append-only event log.
- NCCI PTP and MUE loaded as versioned, quarterly reference data by date of service.
- Overrides restricted to administrators, with a reason, scoped to rule and line, dual-audited and revocable.
- A failure on one claim never blocks the batch or the save.
- Blocked claims feed a filterable work queue.
- Clinical and credential gates that outside scrubbers cannot see.
- A regression suite that replays real rejection cases, as described in our guide to EDI testing.
Building a claims rules engine? We design and build claim scrubbers inside EHR and billing products: rule layers, NCCI reference data, override governance and work queues. Tell us your specialties and payers and we will outline the rule set for your first release. See our healthcare interoperability services or talk to our team.
Ready to scale?
Talk to our healthcare engineering team about building, integrating, and shipping faster.
Frequently Asked Questions
What is claim scrubber software?
What is the difference between claim scrubbing and a clearinghouse edit?
What are NCCI PTP and MUE edits?
How often should a claim scrubber run?
Should billers be able to override scrubber rules?
Should we build a claim scrubber or buy one?

