Power features · Integrations
QuickBooks Online
End-to-end reference for the QuickBooks Online integration — what syncs, what doesn't, every setting and what it changes, and the most common ways agencies actually run it. Setup lives in Settings → Integrations.
What you get
CoPortal's QuickBooks integration is the deepest of all our accounting connectors. It covers the full lifecycle of a billing record:
- •Outbound — push CoPortal invoices, quotes, and customers into QuickBooks (one-click or auto)
- •Inbound — bulk-import existing QB customers, historical invoices (with their payment state), and estimates into CoPortal
- •Linked — once a record is synced once, every future change updates the same QB record (no duplicates)
- •Configurable per-direction — auto-sync, sync-as-draft, and display-only payments are independent toggles you can flip in any combination
Available on Studio and above. There's no per-record API charge — sync as many invoices as you like.
The contract — who owns what
The integration only works cleanly if both sides have a clear job. Here's the split:
CoPortal owns
- • Creating invoices & quotes (with project, client, line items)
- • Editing those records — line items, due dates, notes, recurring
- • Marking paid for internal use (cashflow, dashboards, commissions, client portal)
- • The client-facing layer: portal, reminders, client comms, file requests
QuickBooks owns
- • Bank matching and payment reconciliation
- • Marking invoices paid (this is the canonical action)
- • The legal/tax record of cash receipts
- • Anything an accountant traditionally does — reports, journals, period close
In one line: CoPortal originates the invoice and runs the client side; QuickBooks owns the money side. Marking an invoice paid in CoPortal updates CoPortal only — it never pushes to QB. Marking it paid in QB will, after the next CoPortal release, pull back automatically into CoPortal.
Lifecycle of an invoice — visual flow
End-to-end, here's how a single invoice moves between the two systems:
- 1
CoPortal
You create the invoice (client, line items, VAT, due date).
→pushes toQuickBooks
Lands as Awaiting Payment with your DocNumber preserved.
- 2
CoPortal
You edit the invoice (change line items, due date, add notes…).
→updates inQuickBooks
Same QB invoice is updated in place — never duplicated.
- 3
CoPortal
You create a quote (single-tier or multi-option).
→pushes toQuickBooks
Lands as an Estimate (Pending). Multi-option quotes only sync the accepted tier after acceptance.
- 4
CoPortal
You mark the invoice paid in CoPortal (e.g. client paid you and you want CoPortal's dashboard / cashflow / portal to reflect it).
⊘no pushQuickBooks
Nothing changes in QB. CoPortal updates internally only — safe to do anytime.
- 5
QuickBooks
Your accountant marks the invoice paid in QB (bank match, payment receipt, journal entry — however they record cash).
←pulls intoCoPortal
Invoice flips to Paid in CoPortal automatically — dashboard, cashflow, commissions, client portal all refresh on the next hourly pull.
Connecting QuickBooks
Go to Settings → Integrations and click Connect QuickBooks. You'll be redirected to Intuit, sign in to QuickBooks Online, pick the company you want CoPortal to connect to, and authorise. CoPortal handles the OAuth dance and stores your access + refresh tokens encrypted at rest (AES-256-GCM). Tokens refresh automatically on a rolling 100-day window — no manual reconnects under normal use.
After connecting, the QuickBooks card in Settings shows the company name and how many invoices/clients are currently linked. The connection is workspace-wide — every team member with access to invoices and clients can sync.
QB_SANDBOX appropriately. The OAuth flow auto-targets the correct host.Outbound — what CoPortal pushes to QuickBooks
Invoices
Every invoice gets a Sync to QuickBooks button. On first sync CoPortal:
- •Finds or creates the QB customer (by stored
qb_customer_idfirst, then by email, otherwise creates new) - •Ensures a single shared service item exists (CoPortal uses one “Professional Services” item — your QB chart of accounts stays clean)
- •Builds the QB invoice with your invoice number as DocNumber, line items, VAT/GST rate, due date, and notes
- •Stores the QB invoice ID + sync timestamp on the CoPortal record so the next sync updates this same QB invoice
Re-syncing reads the QB invoice's SyncToken first, then PATCHes — so subsequent edits update the existing QB record rather than creating a duplicate. Use this freely.
Quotes (QuickBooks Estimates)
Quotes push as QuickBooks Estimates with status mapping:
- •Draft → Draft
- •Sent → Pending
- •Accepted → Accepted
- •Declined / Expired → Closed
Multi-option (tiered) quotes only sync the accepted tier — until acceptance, the headline option goes as a single estimate so QB doesn't see four parallel estimates for the same job.
Clients
Clients are synced lazily — the first time you push an invoice or quote for a client without a qb_customer_id, CoPortal creates the QB customer and stores the link. You can also bulk-create QB customers via the Preview customers import (see below) and CoPortal will reuse those links going forward.
Inbound — what you can import from QuickBooks
Customers
Click Preview customers on the QB card to see every QB customer tagged:
- •New — not in CoPortal yet, will be created
- •Duplicate email — already exists in your CoPortal clients (skipped unless you tick it)
- •Linked — already linked to a CoPortal client
A read-only field-mapping table shows how QB fields land in CoPortal (DisplayName → name, primary email → email, primary phone → phone, billing address → address). Tick the rows you want, confirm, and the chosen customers land as CoPortal clients with their QB link recorded.
Invoices (with payment history)
Click Preview invoices. Every QB invoice shows up tagged with both:
- •Paid status — paid, partial, unpaid, draft, or voided (derived from QB's TotalAmt minus Balance)
- •Import action — will import, already imported, no CoPortal client (need to import the client first), or number conflict (the DocNumber clashes with one of your CoPortal invoices)
On import, CoPortal:
- •Preserves the QB DocNumber as the CoPortal invoice number — falls back to
QB-<DocNumber>if it would clash with one you already issued - •Mirrors partial payments — any QB invoice with an outstanding balance lands in CoPortal with the already-paid amount written as an
invoice_paymentsrow, so the outstanding balance is correct from day one - •Deduplicates by QB invoice ID — re-running an import won't duplicate
- •Lets you optionally re-email unpaid invoices to clients via CoPortal at import time (off by default — clients usually got the QB email already)
Estimates
QB estimates can be imported as CoPortal proposals via the same preview flow. Status carries over (Pending → Sent, Accepted → Accepted, Closed → Declined).
Settings — every toggle and what it changes
All three live on the QuickBooks card in Settings → Integrations. They're independent — flip any combination.
Auto-sync
default: offSync as draft
default: offPrivateNote marking them as drafts — you finalise/send from inside QuickBooks. When off, invoices are pushed as approved/sent and treated as live in QB. Useful when an accountant wants to review before billing the client from the QB side.Display-only payments
default: offCommon ways teams run it
Three patterns cover almost every agency. Pick the one that matches your accountant's workflow.
Flow A — Display-only mirror (most common)
When to use it · Your accountant runs the books in QuickBooks; CoPortal is your client-facing layer
Toggles: Auto-sync ON · Sync as draft OFF · Display-only payments ON
How it flows:
- •You issue invoices in CoPortal (with quotes, project context, the works)
- •Each invoice auto-pushes to QB on send — your accountant sees it land instantly
- •Client pays → you mark paid in CoPortal so cash flow / dashboards / commissions update. Nothing changes in QB.
- •Accountant matches the bank transaction in QuickBooks like they always do — they own payment state there.
- •Periodically use Preview invoices import if you want to mirror the accountant's payments back into CoPortal for the few records you didn't mark paid yet.
This is the cleanest split — no fights over “wait, who marked this paid?” CoPortal is the originator of new records; QB is the system of record for cash receipts.
Flow B — CoPortal as source of truth
When to use it · You handle billing yourself; QuickBooks is just a back-office mirror
Toggles: Auto-sync ON · Sync as draft OFF · Display-only payments OFF
How it flows:
- •You issue invoices in CoPortal; auto-sync pushes them to QB live
- •Client pays via Paystack / EFT / card → you record the payment in CoPortal
- •The next time that invoice gets edited and saved, the auto-sync push includes the current status — QB stays in step
- •Imports run once at onboarding to bring historical billing into CoPortal, then it's mostly outbound forever
Best if you don't use QB's bank feed / matching workflow at all and just want a QB mirror for tax filing.
Flow C — Draft review
When to use it · You draft, the accountant reviews + sends from QB
Toggles: Auto-sync ON · Sync as draft ON · Display-only payments ON
How it flows:
- •You draft an invoice in CoPortal with all the project details
- •It pushes to QB as a draft with a [Draft — review in QuickBooks before sending] note
- •Accountant reviews and sends from QB. Payment state is owned in QB.
- •You see the QB number / paid status by running an invoice preview import periodically.
Common in tightly-controlled finance setups (regulated industries, companies with strict approvals).
What happens when I mark an invoice paid in CoPortal?
With Display-only payments OFF (default): nothing reaches QuickBooks. CoPortal's QB sync only pushes invoice creation/update — no payment objects, no Status flips. The next time that invoice is edited and re-saved (auto-sync) or you click Sync to QuickBooks, the push still only includes invoice fields, not payments.
With Display-only payments ON: same behaviour today, but the toggle locks the contract going forward. If a future CoPortal release adds payment-object pushing for QB, this flag will stop it firing for your workspace.
Either way: paying in CoPortal updates CoPortal (cash flow, dashboard tiles, commissions, automations like “invoice paid” triggers, the client's portal). Your accountant's QB stays untouched until they record the payment there themselves.
What does NOT sync
- •Payment objects from CoPortal → QB. Period. (Mark in CoPortal, your accountant matches in QB.)
- •Time entries, expenses, project tasks — these live in CoPortal only. QB doesn't know about them.
- •QB's chart of accounts customisation — every CoPortal line item maps to one shared service item to keep QB tidy.
- •QB items / products — CoPortal doesn't maintain a parallel item list. Line item descriptions and unit prices come from CoPortal directly.
- •QB classes / locations / departments — not currently supported.
- •Automated retries — if a sync fails because the QB token was revoked or QB is down, the push is dropped (auto-sync is fire-and-forget). You'll need to re-trigger by editing/saving or clicking the manual sync button.
Disconnecting
From the QuickBooks card click Disconnect. CoPortal deletes the encrypted token row and stops every push. Existing CoPortal records keep their qb_invoice_id / qb_customer_idas harmless metadata — if you reconnect later (same QB company), every linked record finds its match without re-importing.
For a complete revoke, also remove CoPortal from QuickBooks → Settings → Apps. CoPortal does not call Intuit's revoke endpoint on disconnect by default.
Troubleshooting
“QuickBooks not connected” appears mid-flight
The refresh token expired or was revoked from the QB side. Reconnect from Settings → Integrations → QuickBooks → Connect. Existing record links survive.
An invoice number conflict on import
Means the QB invoice has the same DocNumber as one of your CoPortal invoices. CoPortal will fall back to QB-<DocNumber>automatically — no manual fix needed.
I imported a QB invoice but reminders started going out
They shouldn't — imports default reminders to off. If they did, check the per-invoice reminders toggle (now exposed on the invoice editor since phase 98) and turn it back off.
I marked paid in CoPortal but nothing happened in QB
That's the intended behaviour — CoPortal's QB sync doesn't push payment status (with or without the “Display-only payments” toggle). Your accountant records the payment in QB. The reverse direction (QB → CoPortal) runs automatically once an hour, so the next pull will mirror their entry back to CoPortal.
I want CoPortal to mark QB invoices paid for me
Not currently supported, by design. Payment state is owned by QuickBooks; CoPortal mirrors it back hourly. If your team genuinely needs CoPortal-side payments to push out to QB, email hello@coportal.io.
QB-paid invoice still shows as unpaid in CoPortal
The hourly pull runs on the top of each hour. If you just marked it paid in QB, wait up to an hour. If it's been longer, the most likely causes are: the CoPortal invoice doesn't have a qb_invoice_idlinking it to the QB record (push it once from CoPortal to establish the link), the QB connection's tokens expired (reconnect from Settings → Integrations), or the QB invoice was voided rather than paid.