ServiceM8 Multi-Site Job Card Import
Upload one spreadsheet and this n8n workflow creates every ServiceM8 job card for a multi-site customer. It validates rows, skips duplicates, attaches site contacts and emails a summary.
The Problem
A prospective client’s customers send spreadsheets listing dozens of sites, each needing its own job card in ServiceM8. Entering them one by one in the UI is slow and error-prone. Duplicate job numbers slip in, emails are mistyped, and re-entering a file after a mistake can double up jobs that already exist.
What I Built
I built an n8n workflow behind a simple form. Staff enter the customer name and upload the spreadsheet (.xlsx, .xls or .csv). From there it runs without further input: Looks up the client in ServiceM8 by name. Zero or multiple matches stop the run with a failure email. Cleans each row and validates the job number, site address and email format. Removes duplicate job numbers within the file. Fetches the client’s existing jobs and skips any with a matching PO number, so the same file can be uploaded twice safely. Creates each remaining job with the job number as the PO, retrying up to three times on failure. Attaches the site contact to the job. If that step fails, the job stays and the failure is reported. Emails a summary of created, skipped and failed rows. It uses the ServiceM8 community node for client lookup and job creation, and raw REST calls with header auth for job lookups and contact creation. There is no AI step by design: validation and PO matching need to give the same result every time.
The Result
Status: Completed portfolio case study with a recorded demo and a public repo. It has not been used by a client or in production, so there are no business metrics to report. What the demo shows: One spreadsheet upload creates job cards for every valid, non-duplicate row. A summary email lists what was created, skipped and failed. Re-running the same file skips jobs that already exist instead of creating doubles. What I took from it: I learned an unfamiliar API from a real client brief and turned it into a working, re-runnable import.