One workflow, real money

This one automation could save you thousands a year.

Every lead you type into ServiceM8 by hand costs about nine minutes, done properly. Across every enquiry, every week, all year, a busy shop quietly burns around $9,072 a year on copy-paste. This guide puts your real figure on the board, then hands you the workflow that does it for you.

v0.1 Read time ~10 min You get A calculator + an import-ready workflow Companion to YouTube tutorial

Chapter 01 · The maths

What manual lead entry actually costs you

"It's only five minutes" is the most expensive sentence in a small business. And it isn't even true. By the time someone has read the enquiry, searched ServiceM8 to check the client isn't already in there, created them, added the contact and raised the job, you're closer to nine minutes a lead, done properly. That time feels free because no invoice ever lands for it. But it's paid for, it just hides inside a wage. So let's drag it into the daylight. Punch in your own numbers and watch the real annual figure appear.

Your numbers

min
$

Manual lead entry is costing you

$9,072 / year

That's pure admin time spent re-typing information a computer could capture for nothing. Roughly 27 working days, over five weeks of someone's year, gone on copy-paste. Every dollar of it is recoverable.

202
hours a year
$189
every week
27
working days

How it's worked out: leads/week × minutes ÷ 60 = hours a week, × your hourly cost = dollars a week, × working weeks = the figure above. Nothing fancy, just the time you already spend.

Run the defaults and you can follow every step: a business taking 28 web leads a week, 9 minutes to handle each one properly, at $45 an hour fully loaded, across 48 working weeks. That's 4.2 hours a week, $189 a week, and $9,072 a year. No worst-case, no fudging. Just the lead admin you're already paying for, added up for the first time.

It was never five minutes

The reason the number is bigger than you'd guess is that "entering a lead" is never one action. Done properly, every single enquiry is a little checklist:

  • Read and make sense of the enquiry (~1 min)
  • Search ServiceM8 to see if the client already exists, and read the matches (~1–2 min)
  • Create the client if they're new: name, address, phone (~1–2 min)
  • Add the contact: name, email, mobile, mark them primary (~1 min)
  • Raise the job and paste the enquiry into the description (~1–2 min)
  • Send a quick acknowledgement so the lead doesn't go cold (~1–2 min)

Add it up and nine minutes is honest, arguably generous. Now look at that list again, because it's also the exact job the workflow in the next chapter does for you, every step, in about thirty seconds, for a fraction of a cent. Drop minutes to five if you rush it; the figure's still thousands.

Why $45 an hour, not $30?

The default rate isn't the wage on the payslip. An Australian admin or office assistant sits around $28–$30 an hour in base pay, but that's not what they cost you. Once you add the 12% super guarantee, workers compensation, payroll tax, and leave loading, the genuine cost to the business lands roughly 25–45% higher, call it $40–$45 an hour fully loaded. That's the honest number, so it's the one we default to.

Two other rates are one tap away. $30 if you only want the raw wage. And $80 if the person doing data entry is you or someone billable, because then the real cost isn't their wage at all, it's the quoting, the site visit, or the invoice they didn't get to instead.

The point isn't the exact dollar. It's that the number is never zero, it recurs every single week, and it buys you nothing. A lead typed in by hand and a lead captured automatically land in ServiceM8 looking identical. One of them just cost you five minutes you'll never invoice.

Chapter 02 · The build

The workflow that does it for you

Now the fun part. We're going to replace those nine minutes with a workflow that runs in about thirty seconds and never forgets a step. It's built in n8n and talks to ServiceM8 over plain HTTP. Import the JSON at the end of this guide and you're most of the way there.

We're triggering it from email, because that's how leads actually turn up. A website form notification, a Facebook lead, a "can you quote this?" from a regular, even a forwarded enquiry: nearly all of it lands in an inbox. So the workflow watches a Gmail mailbox, and the moment a lead arrives it captures the sender, the message and any attachments, has AI write a tidy job description, files the whole lot into ServiceM8 as a job, then emails the customer back a branded confirmation with their job number.

flowchart TD A([Lead email arrives]) --> B[Read & map the email] B --> C[Create client + company contact] C --> D[Look up job category] D --> E[AI writes the job description] E --> F[Raise the job] F --> G[Fetch the job number] G --> H[Add the job contact] H --> I[Upload any attachments] H --> J[Reply to the customer with their job number]

Step by step

