Run your monthly Freshdesk support billing in one sitting

Review every client's billable support hours for the month, trim what should not go out, then raise the invoices in QuickBooks without leaving the screen.

App
FreshdeskQuickBooks OnlineSlack BotFinanceOperationsData SyncAI Reports
PromptCreate

Build me an app my ops manager opens at the start of every month to run the support billing cycle. We run a managed support desk on Freshdesk, our agents log time against tickets, and that time record is effectively the invoice. Today the month end means exporting a time sheet report, rebuilding the numbers in a spreadsheet, chasing the entries that look wrong, and then typing invoices into QuickBooks Online. I want one screen where I review the hours, correct what needs correcting, and raise the invoices in the same sitting.

The main screen is the billing run. At the top is a period picker defaulting to the month that just ended, with arrows to step back through previous months. Underneath is one row per Freshdesk company, loaded with List Companies. Each row shows the client name, the billable hours logged in the period, the included hours their contract allows, the overage hours, the amount that overage comes to at their rate, and a status of To review, Reviewed, or Invoiced. A totals bar across the top of the table shows hours logged, hours billable after allowances, and the value of the whole run, and it updates as I work through the clients.

Pull the hours with List Time Entries, scoped by company and by the period's executed_at range. Only ever include entries flagged billable. Freshdesk list endpoints return no total count and cap out at 100 records per page, so page until a page comes back short rather than trusting any count, and remember every timestamp is UTC ISO 8601. Call List Agents once per run and cache the result for the session so every entry can show the agent's name instead of an id, because agent ids mean nothing to the person doing the billing.

Round every individual time entry to the nearest fifteen minutes before anything is summed, and make the rounding increment a setting in case we move to six minute blocks later. Show both the raw logged hours and the rounded billable hours on each client row so I can always see what the rounding is doing before I approve anything. Never let rounding be the reason a number is a surprise.

Each client needs a settings panel inside the app holding their included hours allowance for the period, their hourly rate, the QuickBooks customer they bill to, and whether overage bills at the standard rate or a separate overage rate. The allowance and the rate are app side config, not Freshdesk fields, so they have to live in the app's own storage. Default the allowance to zero, which means every billable hour is chargeable, since plenty of clients are pure time and materials. Where an allowance is set, the invoice bills the overage only, and the client row still shows the included hours consumed so I can see who is about to outgrow their contract.

Clicking a client row drills into the individual time entries behind that number. List them by date, showing the ticket the time was logged against, the ticket subject fetched with View Ticket, the agent who logged it, the note on the entry, the raw minutes, and the rounded minutes. In this view I need to trim the minutes on an entry, write an entry off entirely so it drops out of the invoice, and leave a short reason on either action. Store all of that in the app's own storage keyed by time entry id, and never write any of it back to Freshdesk. The agent's original record stays exactly as they logged it, and the client row total recalculates immediately as I edit.

When a client looks right I hit Approve on their row. The handler finds the matching QuickBooks customer with Query Entities, looking the customer up by display name the first time and then storing the customer id against that client so later months reuse the mapping instead of guessing. Bear in mind the QuickBooks query language only takes AND conjunctions and only supports a trailing percent wildcard on LIKE, so keep the lookup simple and let me confirm or correct the match by hand when more than one candidate comes back. The handler then builds the invoice lines from the approved hours and creates it with Create Invoice. Do not have it email the client, I want to read the wording in QuickBooks and send it myself.

The moment the invoice comes back with an id, permanently mark every time entry id that went into it as invoiced in the app's own storage, recording the invoice id, the period, the client, who approved it and when. This is the part that matters most. Freshdesk time entries carry no billed flag of their own, so the app is the only place that knows, and double billing a client is the mistake that destroys trust in a tool like this. An entry id that appears in that ledger is never offered again in any future run. Write the ledger only after QuickBooks confirms the invoice, so a failed invoice leaves the hours available rather than swallowing them. An invoiced row locks, shows the invoice number it produced, and stays readable in a history view of past runs.

Every client row also needs an Explain the hours button that kicks off a background agent. The agent reads that client's tickets for the period with List Tickets and works through the conversations on the ones carrying the most time with List Ticket Conversations, then writes a plain English account of what actually drove the hours. Four or five sentences, written for the client rather than for us, describing the themes and the incidents in normal words rather than reciting ticket numbers. Something like a run of printer failures at two sites and a mailbox migration that took three attempts. The output lands back in the app against that client and period so the manager can read it next to the numbers and paste it into the invoice email. Show the row as generating while the agent is working, timestamp the result when it arrives, and let me re run it after I have trimmed entries.

