Skip to content

NEWUnify Agents (MCP): governed AI access to finance data. Early access.See Unify Agents

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 429 with 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-signature on every webhook.
  • Run CDC on a schedule to catch missed events.
  • Read company preferences before writing invoices.
  • Handle SyncToken conflicts 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:

Shell
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.

Keep reading

Get started

Connect once. Build everything else on top.

Request sandbox access, or book 30 minutes with an engineer to map your integrations.

Free sandbox access. No credit card. Reply within one business day.