Skip to content
English
  • There are no suggestions because the search field is empty.

QuickBooks Accounting Sync Internals

How the Tai TMS pushes records and transactions to QuickBooks Online: de-duplication, naming and number rules, the batch engine, payees, and limits.

This internal article documents how the Tai TMS pushes accounting data to QuickBooks Online — how master records and transactions are de-duplicated, the naming and document-number rules that QuickBooks imposes, how the batch engine (the engine the Accounting Sync screen always uses) plans and pushes its work, how check-payee names and bill payments are handled, its operational limits, and what parts of the sync framework are referenced but not present in this build.

Overview

This is the staff-only reference for the QuickBooks Online sync. It covers what gets pushed (receivables, payables, and the master records they reference), how the sync avoids creating duplicates in QuickBooks, the specific naming and document-number constraints QuickBooks Online enforces, how the batch engine sets a separate check-payee name without disturbing the de-dup key, how bill payments are linked to bills and vendor credits, and the batch engine's operational limits. Use it when troubleshooting "why did this fail to sync," "why did QuickBooks say a name already exists," "why is a vendor named with a suffix," "why does the check pay to a different name than the vendor," or "why did a long invoice number get rejected."

How it works

The sync sends TMS accounting data into QuickBooks Online in three groups: receivables (invoices, invoice payments, credit memos), payables (bills, bill payments, checks), and the master data those transactions reference (customers, carriers and vendors, and sales reps). Master records are synced first so transactions can reference them. The sync connects to QuickBooks Online with a stored authorization for the company, chooses the sandbox or production QuickBooks environment from configuration, and reports a per-record outcome (such as complete, already-synced, updated, or failed) back onto the TMS records.

The batch engine is the sync. The Accounting Sync screen (in both the current and the older front end) always runs the batch engine, which plans the work, pre-checks it, and pushes chunked QuickBooks batch operations in parallel. The feature flag that once chose between the batch engine and the older per-record engine has been removed, so there is no setting to turn the batch engine on or off. The older per-record engine (one QuickBooks write per object) is still compiled, but it is reachable only through a legacy run-sync entry point that no screen in the product calls. It is still maintained alongside the batch engine, so a change to sync behavior often has to be made in both places unless it is deliberately batch-only.

Run order (batch engine). A run works in phases: first the base records (customers, carriers, sales reps, organization vendors — planned in parallel and then created in chunks), then the accounting records (invoices, bills, checks), then payments (invoice payments and bill payments). Once a user aborts the run, the remaining phases are skipped and the run is reported as stopped. Customer, carrier, rep, and vendor QuickBooks ids are carried onto the transactions between the first and second phases.

Which records are picked up. The engine reads only records for the signed-in user's accounting organization (invoices and invoice payments by billing organization, bills and bill payments by payer organization). It takes records whose sync status is None; records at Failed are included when the request names explicit record ids, which is what the screen sends (the selected rows, or every row that is not Complete when none are selected). Each record type is capped at 5,000 rows per run, in id order, so a backlog larger than that needs another run.

Business rules & limits

What ships in this build

  • Only the QuickBooks Online strategy is present. This checkout ships the QuickBooks Online implementation. A Dynamics GP strategy and a mock (test) strategy are referenced by name in the sync orchestrator but are not compiled in this build, so the branches that check for those names do nothing here. Reviving Dynamics GP would require adding that implementation and repointing the accounting-sync binding.