When the run is closed out, post the summary to Slack with Send a Message: the period, how many clients were invoiced, total billable hours, total value, and the names of any clients still sitting unreviewed. Let me pick the channel in settings. That message is how the rest of the team knows billing is done for the month.

A few things that come up every month and need handling properly. Agents log time late, so any billable entry that falls before the end of the selected period and has never been invoiced should appear in the current run, flagged as caught up from an earlier period, rather than vanishing because its month already closed. Time logged on tickets from contacts with no company attached goes into an Unassigned bucket that is visible but not billable, so I can chase the ticket owner. Clients with zero hours in the period stay in the list but muted, because a support client with no activity at all is itself worth noticing.

The only user is the person running billing, so density beats decoration. I want the whole run readable with as little scrolling as possible, clear totals at the top, edits that save the moment I make them without a separate save button, and an obvious visual difference between a row I have reviewed and a row that is already invoiced and locked.

What does this prompt do?

  • See every client on one screen with the hours their agents logged this month, the hours their contract includes, and how far over they went.
  • Open a client to check the individual entries behind the number, with the ticket and the agent on each one, so you can trim minutes or write a line off before anything is billed.
  • Approve a client and the invoice is raised in QuickBooks Online, with those exact hours locked so the same time can never be billed twice.
  • Press Explain the hours on any client and a background agent reads their tickets for the month and writes a plain English account of what drove the time, ready to paste into the invoice email.

What do I need to use this?

  • A Freshdesk account where agents log time against tickets and flag it billable
  • A QuickBooks Online company you raise your client invoices from
  • A Slack channel for the finished billing run summary
  • The included hours and hourly rate for each client contract, which you set inside the app

How can I customize it?

  • Set a different included hours allowance and hourly rate for each client, or leave the allowance at zero to bill every hour.
  • Change the rounding from fifteen minutes to six minutes, or bill the exact time logged.
  • Bill fortnightly or quarterly instead of monthly by changing the period on the picker, and choose which Slack channel gets the run total.

FAQs

Can the same hours end up on two invoices?
No. When a client is approved and the invoice exists in QuickBooks, those exact time entries are marked as invoiced for good. They never appear in another billing run, even if you reopen the same month later.
Does this change anything in Freshdesk?
No. Trimmed minutes, write offs and notes are stored inside the app. Your agents' original time entries stay exactly as they logged them, so the helpdesk record is untouched.
What happens to non billable time?
It is ignored. Only entries your agents flagged as billable are pulled into the billing run, so internal work and goodwill time never reach a client invoice.
Will the invoice be emailed to my client automatically?
No. The invoice is raised in QuickBooks so you can check the wording and the totals first, then send it yourself when you are happy with it.
Why not just use the Freshdesk time sheet report?
That report emails you a PDF of the hours. It does not let you correct an entry, apply a contract allowance, or raise the invoice, so the billing still has to be rebuilt by hand afterwards.
What if an agent logs time for last month after you have billed it?
It shows up in the next run, flagged as late time caught up from an earlier period, so it gets billed once rather than quietly disappearing.

Related templates

Review desk for portal forms your team still fills in by hand

Stage a batch of filings overnight, then approve each completed form from a screenshot before anything is ever submitted.

Kernel
Google Sheets
Slack Bot
App
Client-by-client cold email pipeline review for agencies

Pick a client and a date range to see sent, replies, meetings booked and the real deal value your cold email produced, campaign by campaign.

Instantly
HubSpot
Slack Bot
App
Audit what Intercom's Fin AI actually resolved before you pay

Review every conversation Fin closed as resolved, judge which ones actually stuck, and see what the gap is worth against your bill.

Intercom
Google Sheets
Slack Bot
App
One triage console for every Jira service desk queue

Merge your IT, HR and Facilities queues into one list ranked by SLA time left, then reply, change status and escalate without ever opening Jira.

Jira Service Management
Jira
Slack Bot
App
Run your Webflow site translations from one review desk

See every page's translation status at a glance, edit translations side by side with the English, and publish only what your team has actually approved.

Webflow
JigsawStack
Slack Bot
+1
App
Legal contract intake desk your teams use instead of email

One place for sales and ops to request an NDA or vendor agreement, watch its status, and let legal launch the contract in a single click.

Ironclad
Slack Bot
General Input Database
App

Stop rebuilding your support invoices by hand every month.

Review the month once, approve each client, and let the invoices and the audit trail take care of themselves.