PLATFORMS
The QuickBooks Online API, explained for builders
OAuth, rate limits, webhooks, sandbox companies and the objects that trip teams up. Read this before your first QuickBooks Online API call.
By Unify Int team4 min read
- quickbooks-online
- accounting
- platforms
QuickBooks Online is often the first accounting integration a product team builds. It is well documented, it has a large small-business footprint in the US, and Intuit runs a developer program with sandbox companies.
It also has habits that surprise teams on their second week. This guide covers the parts that matter before you write production code: auth, rate limits, webhooks, sandboxes and the objects that cause most bugs.
Details below reflect Intuit's public documentation at the time of writing. Limits and versions change, so check Intuit's current docs before you rely on a number.
Auth: OAuth 2.0 with rotating refresh tokens
QuickBooks Online uses OAuth 2.0 with the authorization code flow. Your customer signs in to Intuit, picks a company, and grants your app access. You receive an access token, a refresh token and a realmId, which identifies the company file.
Three things to plan for:
- Short-lived access tokens. Access tokens last about an hour. Refresh them before they expire, not after the first 401.
- Rotating refresh tokens. Refresh tokens are long-lived (around 100 days) but can change when you use them. Always store the refresh token returned by the latest refresh. Teams that keep the original token find connections silently dying months later.
- One connection per realm. A customer with three company files means three connections. Key everything by
realmId, never by user.
Treat refresh as a critical write. If two workers refresh the same connection at once, one of them may end up holding a token that is no longer valid. Use a lock per connection.
Rate limits and concurrency
Intuit throttles per company (realm) and per app. Its documentation describes a limit of roughly 500 requests per minute per realm, plus a cap on concurrent requests. Exceed them and you get HTTP 429 responses.
In practice, the limit you hit is not the steady-state one. It is month-end, when a customer backfills a year of transactions while your nightly sync also runs. Build for that:
- Queue requests per realm and respect
429with backoff. - Use batch operations where Intuit offers them to reduce request count.
- Prefer incremental reads over full re-syncs.
Webhooks and change data capture
QuickBooks Online webhooks tell you that something changed, not what it changed to. A notification lists the realm, the entity type (Invoice, Bill, Customer), the entity id and the operation. You then fetch the record.
Notifications are signed. Intuit sends an intuit-signature header, an HMAC-SHA256 of the payload using your webhook verifier token. Verify it before you trust anything in the body.
Webhooks can be delayed or missed, like any webhook. Intuit also offers a change data capture (CDC) endpoint that returns entities changed since a timestamp. A reliable design uses webhooks for speed and CDC on a schedule to catch anything missed.
Sandbox companies
Intuit lets you create sandbox companies from the developer portal. They come with sample data and behave like real files for most purposes. Use them for automated tests, and create more than one: a US company with sales tax, and a non-US company if you sell abroad.
Sandbox data is not production data. Real customer files have years of history, odd account names, inactive customers and custom fields. Test against a copy of a messy real file before launch if a customer will let you.
The objects that trip teams up
Invoices and sales tax
Tax handling depends on the company's region and settings. US companies using automated sales tax calculate tax differently from companies with manual tax codes. Read the company's preferences before you create invoices, and do not assume you can send a tax amount directly.
Items and accounts
Invoice lines reference items, and items map to income accounts. If your product thinks in "revenue accounts", you still need an item. Decide early whether you create items, map to existing ones, or ask the customer to choose.
Payments and linked transactions
A Payment can settle several invoices, partly or fully. The link lives in Line[].LinkedTxn. Reconciliation logic that assumes one payment per invoice breaks on the first real customer.
Updates and SyncToken
QuickBooks Online uses optimistic concurrency. Every entity has a SyncToken. To update it, you send the current token. If someone changed the record since you read it, the update fails. This is good behavior; handle it by re-reading and re-applying, not by retrying blindly.
Sparse vs full updates
A full update replaces fields you omit. A sparse update ("sparse": true) changes only the fields you send. Use sparse updates unless you mean to overwrite.
Minor versions
The API uses a minorversion query parameter to opt in to newer behavior and fields. Pin a minor version explicitly and test before moving. Intuit retires old minor versions over time, so track their deprecation notices.
A checklist before you ship
- Store the newest refresh token after every refresh, with a per-connection lock.
- Key data by
realmId. - Queue per realm, back off on 429.
- Verify
intuit-signatureon every webhook. - Run CDC on a schedule to catch missed events.
- Read company preferences before writing invoices.
- Handle
SyncTokenconflicts by re-reading. - Use sparse updates.
- Pin a
minorversion. - Test against a messy file, not only a sandbox.
What the same call looks like on a unified API
On Unify Int, the QuickBooks Online details above sit behind the Unify Accounting API. You call one endpoint, and the response has the same shape as Xero or NetSuite:
curl "https://api.unifyint.com/v1/finance/invoices?status=open&limit=1" \
-H "Authorization: Bearer $UNIFY_API_KEY" \
-H "Unify-Connection-Id: conn_qbo_8f2k1"Token refresh, throttling, webhook verification and CDC catch-up run on the platform. The original QuickBooks record is still available in raw when you need a field we don't model.
How Unify Int fits
If QuickBooks Online is your first accounting integration but not your last, start on a shared model. See the Accounting API and the QuickBooks Online integration, or request sandbox access with a QuickBooks Online demo company.