Master-record de-duplication (name / display name)

  • Before creating a customer, carrier, vendor, or sales rep, the sync looks the record up by name first. If a matching record already exists in QuickBooks, it is treated as already-synced and the existing QuickBooks id is reused — no duplicate is created.
  • QuickBooks Online requires the display name to be unique across customers, vendors, and employees. Because of that, the sync enforces a cross-type guard: a customer cannot be created if a vendor of the same name exists, and a vendor, carrier, or rep cannot be created if a customer of that name exists. The attempt fails with a "rename and try again" message.
  • Vendor name suffix: organization vendors are given a trailing "- V" on their display name, appended directly to the name (so an organization vendor will not collide with a customer of the same name). Carriers and sales reps do not get the suffix. As a result, a carrier or rep that shares a name with a customer will still collide, while an organization vendor of the same name will not.
  • The batch engine matches master records by display name: an active match is treated as already-synced, while an inactive match fails with a message to reactivate the record in QuickBooks. Name-collision errors returned by QuickBooks are recognized by their message text and re-resolved.
  • Deleted records are handled differently for customers and vendors. QuickBooks renames a deleted record to " (deleted)". For customers, the batch engine still looks for that renamed record and fails with a message to reactivate it, so no duplicate customer is created. For carriers, sales reps, and organization vendors, the engine does not look for deleted vendors: when the only QuickBooks vendor with that name is a deleted one, the sync creates a new vendor under the original name and the deleted one stays deleted.
  • Existing organization vendors are updated: when an active organization vendor already exists but its QuickBooks billing address differs from the TMS address, the address is updated; if that update fails the vendor's outcome is Failed rather than already-synced.
  • Payment terms default to 30 days for sales reps, for organization vendors with no billing profile, and for carriers without net terms; customers take the payment terms on their billing profile.

Check-payee name (print-on-check) and vendor address — batch engine only, flag-gated

  • The batch engine can set a carrier vendor's QuickBooks print-on-check name (the payee QuickBooks prints on the check) and its billing address separately from the vendor's display name. This is gated by the LSP carriers factoring-company management feature flag (flag value 7108).
  • Where the remit-to details come from (flag on). The carrier's Remit To Source setting is applied when the LSP carrier is saved, not at sync time: saving copies the chosen source into the carrier's stored remit-to company name and address. Carrier Name and Carrier DBA use the carrier's name (or DBA, falling back to the carrier name when the DBA is blank) and its mailing address, or its main address when the mailing address is empty. Factoring Company uses the factoring company's name and invoice address. User Entered keeps what the user typed. Updating a factoring company rewrites the stored remit-to details of every carrier that uses it as its Remit To Source. The sync reads only these stored values.
  • When the flag is on, the name is taken, for a bill, from the remit-to name stored on the bill when it was registered, if that is not blank; otherwise (and always for bill payments and checks, which carry no stored name) from the remit-to company name stored on the carrier's LSP carrier record for the paying organization. It is written to the QuickBooks vendor's print-on-check name. There is no fallback to the carrier name at sync time: when both are blank (for example a User Entered source with no company name), no print-on-check name is set. This lets a bill be paid to a factoring company or an alternate remit-to name while the vendor is still filed under the carrier's own name.
  • When the flag is on, the address is the bill's stored remit-to address if it has a street address and ZIP code; otherwise the remit-to address stored on the carrier's LSP carrier record, used as it is even when empty. A carrier whose LSP carrier record has no remit-to address therefore sends a blank address when its vendor is created, not the carrier's own address. The carrier's own address is used only when the paying organization has no LSP carrier record for that carrier. Payments carry no stored address, so they use the stored remit-to address or, with no LSP carrier record, the carrier's address. When the flag is off, only the bill's stored address or the carrier's address applies.
  • Existing carrier vendors are updated too (flag on): an active QuickBooks vendor matched by carrier name is updated when the carrier's address has a street address and ZIP code that differ from the vendor's billing address, or a non-blank print-on-check name that differs from the vendor's. A blank address or name never overwrites what is already in QuickBooks. If that update fails, the carrier's outcome is Failed with a message that the remit-to name and billing address update did not complete and was not applied.
  • The display name — which is the de-duplication key — is unchanged. It stays the carrier name, so this feature does not affect how the sync matches or de-duplicates vendors; only the decoupled check-payee name and billing address are affected. When the flag is off, no print-on-check name is set and no carrier-vendor update is attempted.
  • This applies to carrier vendors only — organization vendors and sales reps are not given a print-on-check name — and it exists only in the batch engine; the older per-record engine does not set it. Because the stored name on a bill is a snapshot taken at registration, changing a carrier's Remit To Source later does not change the check payee for bills that already exist. A new Remit To Source reaches bill payments and new bills once the carrier has been saved with it.

