The ClaimRev Connect module integrates ClaimRev's clearinghouse services directly into OpenEMR, giving practices access to claims processing, eligibility verification, ERA downloads, payment posting, reconciliation, patient balance management, and analytics — all without leaving their EHR.
—
The ClaimRev Connect module is published on Packagist as claimrevolution/oe-module-claimrev-connect. Starting with v2.1.3 a single build runs on both OpenEMR 7.x and OpenEMR 8.x — runtime compatibility shims in src/Compat/ activate only when the host core lacks the newer APIs. Pick the install method that matches your environment.
Current Version: 2.1.3
If you have CLI access to your OpenEMR install:
cd /path/to/openemr composer require claimrevolution/oe-module-claimrev-connect:^2.1 sudo systemctl reload php-fpm # or restart Apache
Composer downloads the latest v2.1.x release, drops it into interface/modules/custom_modules/oe-module-claimrev-connect/, and updates the autoloader. Continue with Activation below.
To update the module later:
composer update claimrevolution/oe-module-claimrev-connect sudo systemctl reload php-fpm
OpenEMR's Manage Modules page does not have a zip-upload feature for custom modules — it scans interface/modules/custom_modules/ on every page load and lists whatever directories it finds. For installs without CLI access (shared hosting, restricted environments), drop the files into place via SFTP/FTP:
oe-module-claimrev-connect/ containing composer.json, info.txt, src/, public/, templates/, etc.oe-module-claimrev-connect/ folder into interface/modules/custom_modules/ so the resulting path is interface/modules/custom_modules/oe-module-claimrev-connect/composer.json (and so on for the other files).
Note: Updates with this method are the same flow — replace the contents of the oe-module-claimrev-connect/ folder with the contents of the new zip. Method 1 (Composer) is much easier if you have any way to run shell commands on the server.
If you installed OpenEMR via an official release tarball that already bundles claimrevolution/oe-module-claimrev-connect in its composer.json, the module arrives pre-extracted at interface/modules/custom_modules/oe-module-claimrev-connect/. No additional download step.
Note: If you do not yet have a ClaimRev account, visit claimrev.com or contact us at sales@claimrev.com to get started.
—
After enabling the module, you need to configure your ClaimRev API credentials.
Tip: To verify your connection, navigate to the ClaimRev module and click the Connectivity tab for a connection status check. Contact ClaimRev support if you need your API credentials.
—
The Home tab is a KPI dashboard that gives billers a one-glance overview of the entire revenue cycle. It refreshes every time you open the module.
Direct links to Search Claims, Payment Advice, Reconciliation, Claim Status, and Denial Analytics.
The module enables electronic claim submission (837P/837I) to payers through ClaimRev.
The Claims tab provides a searchable view of claims submitted through ClaimRev, with integrated OpenEMR status tracking and actions.
Search for claims using any combination of:
pid-encounterEach claim row displays the OpenEMR claim status alongside the ClaimRev status. This lets you see at a glance whether the two systems agree. OpenEMR statuses include:
| Status | Badge Color | Meaning |
| Not Billed | Gray | Claim has not been sent |
| Unbilled | Light | Claim is queued but not yet sent |
| Billed | Green | Claim has been submitted |
| Crossover | Blue | Crossover claim submitted |
| Denied | Red | Claim was denied |
Each claim row provides action buttons:
Click on any claim row to expand it and see:
The Payment Advice tab allows you to search for ERA (835) payment advice records from ClaimRev and post them directly into OpenEMR's payment system.
Click on a payment advice record to expand it. Each claim line within the ERA shows:
Payment advice records can be posted to OpenEMR to record payments, adjustments, and denials.
Some claim statuses require special attention before posting:
In batch mode, reversals and pended claims are not auto-posted. Instead, they are separated into a “Needs Approval” section in the batch results, where you can review each one individually and click Approve & Post to post them one at a time.
When an ERA is posted, the following data flows into OpenEMR:
ar_session and ar_activityIns1 dedbl: 150.00, Ins1 coins: 45.00, Ins1 copay: 25.00. These memos are later parsed by the Patient Balance screen to show the PR breakdown.last_level_closed flag on the encounter is updated, indicating insurance has finished processingWhen the Enable Test Mode global is on (Admin > Globals > ClaimRev Connect), the Payment Advice, ERA, and Reconciliation pages return mock data generated from local OpenEMR billing rows. Useful for demos, training, and posting-workflow rehearsal without hitting the live ClaimRev API.
Important: Only enable the global in development or training environments. The global is the only switch — there is no longer a per-search checkbox.
The Reconciliation tab provides a side-by-side comparison of OpenEMR encounters against their status in ClaimRev, helping you identify claims that may need attention.
Reconciliation answers questions like:
At the top of the results, four summary cards show:
The comparison table shows each encounter with columns for:
| Column | Description |
| Patient | Patient name |
| Encounter | Encounter number (click to expand details) |
| Service Date | Date of the encounter |
| Payer | Insurance company name |
| Charges | Total billed charges |
| OE Status | Current OpenEMR claim status (color-coded badge) |
| CR Status | ClaimRev claim status |
| ERA | ERA classification from ClaimRev (e.g., Paid, Denied) |
| CR Paid | Amount paid per ClaimRev |
| Issue | Description of the discrepancy, if any |
| Actions | Available action buttons |
The system automatically detects five types of discrepancies:
| Discrepancy | Severity | Meaning |
| Billed in OpenEMR but not found in ClaimRev | Danger (red) | The claim may not have been submitted successfully |
| Rejected in ClaimRev but still Billed in OpenEMR | Danger (red) | ClaimRev shows the claim was rejected, but OpenEMR hasn't been updated |
| Denied in OpenEMR but Accepted in ClaimRev | Warning (yellow) | OpenEMR shows denied, but ClaimRev shows the payer accepted the claim |
| ERA shows paid but no payment posted in OpenEMR | Warning (yellow) | A payment was received but hasn't been recorded in OpenEMR |
| ERA shows denied but OpenEMR not marked as denied | Warning (yellow) | The ERA indicates a denial that OpenEMR doesn't reflect |
Rows are color-coded: red for danger-level discrepancies, yellow for warnings, and gray for encounters not found in ClaimRev.
Each row provides action buttons depending on the situation:
Click on any row to expand a detailed comparison showing:
The Patient Balance tab surfaces encounters with outstanding patient responsibility after insurance has responded. It helps billers identify who owes money and manage the statement workflow.
An encounter appears in the Patient Balance queue when:
last_level_closed >= 1 on the encounter)| Column | Description |
| Patient | Patient name and date of birth |
| Encounter | Encounter number |
| Service Date | Date of the encounter |
| Payer | Primary insurance |
| Charges | Total billed charges |
| Ins Paid | Total insurance payments |
| Patient Owes | Outstanding balance (bold) |
| Stmts | Statement status badge: “Never Sent” (yellow), count (blue), or “Collections” (red) |
| Last Statement | Date of the most recent statement |
| Actions | Action buttons |
Click any row to expand and see:
The module tracks statements in its own mod_claimrev_patient_statements table. The queue shows whichever count is higher: the module's own count or OpenEMR's native stmt_count on the encounter. This means statements sent through either system are reflected.
The Claim Status tab provides a work-queue style dashboard for tracking claims through their lifecycle, with real-time 276/277 status checks.
Claims are categorized into actionable groups:
The AR Aging Report is found under the Analytics dropdown in the navigation bar. It provides a standard 30/60/90/120 day aging breakdown of accounts receivable, grouped by payer.
Each row represents a payer and shows:
| Column | Description |
| Payer | Insurance company name (or “Self-Pay”) |
| 0-30 | Balance for encounters 0-30 days old |
| 31-60 | Balance for encounters 31-60 days old |
| 61-90 | Balance for encounters 61-90 days old |
| 91-120 | Balance for encounters 91-120 days old (red text) |
| 120+ | Balance for encounters over 120 days old (bold red) |
| Total | Total AR for this payer |
| Enc | Number of encounters |
| Distribution | Visual bar showing the percentage of AR that is over 90 days old. Green = healthy, yellow = caution, red = problem. |
Payers are sorted by total AR descending — the biggest balances appear first.
Click Export CSV to download the full encounter-level aging data as a spreadsheet. The CSV includes patient name, encounter, service date, payer, age in days, aging bucket, balance, insurance level, and statement count.
The Denial Analytics page is found under the Analytics dropdown. It analyzes adjustment and denial patterns to help identify systemic issues with specific payers or procedure codes.
The left panel shows the 20 most common adjustment reasons, with:
The right panel shows adjustments grouped by payer:
This helps identify payers that are consistently adjusting or denying claims.
Below the payer breakdown, a monthly trend table shows adjustment counts and amounts over time, with visual bars. This helps answer: “Are our denials getting better or worse?”
Click Export CSV to download the denial reason data as a spreadsheet for further analysis.
The Recoupment Report is found under the Analytics dropdown. It identifies claims where payments were reversed (recouped) — typically from Medicare reprocessing or payer take-backs — and tracks whether a reprocessed payment has been received.
When Medicare or another payer reprocesses a claim, they often reverse the original payment (a “recoupment”) and then issue a new payment at the adjusted amount. This report answers:
| Column | Description |
| Patient | Patient name and date of birth |
| Encounter | Encounter number |
| Service Date | Date of the encounter |
| Payer | Insurance company name |
| Code | Procedure code affected |
| Original Paid | Total of payments received before the recoupment |
| Recouped | Amount taken back (shown in red) |
| Reprocessed | Amount received after recoupment (green), or “—” if still pending |
| Net Impact | Gain or loss from the recoupment cycle (bold, color-coded) |
| Balance | Current encounter balance |
| Status | Reprocessed (green badge) or Pending (yellow badge) |
Rows with a “Pending” status are highlighted with a yellow background to draw attention to claims still awaiting reprocessed payment.
Click any row to expand a three-column detail panel:
ar_activity record
The report queries ar_activity for records with a negative pay_amount (the recoupment). For each recoupment found, it then looks up:
This classification helps billers understand the full payment lifecycle for reprocessed claims.
Click Export CSV to download the report as a spreadsheet. The CSV includes: Patient, Encounter, Service Date, Payer, Code, Original Paid, Recoup Amount, Recoup Date, Reference, Reprocessed, Net Impact, Current Balance, and Status.
Real-time eligibility verification is available from the patient demographics page.
Note: Eligibility, Coverage Discovery, and MBI Finder are mutually exclusive; only one of them can be selected at a time. Demographics can be combined with any of those three.
Coverage Discovery, Demographics, and MBI Finder query the payer using patient demographic data and don't need an insurance row, so the eligibility tab is still available for patients who have no insurance entered. In that case the tab is labelled No Insurance, the Eligibility option is hidden, and Coverage Discovery is pre-selected. Add the matched coverage afterwards through the normal Insurance card workflow if you want to keep it.
A red Reset button next to Check Now clears every cached eligibility row for the current patient (across all payer responsibilities). Useful when re-testing a fresh check or after fixing patient demographics that produced a bad result. The button asks for confirmation before deleting.
The Conversation tab provides an AI-powered assistant that can answer questions about the eligibility response. Ask questions like:
Eligibility results can be synced to OpenEMR's native Insurance card Eligibility tab by clicking the Sync to Insurance Card button. This populates the standard eligibility verification and benefit tables so the data is visible on the patient dashboard.
Electronic Remittance Advice (ERA/835) files from payers can be downloaded and imported into OpenEMR.
The X12 Tracker tab shows the history of X12 files (837, 835, 270/271, 276/277, etc.) that have been transmitted through ClaimRev.
The Appointments tab provides a comprehensive view of upcoming appointments with integrated eligibility verification, allowing front-desk staff and billers to ensure patients have active coverage before their visit.
Filter appointments using any combination of:
Each appointment row displays:
| Column | Description |
| Checkbox | Select for bulk actions |
| Date | Appointment date |
| Time | Appointment start time |
| Patient | Patient last name, first name |
| DOB | Patient date of birth |
| Provider | Rendering provider |
| Facility | Service location |
| Eligibility Status | Color-coded status: Active Coverage (green), Pending (orange), Error (red), Not Checked (gray). Payer name and response messages are shown below the status. |
| Last Checked | Date/time of the most recent eligibility check, or “Never” |
| Actions | Per-row action buttons |
For appointments with completed eligibility results, an expandable detail row shows the full eligibility response including the quick info summary with benefit details parsed from the 271 response.
When enabled, color-coded indicators appear on appointment blocks in the main OpenEMR calendar, giving providers and staff an at-a-glance view of each patient's eligibility status.
The module hooks into the calendar's event rendering system and adds a colored left border to each appointment block based on the patient's primary insurance eligibility status:
| Color | CSS Class | Meaning |
| Green | event_elig_active | Active coverage confirmed |
| Red | event_elig_inactive / event_elig_error | Inactive coverage or eligibility check error |
| Yellow | event_elig_unchecked / event_elig_stale | Never checked or results older than the stale threshold |
| Blue | event_elig_pending | Eligibility check queued and waiting for response |
Eligibility data for all patients visible on the calendar is loaded in a single batch query, minimizing database overhead. However, on very busy calendars with many appointments, enabling this feature may have a minor impact on calendar load time.
The Eligibility Sweep is an automated background service that proactively queues eligibility checks for upcoming appointments on a scheduled basis, ensuring patients have current coverage verification before they arrive.
waiting or creating status) are skipped to avoid duplicates.Navigate to Admin > Config > Connectors > ClaimRev Connect and configure:
| Setting | Description | Default |
| Enable Eligibility Sweep | Turn the sweep service on or off | Off |
| Sweep Days | Comma-separated day numbers: 0=Sun, 1=Mon, 2=Tue, 3=Wed, 4=Thu, 5=Fri, 6=Sat | 1,4 (Mon, Thu) |
| Sweep Lookahead Days | Number of days ahead to check for appointments | 7 |
The stale threshold is shared with other eligibility features and is controlled by the Eligibility Age To Stale setting.
With the default settings (sweep on Monday and Thursday, 7-day lookahead):
This ensures that by the time a patient arrives, their eligibility has been verified within the last few days.
Portal notifications from ClaimRev are accessible within the module, keeping you informed of important updates about your claims and account.
—
The ClaimRev Connect module ships as a single binary covering:
openemr/openemr:flex and openemr/openemr:8.0.0.3-2026-03-25.openemr/openemr:7.0.2.
The src/Compat/ shim layer activates per-host. On OE 8.x cores that already expose the modern APIs the shims are no-ops; on OE 7.x or older 8.0.x cores the shims provide OEGlobalsBag, CryptoInterface, and ServiceContainer via class_alias, and CsrfHelper detects the active CsrfUtils signature at runtime.
| Component | What the shim does on older cores |
OEGlobalsBag | Wraps $GLOBALS with typed getters (used directly on 7.x; on 8.0.x patch line the module imports the shim explicitly because the core's OEGlobalsBag is thinner than expected) |
ServiceContainer | Wraps CryptoGen and other services directly |
LoggerInterface (getLogger) | Provides a PSR-3 logger via OpenEMR's SystemLogger |
ClockInterface (getClock) | Provides a PSR-20 clock returning the current time |
CryptoInterface | Wraps CryptoGen behind the 8.x crypto interface |
CsrfHelper | Detects whether SessionWrapperFactory::getActiveSession exists; routes to CsrfUtils with the correct argument order and $_SESSION fallback when needed |
GlobalConfig::getClientSecret | Prefers CryptoGen::decryptFromDatabase (upstream PR #11956, May 2026) when available; falls back to decryptStandard on older cores |
To verify the module works correctly on your OpenEMR version:
OEGlobalsBag — Whether the native class or shim is in useServiceContainer — Whether the native class or shim is in useLoggerInterface / ClockInterface / CryptoInterface — Whether native or shimmedGlobalConfig and Bootstrap — Whether they instantiate successfullyIf all checks show green, the module is fully operational. If any check shows “Using ClaimRev shim”, the module is running with compatibility shims — all features work normally.
—
pid-encounter)last_level_closed >= 1 (insurance has responded)mod_claimrev_patient_statements table existsClaimRev_Elig_Sweep background service is active in Admin > System > Background ServicesIf you installed the OpenEMR 8.x build on a 7.x install (or vice versa), you may see:
—
claimrevolution/oe-module-claimrev-connect. Install via composer require claimrevolution/oe-module-claimrev-connect:^2.1. Replaces the previous May 12 (OE 7.x) and May 13 (OE 8.0.x rebuild) separate-zip builds with a single binary.src/Compat/ shim layer lives in the module's own repo on GitHub, not duplicated across two build branches. Same code path runs on OE 8.x master, the OE 8.0.x patch line, and OE 7.x.GlobalConfig::getClientSecret uses CryptoGen::decryptStandard (works on both OE 7.x and 8.x) instead of the OE 8.x-only decryptFromDatabase.background_services.last_run column that had been breaking installs on OE 8.x master.release/v8-0 branch. The previous 8.x build assumed every 8.x core exposed OEGlobalsBag::getKernel, SessionWrapperFactory::getActiveSession, and CsrfUtils::collectCsrfToken(session, subject). The OE 8.0.x patch line has none of those — its OEGlobalsBag is thin, SessionWrapperFactory uses a different acquisition pattern, and CsrfUtils::collectCsrfToken takes (subject, ?session) with a $_SESSION fallback. The new build ships the src/Compat/ shim layer with runtime-detection for the divergent APIs so the same zip works on 8.0.0.3 and on newer 8.x / master.openemr/openemr:8.0.0.3-2026-03-25 with full patient + encounter + billing data copied from a flex install. Login, navigation, Claims tab, Reconciliation, Payment Advice, ERA, and Setup all load cleanly.GlobalConfig::getClientSecret now prefers the newer CryptoGen::decryptFromDatabase (upstream PR #11956, May 2026) when present and falls back to decryptStandard transparently. The 2.1.3 hotfix-only revert in the original 8.x build (which always called decryptStandard) is no longer needed.PatientContext helper resolves the session-active patient and the Check Now (eligibility_check_now), Reset (eligibility_clear), and AI chat (eligibility_chat) endpoints now refuse a pid that does not match. The chat endpoint additionally re-verifies the supplied sharpRevenueObjectId belongs to that patient via the stored response payload.appointments.php now verifies the existing eligibility CSRF token before either bulk or single Queue POST handler runs and emits the hidden token in #bulkForm.payment_advice_post.php accepts only paymentAdviceId (single) or paymentAdviceIds (batch JSON) and re-fetches the authoritative ClaimPaymentAggregation from ClaimRev before posting. claim_sync_status.php accepts only claimrevObjectId and derives the status fields from a re-fetched claim. Browser-supplied amounts, encounter PCNs, or status codes can no longer drive an OE write.skipMarkWorked POST flag on payment posting is only honored when isTestModeEnabled() is true, so a regular user can't suppress the upstream mark-as-worked side effect.EligibilityTransfer allowlists claimRevResultId to [A-Za-z0-9_-] (with a server-generated fallback) before composing the raw 271 save path.claim_export_csv basename-strips control characters and restricts the API-supplied filename to a conservative charset before emitting it in Content-Disposition. The header is no longer susceptible to CR/LF injection.ClaimRevModuleSetup::ensureCoreSftpEnabled only flips the X12_SFTP background service to active = 1 on a truly fresh install (last_run IS NULL). An admin who deliberately disabled the service keeps that setting across module re-enables.PaymentAdvicePostingService::post wraps the duplicate check and arPostSession insert in a MySQL named lock keyed by paymentAdviceId. Concurrent submits of the same advice can no longer post twice; the second call returns a clear concurrent post in progress message.GlobalConfig::getClientSecret originally kept calling CryptoGen::decryptStandard (the legacy API) instead of the newer decryptFromDatabase that upstream PR #11956 introduced in May 2026. The new method does not exist on older OpenEMR cores most installs still run, and using it would break the Connectivity tab on those installs. (The May 13 rebuild above changes this to a runtime-detected fallback so the same module works on both.)serviceTypeCodes as a JSON array (List<string>) instead of a comma-separated string, and always emit isRevenueToolsPayerId: false on each payer entry. The ClaimRev API tightened request validation and started rejecting the older shape with HTTP 400, breaking Check Now. Empty service-type-code configuration still asks for all benefits.payers array is omitted when only non-eligibility products are selected, since the API ignores it for those products and its presence corrupts MBI Finder results. When MBI Finder is requested, the subscriber number is copied to the top-level subscriberId field where MBI Finder reads it.retryLater poll loop (~60s) on Coverage Discovery, which exceeded PHP's default 30-second max_execution_time. The Check Now and Appointment Check Now endpoints now allow up to 180 seconds, the Guzzle clients have explicit connect_timeout / timeout set so a stuck call can't burn the whole budget, and the OAuth token POST is retried up to two extra times on transient B2C hiccups.0) in the configured sweep days. claim_export_csv parses request input through the typed boundary helper rather than passing raw $_POST to the service. Menu entry hidden from users without acct/bill access. Migration runner uses QueryUtils::escapeTableName/escapeColumnName for schema-validated identifier escaping.strict_types=1 to catch type coercion bugs at the boundary.PaymentAdvicePostingService and ReconciliationService refactored to expose pure helpers (idempotency-reference building, PCN parsing, claim status labels, service-line aggregation, discrepancy classification) with PHPUnit isolated test coverage.mod_claimrev_claims and mod_claimrev_claim_events database tables for tracking claim status, payer acceptance, ERA classification, paid amounts, and a full event audit trail (submitted, rejected, accepted, denied, ERA received, payment posted, etc.)ClaimRev_Elig_Sweep background service that proactively queues eligibility checks for upcoming appointments on configured days of the week. Configurable sweep days (default Monday and Thursday) and lookahead window (default 7 days). Skips appointments with fresh results or already-queued checks.OEGlobalsBag, ServiceContainer, LoggerInterface, ClockInterface, CryptoInterface) allow the module to run on OpenEMR 7.x without modificationmod_claimrev_patient_statements database table for tracking statement history per encounter