Automating Schedule of Rates (SOR) Coding for Social Housing Maintenance
by Sandlabs Team, Founder, Sandlabs
A technician finishes a job at a housing property, gets in the van, and types a quick note: "cleared blocked gully trap out back, replaced the grate, snaked the line about six metres." Accurate, plain, done in fifteen seconds. Then that note has to become money.
Somewhere between the van and the invoice, a person opens the client's Schedule of Rates, hunts for the line that matches a cleared gully trap, decides whether the replaced grate is a separate billable item or bundled, checks the snaking length against a rate band, and enters codes into the job. Multiply that by 400 to 500 jobs a day across 25 technicians and you have a coding operation that is quietly deciding how much revenue the business actually collects.
This is the gap we keep seeing in social housing maintenance. The field work is fine. The invoicing engine is fine. The bit in the middle - turning what a tradesperson did into the exact code the housing client will pay against - is manual, slow, and error-prone. Every wrong or missed code is either revenue left on the table or a clawback waiting to happen.
We built a Claude-native coding layer for a plumbing maintenance contractor servicing social housing to close that gap. It reads a technician's spoken or written note, matches it to the correct line in that client's Schedule of Rates, and writes the confirmed code back into AroFlo. This post is how it works, why the accuracy problem is harder than it looks, and where it sits alongside the tools a contractor already runs.
The revenue that leaks between the van and the invoice
Most people outside the sector assume maintenance contractors bill by the hour or by a quote. High-volume social housing work does not run that way. It runs on a Schedule of Rates: a large, fixed price book, agreed with the housing client, where every conceivable task has a code and a set price. Clear a blockage, code X. Replace a mixer tap, code Y. Attend but find no fault, code Z.
The SOR is how the client keeps thousands of small jobs a month priced consistently across every contractor they use. For the contractor, it means revenue is not a function of effort or time. It is a function of coding. If the work is done but coded to the wrong line, or a billable item is missed entirely, the money does not arrive - regardless of how well the job was done on site.
At low volume, a good office person absorbs this. They know the client's SOR, they read the notes, they pick the codes. At 400 to 500 jobs a day, that same task becomes a structural bottleneck:
- Under-coding. A job has three billable items but the note only makes two obvious, so the third never gets coded. The work was done and paid for in wages, but never invoiced.
- Wrong codes. The library is large and cryptically worded. Two lines look almost identical but carry different prices or different evidence requirements. Pick the wrong one and the claim gets rejected or, worse, paid and later clawed back.
- Backlog. Coding cannot keep pace with the field, so jobs pile up waiting to be coded, invoicing slips, and cashflow drags behind the work by weeks.
None of this shows up as a dramatic failure. It shows up as a margin that is always a little thinner than it should be, and an office that is always a little behind.
Why manual coding breaks at 400 to 500 jobs a day
The instinct is to fix this with people or with rules. Both hit a wall.
More people does not scale cleanly. SOR coding is skilled work. A coder has to understand the trade, read a terse field note, and know a specific client's price book well enough to choose between near-identical lines. That knowledge takes months to build and lives in a few experienced heads. Doubling the coding team means doubling that training, and coding quality gets more variable, not less, as the team grows.
Rules do not survive contact with real notes. You cannot write a lookup table that maps "cleared blocked gully trap out back, replaced the grate" to the right codes, because the next note will say "unblocked the drain outside, put a new cover on" and mean the same thing. Field language is endlessly variable. Keyword matching and rigid templates break the moment a technician describes the same job in different words, which they always do.
Every client is a different library. A contractor servicing multiple housing clients is not coding against one SOR. They are coding against several, each worded its own way, each updated on its own schedule. A code that is correct for one client is wrong or non-existent for another. The coder has to hold the right library in mind for the right job.
This is the core reason the middle step stays manual while the field and the finance systems get automated around it. It is a language problem wearing a data-entry costume, and language problems are exactly where older automation fell down.
Transcription is not coding
Here is the distinction that matters, because it is where a lot of "AI for trades" marketing gets it wrong.
AroFlo's own JobScribe already does a genuinely useful thing: it captures what happened on a job and turns speech into a written note. That is transcription, and it is worth having. But transcription hands you a cleaner version of the same free-form language. It does not tell you that this job is SOR line 4.12.3 at the medium rate, plus a separate line for the grate, and nothing for the snaking because it falls under the same line.
The hard, valuable part is not writing down what the technician said. It is mapping what they said to the exact client-specific code that gets paid. That is a reasoning task: interpret intent, understand the trade, hold a specific price book in context, and choose. It is the difference between a faster note-taker and a coding intelligence, and it is the part that actually moves revenue.
We built the coding intelligence. It sits on top of the note - however that note is captured - and does the mapping that neither transcription nor a rules engine can.
The Sandlabs approach: note to correct code, back in AroFlo
The system runs in four steps, and the shape of it matters more than any single component.
1. Capture. The technician describes the work in their own words, on site, by voice or text. No new vocabulary to learn, no dropdown to hunt through in the field. The point is to keep the technician doing what they already do well - describing the job plainly - and move the hard part off their plate.
2. Understand and match. A Claude-powered engine interprets the note and retrieves the right code or codes from that specific client's Schedule of Rates. For each match it returns a quantity where relevant and a confidence score. This is where the language problem gets solved: the engine reasons about what the note means, not just which keywords it contains, and it works against the correct library for that client.
3. Confirm. High-confidence matches are ready to book. Anything the engine is unsure about is flagged for a quick human check rather than guessed. A person stays in the loop precisely where judgement is needed, and nowhere it is not. This is a deliberate design choice, not a limitation - it is what keeps the numbers trustworthy.
4. Write back. The confirmed code lands on the job in AroFlo, ready to invoice. The contractor's existing system stays the source of truth. Nothing about their invoicing, reporting, or client submission process has to change.
The connection into AroFlo is a private Sandlabs connector running inside Claude - a scoped, purpose-built link to the job system, not a general-purpose bridge and not another app for anyone to log into. From the office's point of view, coded jobs simply start appearing correctly, faster.
What makes it accurate: client-specific libraries plus a human confirm
Accuracy in this system does not come from a clever one-off prompt. It comes from two design decisions working together.
The first is that the engine reasons against the actual client library, not a generic idea of what a plumbing code should be. When a note comes in for a given housing client, the matching happens against that client's SOR, with its specific wording, structure, and price bands in context. The same note for a different client resolves to that client's codes. This is what a rules engine cannot do and what a human coder does slowly.
The second is the confidence threshold and the human confirm. The engine is honest about what it is sure of. Clear matches flow through. Ambiguous ones - a note that could plausibly map to two different lines, or a job that hints at a billable item without stating it - are surfaced for a person to resolve. Over time, that human confirmation is also the signal that shows where the library wording or the capture habits could be tightened.
The result is a coding standard that is consistent across every technician and every job, because the same engine codes all of them, and reliable, because a person still owns the calls that genuinely need judgement. We are deliberately not publishing an accuracy percentage here, because the honest number depends on the client's library and the quality of the notes, and we would rather show it on your data than quote someone else's.
The business case: protect revenue first
It is tempting to sell this as time saved, and it does save time. But time is the by-product. The reason to do it is revenue.
Revenue protection. Every job coded correctly is a job billed correctly. Fewer missed items means fewer under-billed jobs. Fewer wrong codes means fewer rejected claims and fewer clawbacks. The money you already earned in the field actually makes it onto an invoice.
Faster cashflow. When coding keeps pace with the field instead of piling up in the office, invoicing goes out sooner and cash arrives sooner. The lag between doing the work and getting paid for it shrinks.
Consistency at scale. One coding standard applies to every technician and every job, whether it is job 12 or job 480 on a given day. New technicians do not need to learn the price book, and coding quality stops depending on which experienced person happened to look at the job.
Efficiency and hours saved are real, and they matter. They are just not the headline. The headline is that you stop leaking margin on work you have already done. If you want the wider version of this argument, we wrote about the hidden cost of manual work across operations generally.
Security and trust
Social housing work means tenant details can appear in job notes, so the controls around the data matter as much as the coding itself. We describe what the system does, not what any business is required to do - that is a decision for the contractor and their client, not for us.
- Human in the loop before anything is booked. The system proposes; a person confirms the cases that need it. Nothing is invoiced on an unchecked guess.
- Least-privilege, scoped access. The connector into the job system has the narrow permissions it needs to do the coding task and no more. Every action it takes is logged.
- Client data is not used to train public AI models. The contractor's notes and the client's Schedule of Rates stay theirs.
- Claims match the architecture. We only make data-handling and isolation claims that the delivered system actually backs. Where a contractor has specific data-residency or isolation requirements, we design to those and say plainly what is and is not in place.
Sandlabs is an enabling-technology provider. We build the coding layer; we do not provide legal, compliance, or regulatory advice, and we do not decide what a business must do with its data.
The outcome, and who this is for
This is built for owners and operations leads at high-volume trades and maintenance contractors servicing social housing - the ones already running work through AroFlo, already coding to client Schedules of Rates, and already feeling the coding step strain as volume climbs. If coding is where your invoicing slows down, where margin quietly leaks, or where you are one experienced person away from a bottleneck, this is the layer that addresses it.
It is not a rip-and-replace. It sits alongside AroFlo and the rest of the stack as the coding-intelligence layer - the piece that turns field language into the right, paid code, at the volume you actually operate at. If you are earlier in the automation journey and still deciding what to build versus buy, our guide on custom AI agents versus bundled field-service AI is a useful starting point, and the companion piece on AI job costing for field service covers the note-to-rate mapping in more general trades terms.
If you are not sure what a Schedule of Rates is or why the coding step is where revenue leaks, start with what a Schedule of Rates actually is.
FAQ
What is SOR coding in social housing maintenance?
SOR coding is the process of matching a completed maintenance job to the correct line in a housing client's Schedule of Rates - a fixed price book where every task has a code and an agreed price. Because these contracts bill against the SOR rather than by the hour, the code you assign to a job determines what the contractor gets paid for it.
Can you automate Schedule of Rates coding without replacing AroFlo?
Yes. The approach we describe adds a coding-intelligence layer on top of AroFlo rather than replacing it. Job notes are interpreted, matched to the correct client SOR code, confirmed where needed, and written back into AroFlo, which stays the system of record for invoicing and reporting.
How is this different from AroFlo JobScribe or voice-to-text?
Transcription tools turn speech into a written note. They do not decide which Schedule of Rates code the job should be billed under. The coding layer takes the note - however it was captured - and maps it to the exact client-specific code, with a quantity and a confidence score. Transcription is a cleaner note; coding is the billable decision.
How do you keep the coding accurate?
Two things. The engine reasons against the specific client's Schedule of Rates, so it chooses from the right library rather than a generic one. And it returns a confidence score, so clear matches flow through while uncertain ones are flagged for a quick human check before anything is booked. A person stays in the loop where judgement is genuinely needed.
Is tenant data safe in a system like this?
The controls are designed around it: a human confirms before jobs are booked, the connector into the job system uses least-privilege scoped access, every action is logged, and client data is not used to train public AI models. We only make data-handling claims that the delivered architecture actually supports, and we design to a contractor's specific residency or isolation requirements where they exist.
Talk to us about your SOR coding
If you run high-volume maintenance against client Schedules of Rates and coding is where revenue leaks or invoicing slows, we would like to see your setup. Book a free 30-minute intro call at sandlabs.com.au/book-a-call or email [email protected].