← Back to home

Integration · QuickBooks Online

QuickBooks Online sync.

Three paths to get DirtFleet repair logs into QBO: monthly CSV (works today), Zapier glue (works today), or the OAuth connector (ships with the first paying customer's contract). Field mappings are the same shape across all three.

Pick a path

Effort vs. transactional integrity.

The CSV path is highest-control / lowest-trust; the OAuth path is lowest-effort / highest-trust. Most shops start with Zapier (Pattern 2) because it's real-time and 30 minutes to set up — and graduate to Pattern 3 when QBO becomes load-bearing.

  1. Pattern 1 — CSV export, monthly drop (works today)

    Pull the month's repair logs via /api/v1/repairs?since=…, transform to QuickBooks' IIF or QBO-import CSV format, and drop it on a shared drive the bookkeeper imports manually.

    When to pick this

    Right when accounting wants the data but hasn't approved an automated integration yet. Low-trust, high-control — every entry is a human review before it lands in QBO.

    Show the setup
    # Monthly repair-log export → QBO-import CSV
    # Run on the 1st of each month for the prior month's logs.
    
    node ./export-repairs-to-qbo.mjs
    
    # export-repairs-to-qbo.mjs (Node 20+):
    const KEY = process.env.DIRTFLEET_API_KEY;
    const today = new Date();
    const lastMonth = new Date(today.getFullYear(), today.getMonth() - 1, 1);
    const since = lastMonth.toISOString();
    
    const url = new URL("https://dirtfleet.app/api/v1/repairs");
    url.searchParams.set("since", since);
    url.searchParams.set("limit", "200");
    
    console.log("Date,Vendor,Account,Amount,Memo");
    let cursor = "";
    while (true) {
      if (cursor) url.searchParams.set("cursor", cursor); else url.searchParams.delete("cursor");
      const r = await fetch(url, { headers: { Authorization: `Bearer ${KEY}` } });
      const body = await r.json();
      for (const log of body.repairs) {
        if (!log.cost) continue;
        console.log([
          log.createdAt.slice(0, 10),
          "DirtFleet",                       // or look up parts supplier from log.parts
          "Maintenance & Repair",             // your QBO account name
          log.cost.toFixed(2),
          `WO# ${log.workOrderId ?? "—"} asset ${log.assetId ?? "—"}`,
        ].join(","));
      }
      if (!body.nextCursor) break;
      cursor = body.nextCursor;
    }
  2. Pattern 2 — Zapier glue (also works today)

    Subscribe to workorder.completed via Zapier. Each completion → a QuickBooks Online "Create Expense" action. Map asset's project to a QBO class for P&L reporting.

    When to pick this

    When you want real-time sync and don't mind paying for Zapier's per-zap cost. No code, 30 minutes of setup.

    Show the setup
    Zapier setup:
      1. Trigger: Webhooks by Zapier → Catch Hook
         URL: copy, register as a DirtFleet subscription
           (Settings → Webhooks → New, events: workorder.completed)
      2. Filter: Only continue if data.cost > 0
      3. Action: QuickBooks Online → Create Expense
           Vendor: "DirtFleet" (or look up from data.parts)
           Account: Maintenance & Repair
           Amount: {{data.cost}}
           Memo: WO# {{data.number}} — {{data.title}}
           Class (optional): map {{data.projectId}} → your QBO class
           Date: {{data.completedAt}}
    
    That's it. Total setup time: 30 minutes. Zapier charges per task —
    common shops run 50-200 of these a month, which fits the cheaper
    Zapier plans.
  3. Pattern 3 — Direct OAuth via the lib/integrations/quickbooks helpers

    The OAuth client and request helpers are already scaffolded in the repo (lib/integrations/quickbooks). The live wiring activates with the first paying customer's QBO contract — at which point the in-app /settings/integrations/quickbooks-online flow handles the OAuth dance and sync becomes built-in.

    When to pick this

    Once you've outgrown Zapier's costs OR need transactional integrity (each repair is committed in QBO before DirtFleet considers it 'reconciled'). Status on /integrations/directory: scaffolded — the OAuth + token helpers are in the repo, the in-app /settings/integrations/quickbooks-online flow activates with your first paying QBO contract.

    Show the setup
    # Pre-shipped helpers visible in repo:
    #   lib/integrations/quickbooks.ts — OAuth client + token refresh
    #   /api/integrations/quickbooks/connect    (OAuth callback)
    #   /api/integrations/quickbooks/disconnect (revoke + cleanup)
    #
    # Status: SCAFFOLDED (not live). When you're ready, email
    # hello@dirtfleet.app — first-customer activation is the
    # expected unlock path.
    #
    # The OAuth flow goes through Intuit's standard developer.intuit.com
    # app registration. We do the QBO request signing + token refresh +
    # error mapping; the customer just clicks "Connect QuickBooks Online"
    # in /settings/integrations.

Field mapping reference

DirtFleet RepairLog → QBO Expense.

DirtFleet fieldQBO fieldNotes
RepairLog.costExpense.AmountDirect. Floor at $0.
RepairLog.createdAtExpense.TxnDateUse the YYYY-MM-DD substring; QBO doesn't store the time.
RepairLog.workOrderId + assetIdExpense.PrivateNoteConcatenate as "WO #1234 / asset Excavator 47" for greppable audit.
RepairLog.projectIdExpense.Class (or Customer)Most shops map DirtFleet projects → QBO classes for P&L by project. Some map → QBO customers for invoiceable jobs.
RepairLog.parts (free-form text)(usually skip)Bookkeepers prefer the canonical PrivateNote; parts text gets fragile if anyone edits it in DirtFleet later.

What we don't do today

Honest scope.

  • Bidirectional sync. DirtFleet → QBO works (push); QBO → DirtFleet is not on the roadmap. Most shops don't want it — the data flow is one-directional.
  • Invoice creation. Pattern 2 + Pattern 3 create expenses, not invoices. If you charge end-customers for repair work, build that flow in QBO directly using the project breakdown DirtFleet provides.
  • Direct QBO Desktop. Use the Pattern 1 CSV with QBD's IIF import; the OAuth path is online-only.

Want to try Pattern 3 (OAuth) early? Email hello@dirtfleet.app — first-customer activation is the unlock path.

See also: /integrations/zapier for the Pattern 2 setup walk-through.