The gap between "the work happened" and "the client got billed for it" is where MSP revenue quietly leaks. A tech logs two hours fixing a mail flow rule on a Saturday night. Three weeks later, whoever runs billing is squinting at a timesheet export, trying to remember whether that client is on a fixed rate or T&M, whether weekend work gets a multiplier, and which project line it should land on. Some entries get billed. Some get forgotten. Some get billed at the wrong rate. None of it is malicious — it's just friction, and friction at the end of the month is expensive.

When we built the timecard-to-invoice flow in Morton Command Center, the goal was narrow and specific: take the time entries that already exist in your stack and turn them into invoice lines a human can review in a few minutes, instead of rebuild from scratch in a spreadsheet. This post walks through how that actually works — what's matched, what's calculated, and what still needs a person in the loop.

Where the time entries come from

We don't ask you to re-enter time. Morton Command Center reads time entries from your time-tracking tool — we build that read against whatever you use (eBillity, Toggl, Clockify, or anything with an API), custom to your stack — and from its own native timecard store, which is included with the product. The two can run side by side, so a tech who logs in your time tool and a tech who logs natively both feed the same pipeline. Every entry carries a source pill so you can always see which system it came from.

For shops that capture time elsewhere, there's an authenticated ingest endpoint (API-key based) that other systems can POST entries into — mobile clock-ins, an autofix script, an email-to-timecard relay, or a tool like Toggl or Clockify posting through that webhook. There are two ways in: we build a direct read against your time tool as part of your engagement, custom to your stack, or you POST entries through the ingest webhook and we store them as native time. The native timecard store ships with the product; the reads to outside tools are built to fit your stack. Either way, whatever you track time in — as long as it has an API — its entries feed the same pipeline.

Matching: client, project, and rate

A raw time entry is just a duration, a person, and usually a note. To become an invoice line it has to answer three questions: who is this billed to, against what, and at what rate?

The matching layer resolves each entry to a client, and where applicable to a project or activity, using the mappings you've already set up rather than guessing from a name string. That mapping discipline matters — "Acme Corp" in your time tool and "Acme Corporation, LLC" in your accounting system are the same client, and a name-match would miss it. We lean on explicit crosswalks instead, so the entry lands on the right customer every time.

Rate is the part people underestimate. The activity dropdowns themselves are sourced from whatever owns that capability for your tenant — your time tool, your accounting system's activity catalog (we build that read against your books; any accounting tool with an API — QuickBooks, Xero, Sage, or whatever you run — feeds the list the same way once we wire it to your stack), or the native store — so the activity on an entry already lines up with how your books are organized. From there the billable rate follows the labor rate and billing configuration for that client, not a flat house rate applied to everyone. A managed-services client and a break-fix client logging the identical activity can resolve to different line amounts, because the rate comes from their config.

After-hours rates

The Saturday-night example isn't incidental — it's exactly the kind of entry that gets mis-billed by hand. If your agreement carries a separate after-hours (emergency) rate, that's a rate you set once in the client's billing config, and an entry that classifies as after-hours work resolves to it automatically — instead of the billed amount depending on "whenever the person doing billing happens to remember the engagement terms." Because the after-hours rate lives in the config rather than in someone's head, the weekend mail-flow fix lands at the right amount, and the same rule applies the same way for every tech and every client it's set up for. The whole point of moving this logic out of someone's head and into the billing config is that it stops depending on who's doing the invoicing that month.

Generate-from-timecards: the actual step

Once entries are matched and priced, the generate-from-timecards action turns the unbilled time for a period into draft invoice lines. This is a real, shipped capability — not a roadmap item. It reads the unbilled entries, groups them by client, applies the matching and rate logic above, and produces invoice lines you can look at before anything is committed.

That review step is deliberate. Generated lines are a draft, not an auto-send. You see what's about to be billed, to whom, for how much, and you catch the edge cases — the entry that was logged to the wrong client, the note that needs cleaning up before a customer reads it, the two-hour block that was actually courtesy time you don't want to charge for. Nothing leaves the building until a person says go. The unbilled-time and unsubmitted-time views exist for the same reason: so the stuff that hasn't been turned into a line yet is visible, instead of silently aging into "we'll catch it next month" (which is to say, never).

Into your accounting system — your integration, built to fit your books

When the lines are right, they become an invoice in your accounting system, through an integration we build for your stack as part of your engagement. Because the platform is API-driven, any accounting system that exposes an API — QuickBooks Online, QuickBooks Desktop, Xero, Sage, FreshBooks, NetSuite, or whatever you run — connects the same way: we build the integration to fit your books and your workflows rather than forcing you onto a one-size-fits-all connector. (QuickBooks Desktop, for instance, connects through Conductor, a local sync agent that talks to your QuickBooks company file without exposing it to the internet, so there's no firewall port to open and your books never sit on a public endpoint.) If your tool has an API, we build the integration — custom to your stack.

Invoice creation into the connected accounting system is genuinely read-write and built to be idempotent, with server-side validation that the customer on the line actually maps to a customer record on the accounting side before anything is written. That guard is there specifically so a mismatched mapping fails loudly at generation time instead of quietly creating an invoice against the wrong account in your real books.

Where this fits the bigger billing picture

Timecard-sourced invoices are one of a few ways billing gets created in Morton Command Center. Recurring monthly invoices handle the flat managed-services fees that don't depend on hours. Create-from-billing-config handles per-client standing charges. Generate-from-timecards is the one that catches the variable work — the projects, the after-hours calls, the T&M overflow — that recurring billing structurally can't see. Together they're meant to make the month-end close a review exercise rather than a reconstruction exercise. We dug into that month-end rhythm separately in why end-of-month billing eats your best days, which pairs naturally with this one.

A couple of honest boundaries, because the whole value here depends on trusting the numbers. The accuracy of generated lines is only as good as the mappings and billing config behind them — if a client's rate or activity mapping isn't set up, that's where setup time goes, and it's time well spent. And this is near-real-time, not instant: time syncs run on a schedule (eBillity hourly, for instance), so an entry logged thirty seconds ago may not be in the pool for another cycle. For a once-a-month billing run, that's a non-issue; it's just worth knowing the data is cron-warmed rather than live to the second.

The shape of the win

The math on this isn't dramatic per entry — it's a few minutes saved here, a forgotten weekend call recovered there. But it compounds. Every billable hour that used to fall through the cracks because reconstructing it by hand wasn't worth the effort now shows up as a line by default. Across a year, the recovered after-hours work and the eliminated rate errors tend to dwarf the time saved on the close itself. That's the case we keep seeing: the automation pays for itself less by being fast and more by being complete.

If you want the full picture of how time tracking and billing connect, we lay it out on the time tracking and billing for MSPs page, and the broader invoicing workflow lives on automated MSP invoicing. Both go deeper on the surrounding pieces this post only touches.