Case Study

Medical billing lifecycle management: building a 5-stage state machine

How I built the medical billing module for Synectus Medico — a 5-stage billing state machine for personal injury clinics with CPT codes, aging analysis, and attorney visibility.

Medical billing in personal injury cases does not work like standard healthcare billing. There is no simple "claim submitted, claim paid" workflow. Instead, there is a negotiation process. The clinic invoices the payer (usually the law firm managing the case). The payer counters with a lower amount. The clinic agrees or counters back. Eventually, a reduction amount is agreed and the payer sends a cheque. The cheque arrives, gets recorded, and the case is settled.

Most billing software does not model this workflow because most billing software is designed for insurance claim processing, not PI settlement negotiation. That gap is what the Synectus Medico billing module was built to fill.

This case study covers how the billing lifecycle was designed and built as a state machine, what the CPT code management and aging analysis systems look like, and how the attorney portal fits into the billing workflow.

Why a state machine is the right model for medical billing

A state machine is a software design pattern where an object can be in exactly one of a set of defined states, and can only transition between states according to defined rules.

Medical billing is a perfect state machine candidate because:

  • Each invoice is always in exactly one stage of the billing lifecycle
  • The transitions between stages follow defined rules (you cannot go from pending_invoice to cheque_received without going through pending_reduction and pending_cheque first)
  • Each stage requires specific actions, inputs, and creates specific data
  • Different stages are relevant to different users (billing staff see one view; attorneys see a simplified version of the same stages)

The alternative to a state machine is a series of boolean flags or status strings with no enforced transition logic. This leads to inconsistent data: an invoice that has a cheque recorded but is still in "pending_invoice" status. An invoice with a reduction amount but no record of how the reduction was agreed. These inconsistencies create billing reporting problems and make audits difficult.

The 5 stages of the billing lifecycle

Stage 1: pending_invoice

An invoice has been created based on the patient's exam. The invoice includes line items for each procedure performed, with CPT codes and the billed amount. The invoice is waiting to be sent to the responsible payer.

In this stage: the billing staff member can view and edit the invoice line items, attach supporting documentation, and record billing notes about the invoice status. The transition out of this stage is triggered by sending the invoice to the payer.

Stage 2: pending_reduction

The invoice has been sent and the payer has responded with a request to reduce the billed amount. This is common in PI cases where attorneys negotiate medical bills as part of the case settlement.

In this stage: the billing staff member records the reduction amount offered by the payer. There may be counter-offers and back-and-forth. The billing notes field captures the negotiation history. The transition out of this stage is triggered when a final reduction amount is agreed and documented.

Stage 3: pending_cheque

The reduction has been agreed. The clinic is waiting for the physical or electronic cheque from the payer.

In this stage: no financial changes are expected. The invoice is simply in a waiting state. Billing reminders are most commonly set up in this stage to trigger a follow-up if the cheque does not arrive within a defined period.

Stage 4: cheque_received

The cheque has arrived. The billing staff member records the cheque details: cheque number, cheque date, received date, amount, and the paying party. The cheque document can be uploaded directly in the system.

In this stage: the cheque is recorded but not yet confirmed as final settlement. There may be bank clearance waiting periods or additional documentation requirements.

Stage 5: paid

The case is settled. All related invoices for this patient are confirmed as collected. The billing lifecycle for this case is complete.

Building state transitions in the API layer

The state machine logic lives in the API layer, not the database or the frontend. The database stores the current state. The frontend displays state-appropriate UI. The API enforces valid state transitions.

When a billing staff member triggers a state transition (by clicking "Record Reduction" or "Mark Cheque Received"), the API receives the request and first validates that the transition is legal. If the current state is pending_invoice and the requested transition is to pending_cheque (skipping pending_reduction), the API rejects the request with an error.

Each transition endpoint validates:

  • The current state of the invoice
  • The validity of the requested transition
  • The presence and validity of required input data for the transition (reduction amount, cheque details, etc.)

If all validations pass, the API updates the invoice state and creates an audit log entry recording the transition, the user who triggered it, and the before/after state.

CPT code management and invoice line items

Each invoice line item is tied to a CPT code that identifies the procedure performed. CPT codes are maintained as a master list in the platform with per-code pricing.

The invoice generation flow in Medico:

  1. 1A physician completes an exam for a patient
  2. 2The exam includes a selected exam type, which maps to one or more CPT codes
  3. 3An invoice is automatically generated with line items for each CPT code in the exam type
  4. 4Each line item shows: CPT code, procedure description, units, unit price, and total
  5. 5The billing staff member can review, adjust quantities, and add or remove line items

