Autotask PSA
Autotask contracts, and where the billing leaks
In Autotask PSA the contract is a header and the billable detail lives in its children: contract services and their unit counts for recurring work, contract blocks for prepaid hours, and exclusion sets for what falls outside. The six common leaks are service unit counts that stopped matching reality, blocks drawn past zero, time entries marked non-billable, work against expired contracts, excluded work absorbed rather than charged, and contracts whose annual uplift was never applied. All six are readable through the REST API with an API-only user.
Kyslan finds the unbilled work in your own PSA, then writes the change order that bills it. First report free, read-only. Claim it back →
How an Autotask contract is shaped
The contract record holds the client, the type, the period and the setup. What you can actually bill for hangs off it:
| Object | What it holds | Why it drifts |
|---|---|---|
| Contract | Client, type, start and end dates, billing setup | Rarely. Headers are stable |
| Contract services | The recurring services sold, and their unit counts | Constantly. Units change when the client changes |
| Contract blocks | Prepaid hours purchased and remaining | Every time work is logged |
| Exclusion sets | Work types and roles the contract does not cover | Set once, then quietly ignored at ticket close |
| Time entries | Hours, work type, billable status | Per entry, at the worst moment |
The pattern is the same as every PSA: the header stays right and the children go stale. Any check that reads the contract without walking its services and blocks will report a clean book.
The six leaks
1. Contract service unit counts that stopped matching reality
A recurring service on an Autotask contract carries a unit count, and that count is what bills. New users get onboarded and new endpoints get an agent, but the unit count is a separate edit that somebody has to remember. Compare units per service against the live count for whatever the service represents: directory users, RMM agents, licence seats.
2. Blocks drawn past zero
Covered in detail below, because in Autotask shops it is usually the biggest single number.
3. Time entries marked non-billable
Pull 90 days of time entries and group non-billable hours by work type, by queue and by resource. As in every PSA, a cluster on one work type is a default set wrongly, which is a five minute fix rather than a discipline problem.
4. Work against expired contracts
List contracts whose end date has passed and check for time entries dated after it. Either you are delivering without an agreement, which is a risk, or billing without one, which is a different risk.
5. Excluded work absorbed instead of charged
Exclusion sets are the mechanism Autotask gives you for saying "this work type is not covered". They only produce revenue if the excluded work is then billed some other way. In practice the engineer logs the time against the contract anyway, and the exclusion set becomes documentation of money you chose not to collect.
Check: hours logged against work types that appear in a client's exclusion set, and whether a separate charge exists for them.
6. Annual uplifts never applied
The clause exists in the contract. Applying it is a manual edit to the service prices. List every contract with an uplift clause and the date its prices last changed. Anything over 13 months is overdue, and the arrears compound because the base never caught up.
Blocks are the expensive one
Autotask block hours are prepaid: the client buys hours, the balance draws down, and when it hits zero somebody is supposed to sell them another block.
What actually happens is that the balance reaches zero on a Tuesday, an engineer is mid-problem for a client they like, and the work continues. The hours keep being recorded. Nothing enforces the balance, because enforcing it would mean refusing to help a paying client, which no service desk will do on its own authority.
A block below 20% remaining raises a ticket to the account owner. A block at zero raises one to a manager. Neither of those stops the engineer from helping, which is why they work: the decision to keep going is still yes, but now somebody commercial knows it was made. Without that, the first person to notice is whoever runs the numbers at quarter end, and by then the hours are too old to invoice comfortably.
The check itself is simple and worth running weekly: every block, hours purchased, hours used, balance, and the date of the last entry against it.
Reading it through the API
Autotask's REST API is queried per entity, with the query posted to the entity's own endpoint rather than assembled as a URL, which means every check here is a small set of separate calls joined on your side rather than one request.
Three practical points before you start:
- Find your zone first. Autotask instances live in different data centre zones and each has its own API base address. Calling the wrong one fails in ways that look like an authentication problem. There is a zone lookup call that returns the correct base address for your account, and it should be the first thing any integration does.
- Use a dedicated API-only user. Not a person's login. Give it a security level scoped to reading the entities you need, and an integration identifier so the calls are attributable in your logs. Revoking it then costs nothing and touches nobody.
- Read-only is enough. Every check described here is a read. No audit needs write access to your PSA, and any tool asking for it for a billing review should be asked why.
Why standard reporting misses it
Autotask reporting is strong within an object and weak across them, which is precisely the wrong shape for this problem. Each of the six leaks is either a comparison between two objects, or a comparison against something outside Autotask entirely:
| Leak | Needs |
|---|---|
| Service unit drift | Contract services against the directory or RMM. Outside data |
| Blocks past zero | Blocks against time entries. Two objects |
| Non-billable time | Time entries grouped and compared against a norm. Needs a baseline |
| Expired contracts | Contracts against time entries. Two objects |
| Excluded work absorbed | Exclusion sets against time entries against charges. Three objects |
| Missing uplifts | Contract terms against price change history. Outside the reporting model |
None of that is a criticism of the platform. It is a description of why the gap survives in well-run shops: the queries that would find it are joins nobody has time to write twice, so they get written once, run once, and never scheduled.
Kyslan connects to Autotask PSA read-only, runs all six checks, prices each finding annually, and re-scans weekly so new gaps surface while they are still easy to invoice. First audit free, or read the sample report first.
Common questions
Where does Autotask PSA store what a contract bills?
On the contract's children rather than the contract header. Recurring revenue comes from contract services and their unit counts, prepaid work comes from contract blocks, and what is not covered is defined by exclusion sets. The header carries the client, dates and setup, and rarely goes stale, which is why a contract can look correct while under-billing every cycle.
How do I find Autotask block hours that have run out?
List every contract block with hours purchased, hours used, the remaining balance and the date of the most recent entry against it. Flag anything at or below zero, and anything below 20% remaining. Autotask does not prevent time being logged against an exhausted block, so the work continues and the hours accumulate until someone runs the numbers.
Do Autotask exclusion sets generate revenue?
Only if excluded work is then charged another way. An exclusion set defines what a contract does not cover, but it does not stop time being logged against the contract anyway. Checking hours recorded against work types that appear in a client's exclusion set, and whether a separate charge exists for them, is what turns the exclusion into money.
What access does an Autotask billing audit need?
Read-only, through a dedicated API-only user with a security level scoped to the entities being read and an integration identifier so calls are attributable. No billing audit needs write access. It is also worth resolving your account's API zone first, because Autotask instances sit in different zones with different base addresses and calling the wrong one fails in ways that look like an authentication error.
Why do Autotask reports not show unbilled work?
Because every instance of it is a comparison across two or more objects, or against data that does not live in Autotask at all. Contract service units have to be compared against a directory or RMM count, blocks against time entries, exclusion sets against time entries against charges. Reporting that answers well within a single object cannot see a mismatch between two.
Keep reading
See your own number, then send the invoice for it
Kyslan reads 90 days of your tickets, time entries and contracts, finds the work you delivered and never billed, then writes the change order that puts it back on the invoice. Read only, nothing installed, first report free.
Claim it backFree · read-only key · no card · HaloPSA, ConnectWise Manage, Autotask PSA or a CSV export