QuickBooks to BigQuery: how to load financial data your team can actually query
9 min read Data engineering The Adapters team
Last updated July 2026
Field mapping auto-plugged · tap a port to rewire
Plug a source port into
Transform on this cable
JSON in
JSON out
5 sample records ready
To load QuickBooks Online data into BigQuery, pull entities from the Intuit v3 REST Accounting
API with OAuth2, land them in a staging table, and MERGE them into partitioned target tables
keyed on the entity Id. Pull only changed records using the
MetaData.LastUpdatedTime watermark or the ChangeDataCapture endpoint, store the
watermark, and overlap the window so retries stay idempotent. Map money to
NUMERIC, dates to DATE, timestamps to UTC TIMESTAMP, and
keep both the transaction-currency and home-currency amounts so your GL totals tie back.
Key takeaways
- There is no native BigQuery connector inside QuickBooks. A managed connector, a scheduled script, or the CDC endpoint has to sit between the Intuit API and the warehouse.
- Incremental beats full pulls. Per-realm throttles and a 1000-row page cap make a naive full scan slow, so watermark on
LastUpdatedTimeor use CDC. - Money is NUMERIC, never FLOAT64. Float drift on amounts breaks reconciliation, and finance will notice before your analytics team does.
- Multi-currency needs three columns. Carry the transaction amount, the home-currency amount, and the exchange rate so BigQuery totals match QuickBooks.
How do you connect QuickBooks to BigQuery?
You connect QuickBooks to BigQuery by authenticating to the Intuit v3 REST Accounting API with OAuth2, reading each entity for a company (its "realm"), and writing the results into BigQuery through load jobs or the Storage Write API. QuickBooks ships no native BigQuery driver, so a managed connector, a scheduled script, or the CDC endpoint has to sit in the middle and move the data.
The connection has three moving parts. First, auth: an OAuth2 app with a client ID and
secret, a refresh token per company, and the realm ID that scopes every request. Second, the
read side: the v3 API exposes entities like Invoice, Bill,
Payment, Account, JournalEntry, Customer,
Vendor, and Item, queried with a SQL-like syntax. Third, a Google
Cloud service account with bigquery.dataEditor on the destination dataset, plus
object write access on a staging bucket if you land files before loading.
The managed path is the QuickBooks to BigQuery integration, which handles the OAuth refresh, pagination, the watermark, the staging table, the MERGE, and the retries. The pattern is the same one you would use for a database source such as Postgres to BigQuery, just with an accounting API in place of a wire protocol.
Can you export QuickBooks Online data to BigQuery automatically?
Yes. You schedule a job that calls the Intuit v3 API on a cadence, extracts new and changed records, and loads them into BigQuery without manual exports. QuickBooks has no built-in warehouse sync, so the automation lives in a connector or a script that manages OAuth token refresh, pagination, and the load. The result is a hands-off pipeline once it is wired up.
Pagination is the part that trips people up. The v3 API uses SQL-like queries with
STARTPOSITION and MAXRESULTS, and it caps each page at 1000 rows.
On top of that, Intuit enforces request throttles per realm, so a naive full pull of a large
company is both slow and prone to hitting limits. A production job paginates in order, backs
off on throttle responses, and checkpoints its position so a mid-run failure resumes instead
of restarting from zero.
Schedule the job to match how fresh the numbers need to be. A finance dashboard that refreshes each morning is fine on an hourly or nightly cadence. Pulling every entity on every run is wasteful, so the automation should ask for changes only, which is where incremental loading comes in.
How do you load QuickBooks data into BigQuery incrementally?
You load QuickBooks data incrementally by filtering on
MetaData.LastUpdatedTime as a watermark, or by calling the ChangeDataCapture
(CDC) endpoint, which returns every entity changed since a timestamp including deleted ones.
Store the last watermark, overlap the window slightly on each run, and MERGE into BigQuery
keyed on the entity Id so retries stay idempotent.
The watermark approach queries each entity with a clause like
WHERE MetaData.LastUpdatedTime > :last_watermark, orders by that timestamp,
and pages through the results. After a successful run you advance the stored watermark. Two
habits keep it reliable: overlap the window by a few minutes so records committed slightly
out of order are not skipped, and keep the MERGE idempotent so re-reading a handful of rows
costs nothing.
The CDC endpoint is the better fit when deletes matter. A voided or deleted invoice does not
show up in a plain LastUpdatedTime filter the way you want, but CDC reports it,
so your BigQuery tables can reflect the removal instead of carrying a ghost row. Whichever
source you use, the load pattern is the same: write the batch to a staging table, collapse it
to one row per Id keeping the latest LastUpdatedTime, then MERGE on
Id into the partitioned target. Re-running the same batch after a timeout lands
the same state rather than duplicates.
How do QuickBooks fields map to BigQuery types?
Money fields map to BigQuery NUMERIC (never FLOAT64 for money),
TxnDate maps to DATE, timestamps such as
MetaData.LastUpdatedTime map to TIMESTAMP stored in UTC, and the
entity Id stays a STRING. Currency codes are short strings and
exchange rates are NUMERIC. Get these right at load time or reconciliation gets
painful later.
First, map the entities to tables so the warehouse layout mirrors the accounting model.
| QBO entity | BigQuery table | Notes |
|---|---|---|
| Invoice | invoices | Fact table. Partition by TxnDate, cluster on CustomerRef. Line items usually land in a child invoice_lines table |
| Bill | bills | Accounts payable side. Partition by TxnDate, cluster on VendorRef |
| Payment | payments | Links to invoices through applied lines. Keep the linked transaction Ids for cash application |
| Account | accounts | Chart of accounts dimension. Small and slow-moving, so a full reload is fine |
| JournalEntry | journal_entries | GL postings. Partition journal_lines by TxnDate, cluster on AccountRef for ledger queries |
| Customer | customers | Dimension table. MERGE on Id so name and status changes update in place |
Then map the field-level types. The money and timestamp rows are the ones that cause silent problems if you get them wrong.
| QuickBooks field / type | BigQuery type | Notes |
|---|---|---|
| TotalAmt, Line.Amount (money) | NUMERIC | Never FLOAT64 for money. NUMERIC holds 38 digits with scale 9, which covers currency to the cent without drift |
| TxnDate | DATE | Calendar date of the transaction, no time component. Good partition key for fact tables |
| MetaData.LastUpdatedTime | TIMESTAMP | Store in UTC. This is the incremental watermark, so treat it as an absolute point in time |
| MetaData.CreateTime | TIMESTAMP | Also UTC. Useful for auditing when a record first appeared |
| Id, CustomerRef.value | STRING | Intuit Ids are opaque strings. Keep them as STRING and MERGE on them; do not cast to INT64 |
| CurrencyRef.value (currency code) | STRING | Three-letter ISO code such as USD or EUR. Store it next to every money amount |
| ExchangeRate | NUMERIC | Rate that converts transaction currency to home currency. Keep it so home-currency totals are reproducible |
Partition the fact tables (invoices, journal lines) by transaction date and cluster on the column you filter on most, usually account or customer. That combination cuts the bytes each dashboard query scans, which is the lever that controls your BigQuery bill.
How do you handle multi-currency in a QuickBooks to BigQuery load?
Carry both amounts and the rate. QuickBooks stores a home currency and, for multi-currency
companies, a transaction CurrencyRef plus an ExchangeRate. Load the
transaction-currency amount, the home-currency amount, and the rate into BigQuery so general
ledger totals tie back to QuickBooks exactly. Dropping any one of the three breaks
reconciliation somewhere down the line.
If a company runs a single currency, this is a non-issue: every amount is already in the home currency. The moment multi-currency is on, a euro invoice posts in EUR but rolls up to the home currency (say USD) at the exchange rate on the transaction. If you only store the EUR amount, your USD GL will not match, and if you only store the converted amount, you lose the original figure the customer actually sees. Keep both, plus the rate, and derived columns stay auditable.
One more subtlety: posting period and transaction date can differ. A bill dated at the end of
one month may post into the next accounting period. Keep both the TxnDate and
the posting period so financial reports can group either way without a second pull. Storing
the raw fields and computing period logic in BigQuery is safer than baking assumptions into
the extract.
How much does it cost to run QuickBooks to BigQuery?
BigQuery bills on two axes: storage for the bytes you keep, and compute for the bytes your queries scan. Replication itself is cheap. Table design drives the bill, because an unpartitioned table forces every dashboard query to scan the full history instead of the slice it needs. Partitioning and clustering are what keep the number sane.
Partition fact tables by TxnDate and cluster on account or customer. A report
asking for the current quarter then reads a few partitions rather than every invoice you have
ever loaded. This matters more with financial data than most people expect, since ledger and
invoice tables grow steadily and queries tend to fan out across dashboards. It is worth it to
keep an eye on what the warehouse and the
rest of your cloud run up before the monthly invoice is a surprise.
On the pipeline side, our pricing is flat by plan (Starter $49, Growth $149, Scale $399, Enterprise custom) rather than metered per row, so a busy close at month end does not produce a surprise line item. See pricing for the full breakdown. If you are still deciding where transformation should live, the tradeoffs are in ETL vs ELT. To see the entity mapping and schedule for your own company file, start a demo.
Load QuickBooks Online into BigQuery incrementally, without writing the merge logic
OAuth refresh, pagination, LastUpdatedTime watermark, CDC deletes, MERGE, and retries. Map the pair in the browser and pay a flat price from $49 a month.
No credit card required.