Ask any MSP owner where their invoices leak money and you'll hear two answers before you finish the question: after-hours work billed at the standard rate, and contract rates that nobody applied because the right person wasn't looking. Both are rate-math problems, and both are completely silent. Nobody files a complaint when a 1.5× emergency call goes out at 1×. The hours were tracked. The invoice went out. The number was just quietly wrong.

We hit this constantly at the MSP we run Morton Command Center for, and it's the reason rate logic was one of the first things we built into the billing layer. The goal isn't a fancier timesheet — it's making sure that by the time an entry becomes an invoice line, the correct rate has already been applied, every time, without a human remembering to do it.

Why the math is harder than it looks

On paper, billing time is simple: hours times rate. The trouble is that "rate" is rarely one number. For a typical MSP it's a small matrix:

Now multiply that matrix across dozens of clients and hundreds of entries a month, and you can see why this leaks. A tech logs two hours at 11pm fixing a downed server. To bill it correctly someone has to know it was that client, that the work was after-hours, that it bills against a contract rate, possibly over their included cap, at an emergency rate. That's four lookups for one line. Do it by hand at month-end across the whole book and a few of them will be wrong — always in the direction that costs you money, because under-billing never bounces back.

The fix is encoding the rules once — not applying them every month

The mistake most teams make is treating rate logic as a month-end task: export the time entries, eyeball each one, apply the rates, type the totals into accounting. That's the part that's slow and error-prone, and it's the part that should never be manual.

The approach we took with Morton Command Center is to encode the rate model once, during your build, so it runs automatically against every entry as time flows in. Because the platform is built around your specific stack rather than a generic template, the rules are set up to match exactly how your business already bills — your contract rates, your per-activity rates, your after-hours and emergency rates, your plan caps. There's no settings screen to wrestle with; the logic is wired to your billing model when we stand the tenant up.

Concretely, here's what "applied automatically" means once it's in place:

The shift is subtle but it's the whole game: the rate decision happens at the moment the entry is classified, against rules that don't forget and don't get tired at 4pm on the last day of the month.

Keeping T&M and project work in their own lanes

After-hours multipliers get the attention, but the quieter leak is project hours bleeding into your BAU support bucket. A tech working on an active migration logs time the same way they log a password reset, and if those hours land in the general support pile they either get billed at the wrong rate or — worse on a fixed-fee project — get billed twice or not at all.

So the same classification that applies rates also keeps the lanes separate. Time logged against an active project rolls up into project-specific billing and stays distinct from recurring support, so project hours are invoiced on their own rather than disappearing into the monthly support bucket. Project work picks up the project rate; BAU support picks up the contract rate; after-hours work on either picks up the after-hours rate. Each entry ends up where it belongs, with the rate that belongs to it.

Why this matters more than it sounds

The MSPs we've worked with consistently find, once rate logic is running automatically, that they'd been under-capturing by a meaningful margin every month — after-hours work billed flat because nobody flagged the multiplier, project hours buried in support, overage that never made it past the included cap. It's rarely dramatic on any single invoice, which is exactly why it persists: a 1× emergency call or a misfiled project hour doesn't look wrong, it just looks like a normal line. Across a year and a full client book, those normal-looking lines add up to real money.

There's a second benefit that's easy to overlook: defensibility. When a client questions a charge, "the system applied your contracted after-hours rate because the work was logged as an after-hours call" is a far better answer than "I think someone marked it as emergency." The rule is consistent, it's the same for every client on that agreement, and it's the same every month. Consistent billing is easier to stand behind than billing that depends on who happened to be processing invoices that week.

Where the invoice actually lands

Once the rates are applied, the entries become invoice line items at month-end and land in your accounting system — QuickBooks, Xero, Sage, or anything with an API. We build that accounting integration to fit your stack as part of your engagement. For our own MSP that means generating invoices straight into QuickBooks Desktop — through Conductor, the local sync agent we use so the accounting system never has to be exposed to the internet — including a generate-from-unbilled-timecards flow so the priced entries roll up into the right customer's invoice without re-keying. QuickBooks Online, Xero, and any accounting system with an API are built the same way, custom to your workflow. Either way the principle is identical: the rate math is finished before the line ever reaches accounting. If your tool has an API, we build the integration for it — to fit exactly how you bill.

If you want the full picture of how time entries travel from tracker to invoice, we wrote that up in time tracking that flows directly to invoices, and the end-to-end month-end generation side lives on the automated MSP invoicing page. And if the month-end crunch itself is what's killing you, where your end-of-month billing time actually goes breaks down which parts of the close are worth automating first.

The one-week version

You don't need a platform to start fixing this. This week, pull last month's after-hours entries and check how many actually carried the multiplier. Then pull a handful of project entries and confirm they billed at the project rate, not the support rate. If either check turns up misses — and it almost always does — you've found money you already earned and didn't bill. The platform's job is to make sure that check passes automatically every month instead of only when someone remembers to run it.