Nick George — AI Agents & Automation
Open source · fieldtwin

Test Jobber and QuickBooks integrations without touching a real customer's books.

fieldtwin runs twins of the Jobber and QuickBooks Online APIs on your laptop. Point your code at http://localhost:4010 and it gets the same paths, headers and JSON back, from a fake trades business with months of jobs, invoices and payments, kept in both systems at once.

Open sourceApache 2.0Node 22+v0.4.0

The dashboard: the control room, the event log as it grows, and Jobber and QuickBooks side by side, with every customer and invoice marked as matching or drifted. 1:55, no sound.

The problem

You can't test against a customer's live books.

If you build software for trades and field-service businesses, you know the three options. A client's live account, where every test is a risk to real money. Vendor sandboxes, which start empty, and where a Jobber sandbox and a QuickBooks sandbox never describe the same business. Or hand-written mocks, which return exactly what you expected, and so never catch what you didn't.

None of them suits an AI agent either, which needs somewhere it can make mistakes many times over, in parallel.

How a client's live account, a vendor sandbox, hand-written mocks and fieldtwin compare
fieldtwinA client's live accountVendor sandboxHand-written mocks
Safe to breakYesNoYesYes
Ready to usenpm startWhen the client trusts youAfter a developer account, an app and setupAfter you write each endpoint
Realistic dataA seeded business with months of historyYesGeneric samples, or noneWhat you typed
Jobber and QuickBooks describe the same businessYes, or drifted on purposeYesNoNo
429s, 5xx, lost answers, duplicate webhooks on demandYes, in the vendor's own error formatNoNoOnly the ones you thought of
Skip ahead in timeYes, instantlyNoNoRarely
See what your code changed, and undo itCheckpoints, change lists, rewindNoNoNo
Offline, in CI, many copies in parallelYesNoNoYes
Exactly like productionNo. Modeled from the public docsYesNearlyNo

Swipe the table sideways to compare.

fieldtwin doesn't replace the vendors' sandboxes. It covers what they can't.

How it works

Change one URL, then make it hard on purpose.

  1. 01

    Start the twin.

    Clone the repo, run npm ci, then npm start. It needs Node 22 or newer. No developer account, no app setup, no test data typed in by hand.

  2. 02

    Point your code at it.

    Use http://localhost:4010 instead of quickbooks.api.intuit.com or api.getjobber.com. Change only the base URL: paths, headers and body shapes match the real APIs.

  3. 03

    Make it hard on purpose.

    Add fault rules, load a ready-made scenario like flaky-apis, or jump the clock forward. Tokens expire and scheduled events happen on the way.

git clone https://github.com/nickgeorgeseo/fieldtwin && cd fieldtwin
npm ci && npm start
# fieldtwin: Rowntree Electric is open for business at http://localhost:4010

# The path you'd send to quickbooks.api.intuit.com, sent to the twin
curl -H "Authorization: Bearer dev" \
  http://localhost:4010/v3/company/9341000000000001/customer/1

# Move twin time forward an hour: tokens expire, rate limits refill
curl -X POST localhost:4010/_twin/clock/advance \
  -H "Content-Type: application/json" -d '{"minutes": 60}'

By default the twin accepts any bearer token. Start it with FIELDTWIN_AUTH=oauth and it checks tokens the way the real APIs do, at the vendors' own OAuth paths.

What you get

A whole business from one command.

You getInstead of
A working fake business, in Jobber and QuickBooks at once, from one commandDeveloper accounts, app setup, and test data typed in by hand
Throttling, outages, lost answers, and duplicate webhooks whenever you askMeeting them for the first time in production
Hours of retry waits and token expiry, in secondsTests that sleep, or that never cover it
The same results from the same seed, every run“Works on my machine”
An exact list of what your code or agent changed, and an undoGuessing from logs, on an account you can never reset
Tests that run on every commit, offline, with no vendor accountChecking by hand in a sandbox before each release

Features

Find the bad night in testing, not in a customer's books.

A realistic business, in both systems

A seeded trades business with customers, technicians, and months of jobs, quotes, invoices and payments, kept in Jobber and QuickBooks at once. Or drifted apart on purpose: customers spelled differently, customers in only one system, a customer the books made inactive who has paid for new work since.

Failures on demand

429s, 5xx errors, lost answers, and webhooks delivered twice or late, each in the vendor's own error format and marked with an X-Twin-Fault header. A lost answer does the write first and fails anyway, the way a gateway timeout hides a write that succeeded.

Twin time

Skip hours in a second. Rate limits refill, tokens expire, and scheduled events and their webhooks happen on the way, so retry waits and token expiry stop being tests that sleep.

Checkpoints, change lists and rewind

Name a moment, let your code or agent run, and get the exact list of what it changed in each system, one line per change. Then rewind, and the same requests meet the same faults.

Signed webhooks and real OAuth flows

Jobber's HMAC-signed webhooks, delivered at least once, and QuickBooks' signed CloudEvents, retried on Intuit's schedule. OAuth 2.0 at the vendors' own paths: codes that work once, access tokens that last 60 minutes, and Jobber's rotating refresh tokens.

An MCP server for coding agents

npm run mcp gives a coding agent like Claude Code tools to reset the twin, load scenarios, set faults, move the clock and list what changed. The agent still calls the vendor APIs over HTTP, the same way production code will.

A web dashboard

A control room for the twin, the event log as it grows, and Jobber and QuickBooks side by side with every customer and invoice marked as matching or drifted. It only reads the control plane, so watching spends no rate limit and draws no fault.

