> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Clearinghouse Multi-Vendor Failover — Admin Guide

> Multi-vendor failover lets your organization designate a primary and secondary EDI clearinghouse (Waystar, Availity, Change Healthcare) and automatically route…

**Related:** [Clearinghouse Admin Guide](/pm/clearinghouse-admin-guide), [Compliance Evidence](/compliance/evidence/hipaa-edi-failover-evidence)

***

## Overview

Multi-vendor failover lets your organization designate a **primary** and **secondary** EDI clearinghouse (Waystar, Availity, Change Healthcare) and automatically route 837/270/276/278 traffic to the secondary when the primary is degraded. Routing decisions are deterministic, per-payer overrides are honored, and every vendor transition is recorded in `pm_audit_log` for HIPAA 164.312(b) audit controls.

**Who this is for:** Organization Admins and Billing Managers with `pm.clearinghouse.admin`.

***

## Prerequisites

* At least one active clearinghouse configuration (see [Clearinghouse Admin Guide](/pm/clearinghouse-admin-guide)).
* Executed Business Associate Agreement (BAA) on file for **every** vendor you intend to enable. Availity and Change Healthcare routes are gated until the BAA toggle is checked.
* `pm.clearinghouse.admin` permission on the active organization.

***

## 1. Configure Failover Thresholds

**Navigate:** Practice Management → Clearinghouse → **Failover Settings**

1. Select **Primary Vendor** (defaults to your existing Waystar config).
2. Select **Secondary Vendor**. The dropdown only lists vendors with a stored config; vendors without a signed BAA appear disabled with a "BAA required" badge.
3. Acknowledge the **BAA on file** checkbox for the secondary vendor. Without acknowledgement the Save button stays disabled.
4. Set the failover thresholds:
   * **Health check interval** (seconds) — how often the router polls vendor health (default `60`).
   * **Consecutive failures before failover** (default `3`) — number of failed health checks or transaction errors that flip routing to the secondary.
   * **Recovery cool-down** (seconds, default `300`) — minimum time the primary must remain healthy before traffic flips back.
   * **Per-transaction timeout** (ms, default `15000`) — used by the router to mark a single 837/270/276/278 call as failed.
5. Click **Save**. Settings are written to `pm_clearinghouse_failover_settings` scoped to the active `organization_id`.

> The router (`resolveVendorRoute` / `resolveVendorRouteWithAudit` in `src/cores/pm/services/clearinghouse`) reads these thresholds on each routing decision; no redeploy is required.

***

## 2. Override Routing per Payer

Some payers require a specific clearinghouse (e.g., a state Medicaid line that is only enrolled with Availity). Per-payer overrides win over the global primary/secondary selection.

**Navigate:** Practice Management → Clearinghouse → Failover Settings → **Payer Routes** tab

1. Click **Add Payer Route**.
2. Choose the payer (PM-02 record).
3. Select the **Forced Vendor**. Only vendors with a config + signed BAA appear.
4. Optional: toggle **Allow failover for this payer**. When off, the router will surface a hard error instead of falling back if the forced vendor is degraded — useful for payers that reject claims submitted via an unenrolled CH.
5. Save. The row is written to `pm_clearinghouse_payer_routes` and takes effect on the next routing decision.

Override precedence (highest first):

1. Per-payer route with `allow_failover = false` → hard pin.
2. Per-payer route with `allow_failover = true` → forced vendor with secondary fallback.
3. Global primary → secondary failover.

***

## 3. Verify Behavior in Supabase

All checks below assume you are logged into the Supabase dashboard for the project and have selected the SQL editor. Replace `:org_id` with the active organization UUID.

### 3.1 Confirm settings persisted

```sql theme={null}
select primary_vendor, secondary_vendor, failure_threshold,
       recovery_cooldown_seconds, transaction_timeout_ms, baa_acknowledged_at
from pm_clearinghouse_failover_settings
where organization_id = :org_id;
```

### 3.2 List active payer overrides

```sql theme={null}
select p.name as payer, r.forced_vendor, r.allow_failover, r.updated_at
from pm_clearinghouse_payer_routes r
join pm_payers p on p.id = r.payer_id
where r.organization_id = :org_id
order by p.name;
```

### 3.3 Trigger a failover and watch the audit log

1. In **Failover Settings**, temporarily set the primary vendor's stored credential to an invalid value (or use the **Simulate health failure** button if your environment exposes it).
2. Submit a test 270 eligibility check from PM-02 against any payer that uses the global route.
3. Within `failure_threshold * health_check_interval` seconds the router flips to the secondary. Confirm with:

```sql theme={null}
select created_at, action, old_values, new_values
from pm_audit_log
where organization_id = :org_id
  and action = 'clearinghouse_route_failover'
order by created_at desc
limit 10;
```

You should see a row whose `new_values.vendor` matches the secondary, `new_values.failed_over = true`, and `new_values.reason` describes the trigger (e.g., `consecutive_health_failures`). Re-running the same payer in quick succession should **not** produce duplicate rows — the router dedupes by `organization_id + payer_id` scope until the vendor changes again.

### 3.4 Confirm recovery

Restore the primary credential. After the cool-down window the next routing decision logs a transition row back to the primary with `new_values.failed_over = false`.

### 3.5 RLS spot-check

Run as a non-admin user in the same org — the settings/route rows should be readable but not writable, and rows from other organizations must be invisible. The RLS test suite covers this:

```bash theme={null}
npm run test:rls -- pm-clearinghouse-failover
```

***

## 4. Troubleshooting

| Symptom                                                     | Likely cause                                                                           | Fix                                                                                                  |
| ----------------------------------------------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| Save button disabled in Failover Settings                   | BAA checkbox not acknowledged for the secondary vendor                                 | Confirm BAA is on file, then check the box.                                                          |
| Secondary vendor missing from dropdown                      | No `pm_clearinghouse_configurations` row for that vendor in this org                   | Add the configuration first, then return to Failover Settings.                                       |
| No `clearinghouse_route_failover` rows after a known outage | Router is being called via the legacy path that bypasses `resolveVendorRouteWithAudit` | Confirm the calling code uses the audited wrapper exported from `@/cores/pm/services/clearinghouse`. |
| Duplicate audit rows for the same outage                    | The dedupe cache was reset (process restart) — expected                                | No action; cache rebuilds on next decision.                                                          |
| Hard error instead of failover for a payer                  | Per-payer override has `allow_failover = false`                                        | Edit the payer route or remove it.                                                                   |

***

## 5. Change Log

| Date       | Author  | Change                                  |
| ---------- | ------- | --------------------------------------- |
| 2026-05-15 | Lovable | Initial publication for PM-15-P2-EN-01. |
