User guide
Accounting Integrations
Looking for what it does rather than how to use it? Read the Accounting Integrations overview .
Audience: MSP administrators who keep the books in QuickBooks Online. Scope: the QuickBooks Online integration — connection, mapping, sync and troubleshooting.
What it is
Solidlio connects to QuickBooks Online over OAuth 2.0 and keeps invoices, payments, credit notes, customers, items, vendors, bills and purchase orders in step with your books. Sync is queued and retried in the background, and every run is recorded.
QuickBooks Online is the only accounting system that ships. Xero appears in the catalogue as Coming Soon and cannot be connected. Sage is not implemented.
Concepts
| Concept | What it is |
|---|---|
| Realm | Your QuickBooks company. One connection per organization — the MSP’s OWN organization owns it; documents raised to managed clients sync through it. |
QuickBooksEntityMapping | One row per linked record, pairing a Solidlio id with a QuickBooks id, scoped to your tenant. |
| Account mapping | A Solidlio accounting slot (income, COGS, sales tax) → a QuickBooks chart-of-accounts entry. |
| Tax code mapping | The TAX_CODE_SALES slot → a QuickBooks tax code. Required before any taxed invoice syncs. |
| Sync log | One row per run: entity, direction, counts, status. |
Direction of travel
| Object | Solidlio → QuickBooks | QuickBooks → Solidlio |
|---|---|---|
| Customer | ● | ● update mapped record |
| Invoice | ● | ● update mapped record |
| Invoice line | ● | ● |
| Payment | ● | ● update, or create when linked to a mapped invoice |
| Credit note | ● | ● update or create |
| Product / item | ● | ● |
| Vendor | ● | ● update mapped record |
| Vendor bill | ● | ● update mapped record; bulk import creates (approved, with lines) |
| Purchase order | ● | ● update mapped record; bulk import creates (issued, with lines) |
| Invoice VOID | ● | — (a QuickBooks Delete/Void unlinks the local record) |
| Payment refund | ● | — (the QuickBooks receipt is restated to the net amount) |
| Credit applied | ● | — (a $0 QuickBooks payment links memo and invoice; reversal voids) |
Bills and purchase orders arriving from a QuickBooks webhook that Solidlio has never seen are rejected with a clear message pointing at the bulk importer. Creating them from a single id would require vendor matching and expense categorization that one id cannot supply.
Voiding an invoice in Solidlio voids its QuickBooks mirror (QuickBooks keeps the document on file at $0). Only issued documents are pushed: DRAFT and VOID invoices and credit notes are never sent.
Refunds. The QuickBooks receipt is always the NET cash retained. A payment pushed before a refund is restated to amount − refunded (a sparse update of the same Payment, so the invoice balance in QuickBooks reopens exactly as Invoice.paidAmount does); a fully refunded payment is voided. No separate refund receipt is posted — card processors net refunds out of the payout, so one net receipt is what the bank statement shows.
Credit applied to an invoice. Applying a credit note creates the $0 QuickBooks Payment whose line links the credit memo and the invoice — the only way the API applies a credit. Reversing the application voids that payment. Both require the memo and the invoice to be in QuickBooks already.
Roles and permissions
Every QuickBooks route requires organization administrator or above. The webhook receiver is the one exception — it is public and authenticated by signature instead.
| Role | QuickBooks admin |
|---|---|
| platform administrator | ● |
| MSP administrator | ● |
| MSP technician | ● |
| organization administrator | ● |
| power user | — |
| CUSTOMER | — |
In practice this is an MSP-portal feature: the screens live at /msp/accounting/quickbooks. There is no org-portal or customer-portal accounting surface.
Walkthrough — connecting and first sync
- Connect —
Accounting → QuickBooks. Choose Connect and complete Intuit’s OAuth consent. Tokens are encrypted at rest and refreshed automatically. - Map your chart of accounts — open the Accounts tab and map each slot (income, COGS, expense categories) to a QuickBooks account.
- Map a sales tax code — in the same tab, map
TAX_CODE_SALESto the QuickBooks tax code you charge on sales. Do this before syncing any taxed invoice — see the warning below. - Link existing records — the Mappings tab pairs Solidlio customers, items and vendors with their QuickBooks counterparts. Use the suggestions list to match by name, then confirm. Mappings can be renamed or unlinked.
- Push an invoice — the Invoice Sync tab lists invoices and pushes a selected one to QuickBooks on demand.
- Let it run — invoice-sent, payment (manual AND card-through-Stripe), credit-note-issued, bill-approved, PO-approved and invoice-void events queue automatically thereafter, and a 4-hourly job re-syncs anything the event path missed (invoices, payments, credit notes, vendors, bills, POs). Watch progress in Sync Logs.
Which connection a document uses
The QuickBooks connection is owned by the MSP’s own organization. An invoice an MSP raises to a managed client carries the CLIENT’s organization, so the sync resolves the connection from the document’s seller account (Invoice.accountId), then the organization’s own account, then every MSP servicing it. A tenant with no QuickBooks in reach is acknowledged with queued: false — nothing is enqueued and nothing fails.
Linking through the mapper
Several jurisdictions may share one QuickBooks tax code (NB/NS/NL/PE → “HST 15%”), and an expense category may share an account with the chart-of-accounts slot it belongs to.
Reconnecting
If Intuit revokes or expires the grant, Status reports Reconnect Required and the page offers a Reconnect button. Reconnecting re-runs OAuth onto the SAME integration row (mappings and history are kept). Disconnecting revokes the token at Intuit.
⚠️ Tax mapping is required
If an invoice carries tax and no TAX_CODE_SALES mapping exists, the sync fails with an actionable error rather than pushing an untaxed invoice. This is deliberate: previously tax was never sent at all, so a $100 + $13 HST invoice arrived in QuickBooks as $100 and accounts receivable could not reconcile.
If you are upgrading an existing installation, map a tax code before your next taxed sync.
Configuration reference
| Setting | What it does | If unset |
|---|---|---|
| OAuth connection | Links one QuickBooks company | Nothing syncs |
TAX_CODE_SALES mapping | The QuickBooks tax code used on sales | Taxed invoices and credit memos fail to sync |
| Income / COGS slots | Default accounts for invoice and bill lines | Bill lines fail with an actionable error |
| Expense category mappings | Per-category QuickBooks account for vendor bills | Falls back to the COGS slot, then errors |
| Entity mappings | Links Solidlio records to QuickBooks records | The first sync creates the QuickBooks record |
Troubleshooting
| What you see | Cause |
|---|---|
| Sync fails naming a missing tax code | No TAX_CODE_SALES mapping. Map one in the Accounts tab. |
| Sync fails naming a missing account | A vendor bill line has no expense-category or COGS mapping. |
| Status shows “reconnect required” | The refresh token expired or was revoked at Intuit. Reconnect. Previously this showed “Connected” forever while every sync failed. |
| Invoice refuses to push a second time | Expected. An invoice already carrying a QuickBooks id will not be pushed again — that would duplicate it in your books. |
| Purchase order push fails naming a line | A line has no resolvable QuickBooks item. Map the product first. |
| A queued job reports success but nothing changed | Check Sync Logs — a terminal configuration error is discarded rather than retried, and is recorded there. |
| Bill or PO from a QuickBooks webhook is rejected | Expected. Inbound bills and POs refresh existing links only; use the bulk importer to create. |
| A 404 when queueing an entity | The entity does not belong to your organization. |
| Sync All says “Nothing pending” | Every mapped, issued document is already in QuickBooks. Unmapped customers/vendors are the usual reason a document is not pending. |
| A mapping shows “stale” after reconnecting | The chart-of-accounts slot points at an account id from a previous QuickBooks company. Clear it and re-map (or re-run provisioning). |
| A tax-code row reads “stale” | Its QuickBooks id is not in this company (mistyped, or a different realm). Clear and re-map. |
| Credit application refuses: “not in QuickBooks” | Sync the credit note and the invoice first; the $0 linking payment needs both ids. |
Limits and known behaviour
- QuickBooks Online only. Xero and Sage are not implemented and cannot be connected.
- Inbound bills and purchase orders from a webhook refresh mapped records only; the bulk importers create new rows (approved, with line items).
- Refunds restate the QuickBooks receipt to the net amount rather than posting a separate refund receipt; a fully refunded payment is voided (or never pushed).
- Credit applications need both the memo and the invoice in QuickBooks; the 4-hourly job (and Sync All) picks up any application still unlinked.
- Taxed invoices require a tax-code mapping and fail loudly without one.
- Client provisioning from a QuickBooks customer claims the QuickBooks id before provisioning, so a retry cannot create a duplicate tenant — but the operation is not transactional, so a failure mid-provision can leave a tenant to clean up manually.
- Accounting is an MSP-portal feature; there is no org or customer surface.
- Payments push net of refunds. A fully refunded payment is refused rather than posted as zero.