The same seed, the same results

Every run starts from a seed, so the same requests give the same results, byte for byte. A bug you hit once, you can hit again, in CI or on a teammate's laptop.

New to MCP? What an MCP server is, in plain English →

Who it's for

Built for developers, and the businesses they build for.

Integration developers

The bugs that cost you are the ones you can't make happen on purpose: a throttled API, a write whose answer never came back, a webhook that arrives twice, a token that expires halfway through a sync. fieldtwin makes them happen whenever you ask. The reference integration gets through more than a hundred retries and two hours of token expiry in a couple of seconds.

Teams building AI agents

An agent needs somewhere to make mistakes, many times over, and you need proof of what it actually did. Mark a checkpoint, let it work, and judge it on the changes it made, not on what it says it did. Load mismatched-books to see whether it notices the two systems disagree, or flaky-apis to see whether it gives up.

Agencies and integrators

If you sell to trades businesses, “we test against a full simulation of your Jobber and QuickBooks before anything touches your account” is a promise you can keep, and a reason a cautious owner says yes.

The businesses themselves

They never run it. They get syncs that don't create duplicate customers, leave invoices out of the books, or record a payment twice, and AI assistants that made their mistakes in a copy of the business instead of in theirs.

Testing on every commit

Run it in CI, offline, on every commit.

Your tests reach the twin the way your app does. Each test loads a fresh world, runs your code against it, and checks the change list: what your code really did, not what it logged. In GitHub Actions, check out fieldtwin beside your code and start it before your tests, and when a run fails, the twin's event log is kept with it.

The example test and workflow on GitHub ↗

Terminal demo · 2:45

Prefer the terminal?

Here it is in curl: the QuickBooks query language over months of seeded history, a checkpoint and the change list an agent leaves, throttling on demand, a busy scenario and a jump in time, and the reference sync getting through more than a hundred retries and two hours of token expiry in a couple of seconds.

fieldtwin from the terminal. 2:45, no sound.

Limits

What fieldtwin is not.

  • The real APIs. It's an imitation built from the vendors' public docs. FIDELITY.md ↗ says how closely it matches, behavior by behavior, with the docs page each one comes from.
  • Verified against a live sandbox, yet. Nothing has been recorded from a real one so far: every behavior is built from the public docs, and the ones that are only a best reading of them are marked “check”.
  • Your last check. Do a final check against the vendor's sandbox before you go live.
  • Every vendor, or every endpoint. Two vendors so far. Anything it doesn't model fails clearly, in the vendor's own error format, instead of returning made-up data.

Common questions

Straight answers.

Is fieldtwin free?

Yes. It's open source under the Apache 2.0 license. Clone it from GitHub, run npm ci and npm start, and it runs on your own machine with Node 22 or newer.

Does it replace the Jobber or QuickBooks sandbox?

No. It covers what the sandboxes can't: one business that looks real in both systems, failures on demand, time you can skip, and a clean start whenever you want one. It's modeled from the vendors' public docs, so do a final check against the vendor's sandbox before you go live. If you have a sandbox, fieldtwin's conformance suite records what the real API does and scores the twin against it.

Is fieldtwin affiliated with Jobber or Intuit?

No. fieldtwin is an independent project. It is not affiliated with, endorsed by, or supported by Jobber or Intuit, and it's built only from their public documentation.

Which parts of the Jobber and QuickBooks Online APIs does it cover?

QuickBooks Online: customers, items, invoices and payments, read by Id, through the query language and through change data capture; customers and invoices created and updated with SyncTokens; payments created and applied; requestid for safe retries; the 500-requests-a-minute limit; signed webhooks; and OAuth 2.0. Jobber: GraphQL for clients, jobs, visits, quotes, invoices and users, with Relay pagination and dated API versions; clientCreate; the query-cost throttle; signed webhooks; and OAuth 2.0 with PKCE and rotating refresh tokens. Anything it doesn't model fails clearly, in the vendor's own error format, instead of returning made-up data.

Can AI agents use it?

Yes. An agent calls the twin's APIs over HTTP, the same way production code will. Mark a checkpoint first, judge the agent on the exact list of changes it made rather than on what it says it did, then rewind and run it again. For coding agents, npm run mcp starts an MCP server whose tools reset the twin, load scenarios, set faults, move the clock and list what changed.

Do I need a Jobber or QuickBooks account, or internet access?

No vendor account. The twin serves a fake business generated from a seed, on localhost. Once it's installed it runs offline, so tests can run in CI with no vendor account, and several twins can run side by side, each on its own port.

Can I test webhooks locally?

Yes. Subscribe your app's URL, such as http://localhost:3000/webhooks/jobber, and the twin sends Jobber's HMAC-signed webhooks and QuickBooks' signed CloudEvents there, and tries again when your app doesn't answer in time. Fault rules can deliver them twice or late, so you can check that your handler doesn't record a payment twice.

Connecting AI to real books instead? Three ways to connect AI to QuickBooks →

Run a trade business?

Tested against fieldtwin before it touches your books.

Need an integration or an AI agent built for your trade business? I build them, and when they touch Jobber or QuickBooks, I test them against fieldtwin first: through throttling, lost answers, duplicate webhooks and expiring tokens, so the bad night happens in testing instead of in your accounts.

MCP server development →

AI agent development →

fieldtwin is an independent project. It is not affiliated with, endorsed by, or supported by Jobber or Intuit. Jobber and QuickBooks are trademarks of their respective owners.