Incremental sync
Most integrations copy part of a customer’s QuickBooks data into their own database and keep it current. QuickBooks Desktop has no change feed, but every record carries an updatedAt timestamp and QuickBooks keeps a list of recent deletions. Together they give you a reliable incremental sync.
The pattern
Section titled “The pattern”- First sync. List each object type you need without a date filter, or in date windows for large files (see below). Store each record by its QuickBooks
id, with itsrevisionNumberandupdatedAt. - Remember a watermark per end user and object type: the time you started the sync, as QuickBooks sees it.
- Each later sync. List with
updatedAfterset to the last watermark, minus a small overlap. Upsert byid. - Deletions. Call
GET /v1/quickbooks-desktop/deleted-transactionsandGET /v1/quickbooks-desktop/deleted-list-objectswithdeletedAfterset to the same watermark, and remove those records.
import { DesktopAccountingApi } from "@desktopaccountingapi/quickbooks-desktop";
const qb = new DesktopAccountingApi().forEndUser("eu_01j9...");const lastWatermark = "2026-10-04T00:00:00"; // from your database
for await (const invoice of qb.qbd.invoices.list({ updatedAfter: lastWatermark })) { // upsert by invoice.id console.log(invoice.id, invoice.revisionNumber);}
const deleted = await qb.qbd.deletedTransactions.list({ transactionTypes: ["invoice"], deletedAfter: lastWatermark,});for (const d of deleted.data) { // delete your copy of d.id console.log(d.id);}from desktopaccountingapi import DesktopAccountingApi
qb = DesktopAccountingApi().for_end_user("eu_01j9...")last_watermark = "2026-10-04T00:00:00" # from your database
for invoice in qb.qbd.invoices.list(updated_after=last_watermark): print(invoice.id, invoice.revision_number) # upsert by id
deleted = qb.qbd.deleted_transactions.list(transaction_types=["invoice"], deleted_after=last_watermark)for d in deleted.data: print(d.id) # delete your copyPicking the watermark
Section titled “Picking the watermark”QuickBooks timestamps use the clock and time zone of the customer’s computer, for example 2026-10-05T09:14:03-07:00. Filters work on the same clock:
updatedAfterandupdatedBeforeaccept a date (2026-10-04, meaning the start or end of that day), a local date-time without offset (2026-10-04T09:00:00, read in the computer’s time zone), or a date-time with offset (2026-10-04T16:00:00Z, converted to the computer’s time zone).- Use the largest
updatedAtyou received as the next watermark, or the time the sync started minus a few minutes. Overlap a little and deduplicate byid; re-reading a record is harmless, missing one is not. revisionNumberchanges on every edit. If the stored revision equals the new one, you can skip the record.
Deletions
Section titled “Deletions”| Endpoint | Covers | Filter |
|---|---|---|
GET /v1/quickbooks-desktop/deleted-transactions |
Deleted invoices, bills, checks and other transactions | transactionTypes (required), deletedAfter, deletedBefore |
GET /v1/quickbooks-desktop/deleted-list-objects |
Deleted customers, vendors, items, accounts and other list objects | objectTypes (required), deletedAfter, deletedBefore |
QuickBooks keeps deletions for 90 days. Run incremental syncs more often than that, and do a full comparison by ID if a customer has been offline longer.
List objects (customers, items, vendors) are usually deactivated rather than deleted. Include inactive records with status: "all" so a deactivation shows up as isActive: false.
Large company files
Section titled “Large company files”A single paged query must finish inside one QuickBooks session (see Pagination). For a first sync of a large file, split the range into windows:
- Choose a window, such as one month of
updatedAfter/updatedBefore, or one month oftransactionDateFrom/transactionDateTofor transactions. - Read each window completely before moving on.
- If a window fails with
CURSOR_EXPIRED, retry that window, or split it in half.
For several end users, run their syncs in parallel; each company file has its own queue.
Cross-type transactions
Section titled “Cross-type transactions”GET /v1/quickbooks-desktop/transactions returns a summary of every transaction type in one paged list, filtered by date, account, entity or type. Use it to find what changed across all types, then fetch full records from the type-specific endpoints.
When to sync
Section titled “When to sync”Customer-started syncs (“Sync with QuickBooks” buttons) give the best experience, because a person is there to fix a connection problem. Scheduled background syncs work too: run them with async requests, record failures per customer, and show the last sync result in your product. Avoid tight polling loops; one sync every few minutes is plenty for most products, and each request waits its turn in the company file’s single queue.