Transaction de-duplication (document number)

  • Transactions are keyed by document number: an invoice syncs with the TMS invoice number as its QuickBooks document number, and a bill syncs with the TMS bill number. The document number must be unique in QuickBooks Online.
  • The batch engine enforces a 21-character maximum on the document number — an invoice or bill number longer than 21 characters fails in pre-check. The older per-record engine does not pre-check the length; it relies on QuickBooks itself rejecting an over-long or duplicate document number.
  • The older per-record engine also does no pre-check for an existing transaction by document number. Transaction idempotency there relies on QuickBooks rejecting a duplicate document number and on the orchestrator skipping objects the TMS already marks as synced.
  • In the batch engine, invoice payments are linked to existing invoices or credit memos by document number, and a receivable whose total is zero or less is sent as a credit memo rather than an invoice (it is built from the first line's sale account; with no such account it fails). A bill whose total is negative is sent as a vendor credit. Bills are grouped by credit-or-not, number, and vendor, so the same number and vendor become one QuickBooks transaction.
  • Line shape and order: one QuickBooks line per distinct account code with amounts summed. With the charge-line display order flag on, lines are ordered Linehaul first, then Fuel, then everything else.

Bill payments (batch engine)

  • A bill payment needs a bank or credit-card general-ledger account name on the accounting organization (otherwise it fails), an active vendor, and an account of the expected type that exists in QuickBooks.
  • Payment lines are linked to QuickBooks bills by document number, falling back to the QuickBooks id cached on the TMS bill. A bill that is voided in QuickBooks, or that belongs to a different vendor, is skipped with a warning (the payment is still applied, just not linked to that bill).
  • If no line could be linked and at least one named bill was not found in QuickBooks, the payment fails with a message to sync the bills first and then re-sync the payment. If some lines linked, the payment goes through with warnings for the rest.
  • A payment with no bill lines at all, or whose lines were all skipped as voided or for another vendor, is submitted to QuickBooks as a Purchase with no bill link. That requires a cost account named exactly "Freight COS"; without it the payment fails. A card-processing fee is not applied to a Purchase.
  • Vendor credits (flag-gated): with the QuickBooks bill payment vendor-credit linking feature flag (2308) on, a payment line group whose applied amount is negative is resolved against the matching QuickBooks vendor credit (voided or other-vendor credits are skipped with a warning; a missing credit counts as an unsynced bill). With the flag off, every group is looked up as a bill only, so a negative group has no vendor credit to find.
  • An ACH payment is posted as a Check-type payment, because QuickBooks bill payments support only Check and Credit Card. An ACH payment with no check reference uses the TMS payment id as its document number, and a check reference longer than 20 characters is truncated to 20.

Batch engine limits

  • The batch engine sends QuickBooks operations in batches capped at 30 operations per batch, and processes up to about 10 chunks in parallel.
  • Individual chunk failures are recorded and the run continues rather than aborting — the engine does not throw out on a single failed chunk. A user-initiated abort is polled about every two and a half seconds so a long run can be stopped.
  • Each record type is limited to 5,000 rows per run.

Other operational notes

  • Sandbox vs. production is chosen from configuration; a mis-set environment sends data to the wrong QuickBooks company.
  • The stored QuickBooks authorization is cached for a long window (around 100 days), but the token itself can expire sooner, which surfaces as a "session expired / reconnect" message and the screen disconnects from QuickBooks.
  • A Precheck (test run) reports success without writing anything to QuickBooks. In the batch engine QuickBooks lookups still run, but every create or update is answered with a synthetic success and placeholder ids, and nothing is written back to the TMS records, so a "complete" outcome under a Precheck is not proof that data reached QuickBooks.
  • Referenced items must already exist in QuickBooks: products/items and sale accounts are not auto-created, and a missing one causes a failure rather than a silent create.
  • On each logged run the QuickBooks request/response log directory is cleared before logging begins, so only the latest run's logs are retained (a batch Precheck keeps the existing files).

Frequently asked questions

Which accounting systems can the Tai TMS sync to in this build?

In this build the Tai TMS syncs only to QuickBooks Online. A Dynamics GP strategy and a mock/test strategy are referenced by name in the sync orchestrator but are not compiled into this build, so those code paths are inert here. Only the QuickBooks Online implementation is active.

How does the sync avoid creating duplicate customers or vendors in QuickBooks?

In the Tai TMS the sync looks each master record up by name before creating it. If a matching record already exists in QuickBooks, it is treated as already-synced and the existing QuickBooks id is reused instead of creating a duplicate. An inactive match fails with a message to reactivate the record in QuickBooks. A deleted customer (which QuickBooks renames to " (deleted)") also fails with a reactivate message, but a carrier, sales rep, or organization vendor whose only QuickBooks match is a deleted vendor is created as a new vendor.

Why did QuickBooks reject a record saying the name already exists?

In the Tai TMS this happens because QuickBooks Online requires the display name to be unique across customers, vendors, and employees. The sync will not create a customer when a vendor of the same name exists, or a vendor/carrier/rep when a customer of that name exists; it fails with a "rename and try again" message. The fix is to disambiguate the names in the TMS or QuickBooks.

Why do some vendors show up in QuickBooks with a "- V" on the name?

In the Tai TMS, organization vendors have a trailing "- V" appended to their display name so they do not collide with a customer of the same name in QuickBooks. Carriers and sales reps do not get this suffix, so a carrier or rep that shares a name with a customer can still collide, whereas an organization vendor of the same name will not.

Why does a carrier's check in QuickBooks pay to a different name than the vendor's name?

In the Tai TMS, the batch sync can set a carrier vendor's QuickBooks print-on-check name separately from its display name, gated by the LSP carriers factoring-company management feature flag. When the flag is on, the check-payee name is the remit-to name stored on the bill, or else the remit-to company name stored on the carrier, which saving the carrier fills in from its Remit To Source (carrier name, carrier DBA, factoring-company name, or a user-entered company name), so the check can pay a factoring company or an alternate remit-to while the vendor is still filed under the carrier's own name. The display name — the de-duplication key — is unchanged, so this does not create a duplicate vendor; only the check payee differs. This applies to carrier vendors only.

Why did a long invoice or bill number fail to sync?

In the Tai TMS, the batch engine enforces a 21-character maximum on the QuickBooks document number, so an invoice or bill number longer than that fails in pre-check. The older per-record engine does not check the length itself and instead relies on QuickBooks rejecting the number. Shorten the number so it fits within 21 characters.

How large are the batches the batch engine sends, and what happens if one fails?

In the Tai TMS the batch engine sends up to 30 QuickBooks operations per batch and runs up to about 10 chunks in parallel. If a chunk fails, the engine records the error and keeps going rather than aborting the whole run, so a single failure does not stop the rest of the sync. Each record type is capped at 5,000 rows per run, so a larger backlog takes more than one run.

Is the batch engine optional or behind a feature flag?

No. In the Tai TMS the Accounting Sync screen always runs the batch engine; the feature flag that used to choose between it and the older per-record engine has been removed. The older engine is only reachable through a legacy entry point that no screen calls.

Why did a bill payment sync as a "Purchase" with a warning instead of paying the bill?

In the Tai TMS, when none of a bill payment's lines can be linked to a bill in QuickBooks (for example the bills are voided, belong to another vendor, or have no numbers to look up), the payment is submitted as a Purchase with no bill link and a card-processing fee is not applied. It needs a cost account named exactly "Freight COS" in QuickBooks. If the named bills simply were not synced yet, the payment fails instead, with a message to sync the bills first.

Does a successful Precheck mean the data reached QuickBooks?

No. In the Tai TMS a Precheck (test run) reports successful outcomes without actually writing to QuickBooks. A "complete" result under a Precheck only means the sync would have proceeded — it is not evidence that any record was created in QuickBooks. Use a real (non-Precheck) run to confirm data was written.