Manage fee schedules
Outcome
Fee schedules in the platform that match what each payer pays you. Charges priced at the right rate, with a clean audit trail of which schedule and which entry priced each line.
Prerequisites
| Scope | What it lets you do |
|---|---|
billing.fee-schedule.read | View list / detail / entries |
billing.fee-schedule.write | Create / edit / import |
A payer and contract registered first (see Manage payers, programs & contracts). A fee schedule with no contract is also valid — it becomes a floor used when no contracted rate exists.
What is a fee schedule
A fee schedule is a list of entries, each combining:
| Field | Example |
|---|---|
| Procedure code | 99213 |
| Modifiers (optional) | HQ U2 |
| State (optional) | OH |
| Effective from / to | 2025-01-01 → 2025-12-31 |
| Allowed amount | $78.42 |
Optional contract attachment links the schedule to a payer contract. When a charge is priced, the platform finds the entry with the most-specific match (code + modifiers + state + dates) on the contracted schedule.
Steps
Pick
Configuration → Fee Schedulesat/admin/fee-schedules. Each row shows the schedule's name, the contract it is attached to (if any), the effective window, and the entry count.Click
+ New fee scheduleto create one. The form asks for:- Name — display label.
- State — the schedule's primary state, or
Multi-statefor unscoped. - Effective from / to — the schedule's window.
- Contract — optional. Pick from contracts on registered payers.
Open a schedule's detail to see the entries grid. The grid is filterable by procedure code, modifier, and state. Use the search box to find a specific code.
Add or edit entries with the inline editor. Each row commits on blur and shows a green bar briefly when saved. Validation enforces:
- The effective window must fall within the schedule's window.
- An entry with the same
(code, modifiers, state, effectiveFrom)cannot exist twice — duplicates return HTTP 409.
Bulk-import a schedule from CSV with the
Import CSVbutton on the detail page header. The import flow has three stages:- Drag-drop the CSV. The first row is the header; expected columns are
code, modifiers, state, effectiveFrom, effectiveTo, allowedAmount. - Dry-run previews how many rows will create / update / fail. The diff table shows old → new for any entry that would change.
- Confirm to apply. The platform writes the entries in a transaction — either the whole file lands or none of it does.
- Drag-drop the CSV. The first row is the header; expected columns are
Export the current view with
Export CSVon the detail page. Useful for reconciliation against the payer's published schedule.
Validation
| Check | Expected |
|---|---|
New schedule appears on /admin/fee-schedules | Yes. |
| Charges priced after effective date | The schedule's entries drive the allowed amount. |
rate_source_ref on the priced charge | Format FEE_SCHEDULE:<id> (or CONTRACT:<id> if the contract carries the schedule). |
| CSV export round-trip | Export CSV → re-import via Import CSV produces zero diffs. |
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Charges priced at $0 | No entry matched the (code, modifiers, state, date-of-service) tuple | Add an entry for the missing combination, or widen the modifier filter. |
| Import fails with 409 on a row | The row collides with an existing active entry | The dry-run flags this — accept the diff to update, or drop the duplicate row. |
| Effective-date overlap warning | Two entries cover the same key for overlapping windows | Trim the older entry's effectiveTo, then re-import. |
| Schedule attached to the wrong contract | Contract was switched | Edit the schedule's header → save → the rate-source on future charges updates immediately; charges already priced are not retroactively updated. |