The work on this page is covered by a non-disclosure agreement with ScaleXP and their end client. Client names, specific data structures, and business details are not disclosed. This is not just a legal requirement. It reflects how I approach every engagement. Client data stays private. Always.

How ScaleXP ships backend automation their clients can trust with live financial data
Code can be reverted. A line written into a live general ledger cannot. That one fact set every rule in this build.
The Problem
A creative production agency ran delivery in Teamwork and money in Xero. Projects, tasks and expenses on one side. Invoices, bills and the chart of accounts on the other. The same client existed in both, keyed once into each, and at month end a person reconciled the two by hand.
ScaleXP designs Notion workspaces and the automation around them. They brought Abhiman Labs in to own the backend for this one and build the sync properly.
The harder half of the brief was not the syncing. It was the writing. Teamwork is a project tool, and a wrong record there is a wrong record. Xero is a live general ledger, and a wrong record there is a line in an audit trail with a date on it. It does not get deleted. It gets corrected, and somebody's accountant does the correcting. An automation that writes into that has to be right on the first pass, on every run, with nobody watching.
One identity across two systems
Teamwork calls them companies. Xero calls them contacts. They are the same organisations, held twice, with two sets of IDs and often two spellings of the same name.
- 01Reference tagBoth records already point at each other. Exact, nothing else to check.
- 02Exact nameThe two names are identical.
- 03Name minus the project code"TIT000 - Titanium" is tried against "Titanium".
- 04EmailThe stored addresses agree.
- 05Fuzzy scorePunctuation stripped, "&" read as "and", Pty Ltd and LLC removed, then scored.last resort
The first run does the matching. Every run after it reads the answer. A confirmed pair gets a permanent reference written onto both records, each one pointing at the other, and around 1,300 contacts carry one. A rename on either side no longer breaks the link.
Invoices, bills, and the files that belong with them
With identity settled, the money follows a fixed path.
Project codes land in Xero as a tracking category, and the valid options are pulled live on the run rather than read from a list captured at build time. A code that has since been retired is never written, and a Xero bill that has already been paid is left alone with the change flagged instead.
Receipts and project files attached in Teamwork are pushed onto the matching Xero record, so the document sits with the transaction instead of in a folder someone has to go and find. A file is matched by the invoice number in its filename, read past differences in case and spacing, so a receipt saved by hand as "inv 8921 second page" still finds INV8921. It counts as synced only once Xero confirms it, so a failed upload is retried on the next run rather than marked done.
Every sales invoice is created as a draft. A person reviews it and sends it.
Never write on a guess
Name matching is the load-bearing part of the whole system, so it carries the strictest rule. Every candidate pair is scored before anything is written anywhere.
The middle band is the design. A pair inside it looks like a match and might not be, which is precisely where an automation with no middle band writes a bill against the wrong supplier. A short name also cannot match a longer one just by being a fragment of it.
Confirm the write, do not trust the response
The orchestration logic is a single code node, over 30KB of it. Pushing a change to it is an API call, and a success response from an API means the request was accepted. It does not mean the right bytes are sitting in the workflow.
So every push is read back. The node is fetched after the write and md5 checked against the source file on disk. If the two hashes disagree, the deploy is not finished.
n8n adds a second version of the same question. Editing a workflow only changes its draft. Production keeps running whatever was published last, which means a workflow can look correct in the editor and still be executing older logic on schedule. So every publish is re-read live and the active version confirmed to be the one just written.
Test without touching the client's data
Every test run uses pinned fixtures. The credentialed nodes are handed their input instead of being allowed to fetch it, so no node in a test ever reaches a real Xero or Teamwork endpoint. Where a test genuinely needs a record to exist, that record is fictional, created and deleted immediately, with the deletion verified by reading the record back.
The client's ledger is not a staging environment. Nothing in the build treats it as one.
What happens when it is not sure
It stops. Not the whole run, just that record, which is left untouched and handed to a person instead.
There is one digest email per run. Not one per record, which is how a notification channel turns into something people filter into a folder they never open. A clean run sends nothing at all, so an email from this system means a decision is waiting. Volume has a ceiling too. Each run writes at most 40 records per direction, anything over the cap carries to the next run, and the runs come every 12 hours, staggered 15 minutes apart.
The quietest rule is the one that matters most in a two-way sync. If both sides already hold the same value, nothing is written. That single check is what stops two systems that each watch the other from bouncing the same record back and forth on every cycle.
What changed for the team
What changed in the system
The Result
Four workflows run in production behind a shared error notifier, and around 1,300 contacts stay matched across Teamwork and Xero with nobody maintaining the mapping.
Nobody watches it run. That is what the rules above buy. It is built to stop rather than improvise, and anything that does not clear the bar waits with an email attached to it.
For the agency, a record is keyed once and is in both systems by the next cycle. Month end is a check rather than a rebuild, and the audit trail in Xero holds what the team actually did rather than what survived being typed twice.
ScaleXP still routes their backend automation work to Abhiman Labs, and this was one project of several. If you run a consultancy that needs a specialist behind the technical layer of your client work, that is the conversation to start.