Sub-exam pricing. Many exam types include sub-exams that can be individually selected. A comprehensive spine evaluation might include: cervical exam, lumbar exam, neurological assessment, range of motion testing. Each sub-exam has its own CPT code and price. The total invoice is the sum of selected sub-exams.

Bilateral pricing. When a procedure is performed bilaterally (on both sides of the body), the CPT code billing convention is to bill at a higher rate. The Medico billing module includes a bilateral toggle on each line item. When enabled, the unit price doubles. This automates a calculation that billing staff previously had to remember to apply manually.

Facility grouping. Invoices are grouped by facility when displayed. If a patient had exams at two different clinic locations, their invoices are organized by facility for clarity.

Aging bucket analysis

An aging analysis shows how long invoices have been outstanding, grouped by time buckets. This is one of the most operationally important views in any billing system.

The Medico aging dashboard shows invoices in five buckets:

  • 0 to 30 days (recently created, low priority)
  • 31 to 60 days (follow-up recommended)
  • 61 to 90 days (active follow-up required)
  • 91 to 120 days (escalation recommended)
  • 121 days and older (high collection risk)

Aging is calculated server-side on every request: (today's date - invoice creation date). The billing dashboard supports filtering by aging bucket. A billing staff member can click "61-90 days" and see only the invoices in that range that need immediate attention.

Color coding makes the urgency visually immediate. 0-30 days is green. 31-60 is yellow. 61-90 is orange. 91+ is red. At a glance, a billing manager can see the aging distribution of the full invoice portfolio.

Aggregate aging analysis. The executive dashboard shows total dollar value in each aging bucket, not just invoice count. This is more operationally useful: knowing there are 15 invoices in the 91+ bucket is less actionable than knowing those 15 invoices represent $127,000 in high-risk receivables.

Billing reminder scheduling

The most common cause of aging invoices is that billing follow-up gets missed. An invoice is sent, nobody follows up, and it sits in pending_reduction for 60 days without anyone noticing.

The reminder scheduling system lets billing staff schedule internal reminders on any invoice. A reminder includes:

  • A target date
  • A description of the action to take
  • Optional billing notes

When the target date arrives, the reminder surfaces on the billing staff member's dashboard as a pending task. They can see exactly which invoice needs attention and what the intended action was.

This is different from an automated email to the payer (which is also valuable but requires more configuration and payer-specific customization). Internal reminders are simpler and more reliable for teams getting started with billing automation.

Attorney visibility into billing: the filtered view

Attorneys in personal injury cases have a legitimate need to see the billing status of their clients' medical treatment. They need to know: what has been invoiced, what has been collected, and what is still outstanding. This information directly affects how they structure the settlement negotiation.

But attorneys should not see:

  • Internal billing notes about negotiation strategy
  • Reduction counter-offers in progress
  • Other attorneys' clients' billing data
  • Sensitive operational details not relevant to case settlement

The attorney portal in Medico provides a filtered view of billing data:

  • Invoice line items and billed amounts are visible
  • Current billing stage is shown (pending_invoice, pending_reduction, etc.)
  • Reduction amounts agreed are shown once finalized
  • Internal billing notes are hidden
  • Cheque details are shown once received

This view is implemented by the API returning a different response shape for attorney role users vs billing staff role users. The billing endpoint checks the user's role from the JWT token and returns either the full billing record (for billing staff) or the filtered version (for attorneys).

Bulk export for accounting reconciliation

At the end of each month, billing data needs to flow into the clinic's accounting system. The Medico billing module provides bulk CSV and Excel export with the following filters:

  • Date range (invoice creation date or payment date)
  • Billing status
  • Facility
  • Physician
  • Payer

The export includes all the fields an accounting team needs: invoice ID, patient name, exam date, facility, physician, CPT codes, billed amount, reduction amount, collected amount, cheque number and date, and current status.

Technically, the export uses the blob download pattern: the API generates the file server-side and streams it as a binary response. The frontend receives the blob, creates an object URL, and triggers a browser download with the appropriate MIME type and filename.

For Excel export specifically, the xlsx library on the server generates a proper .xlsx file with formatted columns and appropriate data types for each column (dates as date cells, currency as number cells).

// common questions

FAQ

Conclusion

The Medico billing lifecycle management system shows what personal injury billing software looks like when it is designed for the actual PI workflow rather than adapted from standard insurance claim processing.

The 5-stage state machine enforces workflow consistency. CPT code management with bilateral pricing automates manual calculations. Aging analysis makes collection risk visible. The attorney portal gives legal teams the visibility they need without exposing internal operational data. And bulk export closes the loop with accounting.

If you are building billing software for a personal injury clinic network or medical-legal services company, these are the features that matter and the design patterns that work in production.

Building something similar?

Book a free 30-minute discovery call. No pitch, just a conversation about what you are building and how to approach it right.

Start the Conversation