1
Catch the email
A Gmail Trigger fires on each new message. Point it at a label or a filtered inbox so only real leads set it off.
Node: Gmail Trigger
2
Read and map it
A Code node parses the lead straight out of the email body, the form's table of name, phone, email, address and the issue, into clean fields. This is the one spot you tailor to your own lead emails.
Node: Normalize Lead
3
Create the client + contact
A POST creates the client, then another adds the company contact against it. No duplicate-checking here, we keep this version deliberately simple (more on that below).
Create Client → Company Contact
4
Look up the category
A quick GET finds your job category by name and grabs its UUID, so the job lands in the right bucket on your dispatch board instead of "Uncategorised".
Node: Look Up Category
5
AI writes the description
An OpenAI node reads the whole enquiry and turns the customer's ramble into a clean, plain-text job description, so the job reads like one of yours instead of a pasted email.
Node: Generate Description
6
Raise the job
Create the job with that description and the category, fetch its job number, then attach a job contact so whoever's dispatched has the customer's details on the card.
Create Job → Get Job → Job Contact
7
File the attachments
The form drops uploaded photos in as links, so a small loop downloads each one, creates the attachment record and uploads it to the job. The customer's photos end up right on the job.
Split → Create Record → Upload
8
Reply to the customer
A Gmail send goes to the customer's own email (parsed from the form): a branded HTML email with your logo, their new job number, and a tidy summary of what they submitted, so they know they've been heard within seconds.
Node: Send Confirmation

The bit everyone gets wrong: attachments are a two-step

You can't just push a file at a job in ServiceM8. An attachment is two separate calls, and they have to happen in order. First you create the attachment record, the metadata that says "a file named X, of type Y, belongs to this job". That gives you an attachment UUID. Then you upload the actual bytes to that record's .file endpoint. Skip the first step and there's nothing to upload into; the file has nowhere to live.

# Step 1: create the attachment RECORD (metadata only)
POST https://api.servicem8.com/api_1.0/attachment.json
  related_object       = job
  related_object_uuid  = {{ job_uuid }}
  attachment_name      = site-photo.jpg
  file_type            = .jpg

# Step 2: upload the actual FILE to that record's .file endpoint
POST https://api.servicem8.com/api_1.0/attachment/{{ uuid }}.file
  (the binary file as the body)

Web forms usually list the customer's uploads as links in the email body rather than as email attachments, so a small Code node fans each link into its own item, downloads the file, then runs the two-step once per file. One photo or ten, it just works. (If your leads carry real email attachments instead, the Gmail trigger can download those directly.)

Closing the loop: the customer hears back instantly

The last step is the one customers actually notice. A small heads-up matters here: the lead email comes from the form's notification address, not the customer, so we don't reply to it. Instead we send a fresh email to the customer's real address (the one we parsed out of the form body). We fetch the job's friendly number (the generated_job_id, which only comes back when you read the job after creating it), then send a branded HTML confirmation: your logo up top, a thank-you, their job number in black and white, and their submission played back in a clean table. A lead that emails at 9pm gets a real acknowledgement at 9pm, while the job's already sitting in ServiceM8 waiting for you.

Talking to ServiceM8: one header, fields you can read

No OAuth dance. ServiceM8's private API uses a single API key. Generate one under Settings → API Keys, create one Header Auth credential in n8n, and point every ServiceM8 node at it:

# In n8n: Credentials → Header Auth
Name:  X-API-Key
Value: your_servicem8_api_key

And a deliberate choice in how the calls are built: every request uses Send Body → Using Fields Below and Send Query Parameters, the same boxes you'd fill in by hand. Nothing is buried in a raw JSON blob, so you can open any node and read exactly what it sends. Looking up the category, for instance, is one GET with a filter:

# Find the category UUID by name
GET https://api.servicem8.com/api_1.0/category.json
    ?$filter=name eq 'Service Call'
# -> use the first result's uuid as the job's category_uuid
Why no duplicate-check? To keep this build easy to follow. Every email becomes a fresh client, contact and job. If you'd rather match returning customers and avoid duplicate clients, add a lookup step before Create Client: search the client by exact name first, and only create one if there's no match. Same destination, one extra branch.
All up: a Gmail trigger, a couple of Code nodes, a handful of HTTP calls built from plain form fields, one AI node and a branded reply. That's the whole thing. It's genuinely simple, which is exactly why it's worth doing, the payback in the calculator above starts the day you switch it on.

Take it with you

Grab the workflow and switch it on

Here's the actual n8n workflow from this guide, ready to import. In n8n, open a new workflow, choose Import from File, and drop this in. Add your Gmail and ServiceM8 credentials, set your job category, and you're live. The setup notes are baked into the workflow as a sticky note so you won't have to come back here.

n8n workflow · email to job management lead-email-to-job-management.json Gmail → client + both contacts → category → AI job description → raise job → upload attachments → branded reply Download

Our example wires it into ServiceM8, but the pattern is generic, point the final steps at whatever job-management system you run. The full guide is also available as a print-ready PDF from the Downloads button, bottom-right.

What next

Want this running
for your business?

Trade Magnet builds and self-hosts automations exactly like this one: leads into ServiceM8, quotes out the door, AI dropped in where it earns its keep, with the hosting, credentials and error handling done properly. If you'd rather have it built, wired up and watched over for you, get in touch.

trademagnet.com.au →

New to n8n? Start free at n8n.io, self-hosted or on n8n Cloud. Then see why n8n isn't dead and watch Claude build a ServiceM8 form through a custom n8n MCP.