Two rates, never on the same page
Ask a staffing controller where their margin actually lives, and the honest answer is: split across two systems that were never designed to talk to each other. The bill rate — what the client pays per hour — sits on the invoice, generated from the billing system or VMS the client requires. The pay rate — what the worker actually earns per hour — sits on the payroll register, generated entirely separately by the payroll provider. Nobody outside the agency ever sees both numbers next to each other, because no single document is built to show them together.
That gap between the two rates is precisely the agency's margin, and precisely the thing that's hardest to verify without manually pulling both documents and lining them up worker by worker, week by week — a task that becomes genuinely tedious past a handful of workers and multiple clients, and one where a single missed line can hide a real problem for months.
Why this matching matters more than a monthly average
A monthly gross margin figure — total billed minus total paid, divided by total billed — tells you whether the month was profitable in aggregate, but it hides exactly where any erosion happened. Ten workers with healthy margin can offset two workers whose margin quietly went negative after an overtime miscalculation, and the monthly number would still look acceptable.
Matching at the worker-week level is what makes that kind of erosion visible instead of averaged away. A single week where a worker's overtime hours were billed at the wrong multiplier, or a rate card update landed on one side and not the other, shows up as a specific, addressable line — not a vague sense that this month's numbers looked a little soft.
What this doesn't do, stated up front
Doesn't set rate cards or markup percentages
What you charge clients and what you pay workers are business decisions negotiated separately. This confirms what the actual rates produced — it doesn't recommend or set new rates.
Doesn't connect to your VMS, ATS or payroll platform
There's no API, no login, no integration. You export or download the invoice and payroll documents yourself, the same way you already do, and upload them.
Doesn't calculate payroll taxes or workers' comp
Those calculations happen inside your payroll system when pay is actually run. This reads the resulting pay rate, it doesn't recompute the underlying payroll math.
Doesn't decide what margin is acceptable
A thin margin might be a strategic client relationship, or it might be a problem — that judgment call is yours. This surfaces the number clearly enough to make the call.
What's left is narrow, and it's exactly the part that determines whether a margin problem gets caught in week two or discovered three months later at quarter-end.
What gets matched
| Field | Source |
|---|---|
| Worker, week-ending date, hours | Timesheet, invoice, payroll register |
| Bill rate, straight time and overtime | Client invoice |
| Pay rate, straight time and overtime | Payroll register, pay stub |
| Shift differential, per diem where applicable | Invoice, payroll register |
| Realized margin per worker-week | Calculated from the four above |
Five values, read from two documents that were never designed to be compared side by side — and compared anyway.
How a worker-week gets matched across two documents
Matching runs on worker identity, week-ending date and hours together, since any one of these alone can be ambiguous — a common surname appearing across multiple assignments, or a week-ending date that shifts by a day between a client's invoice format and the payroll provider's own calendar convention.
| Signal | What it confirms |
|---|---|
| Worker name and identifier | The invoice line and payroll line refer to the same person |
| Week-ending date | Both documents cover the same time period |
| Hours worked | Straight time and overtime hours agree between the two sources |
| Rate card reference | The bill rate and pay rate match what the assignment specifies |
A worker-week where all four signals agree lands at high confidence. Where hours diverge between the invoice and the timesheet, or a name doesn't quite match between systems, the line is flagged for a quick manual confirm rather than matched on a guess.
One worker, two rates, one spread
A single worker's week, with regular and overtime hours both present.
| Line | Hours | Rate | Amount |
|---|---|---|---|
| Straight time, billed | 40 | $30.00 | $1,200.00 |
| Overtime, billed (1.5x) | 6 | $45.00 | $270.00 |
| Straight time, paid | 40 | $18.00 | $720.00 |
| Overtime, paid (1.5x) | 6 | $27.00 | $162.00 |
| Realized margin | — | — | $588.00 |
Neither the invoice nor the payroll register alone shows the $588 margin on this worker's week — each document only shows its own half. Matched together, both the straight-time spread and the overtime spread confirm the 1.5x multiplier was applied consistently on both sides, which is exactly the check that catches the cases where it wasn't.
How it works
Upload the invoice and payroll register
Plus the timesheet, if hours need independent confirmation beyond what the invoice already shows.
Each worker-week is read from both documents
Bill rate and hours from the invoice, pay rate and hours from payroll, kept linked to the same worker and week.
Matched and margin calculated
Straight time and overtime compared independently, with a confidence level per worker-week.
Export
Excel, CSV or JSON — bill rate, pay rate and margin as their own columns, ready to sort or filter.
Overtime multipliers, matched independently
Overtime is where bill-side and pay-side rules most often diverge, because they come from entirely different rulebooks. A client contract might specify a flat 1.5x billing multiplier for any hours over 40 in a week. The actual pay-side obligation, though, depends on the worker's state — some require daily overtime after 8 hours regardless of the weekly total, others follow the federal weekly-40 standard exactly, and a few have their own additional rules for specific industries.
Matching straight time and overtime as separate lines, rather than one blended hourly average, is what lets a mismatch between the two rulebooks show up as a specific number instead of disappearing into a combined average that looks plausible at a glance.
Catching rate drift before it compounds
Rate drift rarely happens all at once — a client renegotiates a bill rate at contract renewal, and the update gets applied in the billing system immediately, while the corresponding pay rate change (if one was ever intended) takes a payroll cycle or two to catch up, or never gets made at all if nobody flags it. Over a few months, that gap can either quietly erode margin or, less often, overpay a worker relative to what the new rate card was supposed to support.
Because each week is matched independently rather than smoothed into a running average, a drift that started three weeks ago is visible as soon as this week's documents are processed — not discovered at quarter-end when the cumulative effect finally shows up in a P&L review.
Shift differentials and per diem
Many staffing assignments carry extra pay components beyond the base hourly rate — a night-shift or weekend differential, a per diem for workers on a travel assignment, a hazard premium for certain industrial placements. These components frequently apply to the pay side, the bill side, or both, and not always at the same rate or in the same proportion.
Reading these as their own line items, rather than folding them into the base rate, keeps the margin calculation accurate even for assignments with several extra pay components stacked on top of straight time and overtime.
Margin trends across a full engagement
A single week's margin tells you about that week. Matching every week of an engagement and exporting them together turns that single data point into a trend — a worker whose margin has steadily narrowed over eight weeks tells a very different story than one whose margin has stayed flat, even if this week's number looks identical for both.
This trend view is often what actually prompts a rate card renegotiation with a client, rather than a single week's number, which can look like normal week-to-week variance until it's placed next to several weeks before it.
Who this is for
Staffing agency controllers
Margin confirmed at the worker-week level instead of estimated from a monthly average.
Agency owners renegotiating client contracts
A clear margin trend to bring to the table, rather than a gut feeling about which clients are underperforming.
PEOs and employer-of-record providers
The same bill rate to pay rate matching applied across a broader worker roster.
Bookkeepers serving staffing clients
A consistent margin check applied regardless of which client's invoice format is in front of them.
This isn't a payroll or billing system
Worth being precise about the boundary. This doesn't run payroll, generate client invoices, or connect to any payroll or billing platform. There's no login, no API. What it reads is the documents your existing payroll and billing systems already produce, matched together to expose the number neither system shows on its own.
How often to check margin
Matching margin on the same cadence as your billing cycle is the simplest rule that actually works — weekly for agencies that bill weekly, biweekly for those on a biweekly cycle. Checking less often than invoices go out means a margin problem can run for several billing periods before anyone notices it.
For an agency managing many clients on different cycles, batching margin checks on a fixed weekly rhythm across all clients at once is usually simpler than reacting to each invoice individually as it goes out.
What accuracy actually looks like
Matching accuracy is best thought of as a confidence distribution across worker-weeks rather than a single percentage. An agency with clean, consistent timesheet and payroll data sees most worker-weeks land at high confidence, with a small tail needing review. An agency with several new clients or inconsistent timesheet formats sees a larger medium-confidence tail — more review time, not necessarily more actual errors.
In practice, most agencies with a stable client base and consistent payroll data see somewhere between 85% and 95% of worker-weeks land at high confidence, with the rest split between a quick medium-confidence confirm and a small number of genuine discrepancies worth investigating individually.
Margin versus true cost
The visible spread between bill rate and pay rate is only part of an agency's actual cost to place a worker. Payroll taxes, workers' compensation insurance, unemployment insurance contributions and any benefits the agency covers all add to the true cost per hour, on top of the pay rate itself. Two placements with an identical visible spread can have meaningfully different true-cost margins if one carries a higher workers' comp classification than the other — a distinction that matters for understanding which clients are genuinely most profitable.
Where a payroll register or burden report breaks out these additional cost components, reading them as their own fields alongside the base pay rate makes it possible to build a true-cost margin view on top of the simpler bill-rate-minus-pay-rate figure, without requiring a separate manual calculation for every worker.
For most day-to-day margin monitoring, the simpler bill-rate-minus-pay-rate figure is the right default — it's fast to check and catches the large majority of drift causes. The true-cost view earns its extra step at renewal time, when a client relationship's actual profitability, burden included, needs a harder look before a rate card gets renegotiated. Running both views side by side at that moment, rather than relying on the simpler figure alone, avoids renegotiating a rate based on a margin picture that looks healthier than it actually is, only to find the renegotiated rate still doesn't cover the real cost of the placement.
Privacy
Uploads go over TLS, encrypted end to end.
Processing runs on EU-hosted infrastructure.
Original documents are deleted immediately after extraction.
Worker pay and client billing data are never used to train AI models.
Full details are on the security page.
