QuickBooks API Integration: A Complete Guide
February 26, 2026
QuickBooks Online's API is the canonical accounting integration for B2B SaaS products targeting SMB and mid-market customers. The endpoints are well-documented and the OAuth 2.0 flow is standard. The complexity isn't the API itself — it's everything around it: per-tenant token lifecycles, SyncToken-based optimistic locking on every write, Change Data Capture for incremental sync, webhook signature validation, and rate limit isolation per company.
This guide covers the direct QuickBooks Online API integration path end-to-end, then explains where the operational overhead becomes the dominant cost — and what that means for products supporting multiple accounting platforms.
Key takeaways
- QuickBooks Online uses OAuth 2.0 with 1-hour access tokens and 100-day rolling refresh tokens. Token lifecycle management is the first source of operational complexity for multi-tenant integrations.
- Every writable QuickBooks entity has a SyncToken that must be included on updates. Stale tokens cause rejections — your code has to retry on version conflict.
- Change Data Capture (CDC) is the recommended incremental sync pattern. Polling full datasets is a trap; CDC returns only changed records since a timestamp.
- Production rate limits are 500 requests per minute and 10 concurrent requests per realmId. Multi-tenant integrations need per-tenant queues, not a single global queue.
- Direct QuickBooks integrations are tractable for one accounting platform. They become a sustained engineering investment when you need to support QuickBooks plus Xero plus NetSuite plus Sage — at which point a unified accounting API removes most of the per-vendor lifecycle work.
Before you start: which QuickBooks API do you need?
QuickBooks has three distinct APIs. Most B2B SaaS integrations target QuickBooks Online — but knowing which one you actually need prevents wasted setup work.
- QuickBooks Online (QBO) API — for cloud QuickBooks accounts. Most B2B SaaS integrations target this. Covered in detail below.
- QuickBooks Desktop API — for the on-premise version. Different architecture (Web Connector and SDK-based). If your customers run QuickBooks Desktop, you need a separate integration path.
- QuickBooks Payments API — for payment processing. Independent product, separate scope (
com.intuit.quickbooks.payment).
This guide covers QuickBooks Online. The others have separate documentation and integration patterns.
How do you set up a QuickBooks Online developer app?
Start at the Intuit Developer Portal.
Create an app and select the appropriate scope:
com.intuit.quickbooks.accounting— accounting data: invoices, customers, payments, etc.com.intuit.quickbooks.payment— QuickBooks Payments
Most B2B SaaS products require the Accounting scope at minimum.
When you create your app, Intuit provides:
- Client ID
- Client Secret
- Access to a sandbox company for testing
Intuit documents sandbox environments and base URLs in its official sandbox guide.
How does QuickBooks Online OAuth 2.0 work?
QuickBooks Online uses the OAuth 2.0 Authorization Code Flow.
Authorization URL pattern:
https://appcenter.intuit.com/connect/oauth2
?client_id=YOUR_CLIENT_ID
&redirect_uri=YOUR_REDIRECT_URI
&response_type=code
&scope=com.intuit.quickbooks.accounting
&state=RANDOM_STRING
After approval, Intuit redirects back with:
coderealmId— the company ID; store this immediately, you'll need it on every subsequent request
Exchange the authorization code at:
https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer
Intuit's OAuth documentation outlines this flow and required headers.
How do you manage QuickBooks access tokens and refresh tokens?
QuickBooks token behaviour:
- Access tokens expire in 1 hour
- Refresh tokens are valid up to 100 days, rolling expiration
Operational requirements for production:
- Store
realmId,access_token,refresh_token, and expiry timestamps per connected company - Refresh access tokens automatically before they expire
- Always store the latest refresh token returned — Intuit rotates them
- If refresh fails, require customer re-authorization
Token storage must be multi-tenant and encrypted at rest. The realmId is what scopes data to a specific QuickBooks company; mixing this up across tenants is a serious data-integrity bug.
What are the QuickBooks Online API base URLs and request patterns?
Production base URL:
https://quickbooks.api.intuit.com/v3/company/{realmId}/
Sandbox base URL:
https://sandbox-quickbooks.api.intuit.com/v3/company/{realmId}/
All requests require:
Authorization: Bearer {access_token}
Accept: application/json
Example: fetch a customer
GET /v3/company/{realmId}/customer/{customerId}
Every request scopes to a specific realmId. Routing requests to the wrong company is one of the most common multi-tenant bugs — design your service so the connection ID resolution happens once, at the start of the request, and the realmId is opaque to the rest of your code.
How does the QuickBooks query endpoint work?
QuickBooks uses a SQL-like query syntax for filtered reads:
GET /v3/company/{realmId}/query?query=SELECT * FROM Customer ORDERBY FamilyName MAXRESULTS 100
This allows filtering and pagination using familiar SQL constructs (WHERE clauses, ORDER BY, MAXRESULTS). It's the recommended pattern for any read that isn't a direct lookup by ID.
How do QuickBooks SyncTokens work?
Every writable entity in QuickBooks includes:
IdSyncToken
When you update an object, you must include the current SyncToken in the request. If the token is stale (someone else updated the object since you last read it), QuickBooks rejects the update with a version conflict.
The practical pattern:
- Retrieve the object
- Update with the latest
SyncToken - On version conflict, re-fetch and retry
This is QuickBooks' optimistic locking mechanism. It prevents lost updates in concurrent-write scenarios — but it means every update path in your code needs retry logic. There's no way to "force" an update past a stale SyncToken; you have to re-fetch.
How does QuickBooks Change Data Capture (CDC) work for incremental sync?
Polling full datasets in QuickBooks doesn't scale. Once a customer has thousands of invoices or transactions, full-dataset reads burn rate-limit budget and miss recent changes during the read window.
CDC is the answer:
GET /v3/company/{realmId}/cdc?entities=Customer,Invoice,Payment&changedSince=2024-01-01T00:00:00Z
CDC returns only records changed since the timestamp. It's the recommended incremental sync pattern for any production integration.
If you're deciding between polling and event-driven updates more broadly, our article on polling vs. webhooks explains the operational trade-offs between periodic API reads and real-time event delivery.
How do QuickBooks Online webhooks work?
QuickBooks supports webhooks per app environment.
Key characteristics:
- One webhook endpoint per app
- Payload includes changed entities and the affected
realmId - You must validate webhook signatures using the verifier token Intuit provides
The common architecture:
Webhook fires → enqueue job → call CDC for changed entities → update internal data store
The webhook itself is a notification, not a data delivery — it tells you something changed but not what specifically. You still need to call CDC (or fetch the entity directly) to get the actual changed data.
This is the canonical sync-then-notify pattern: data is changed at the source, a notification fires, and your application has to make a follow-up call to retrieve the change. It's reliable, but it requires you to build and maintain the change-detection plumbing.
What are QuickBooks Online API rate limits?
Production limits:
- 500 requests per minute per
realmId - 10 concurrent requests per
realmId
Design implications for multi-tenant integrations:
- Per-tenant queues, not a single global queue — one customer's heavy sync shouldn't block another's
- Failure isolation per tenant — one customer's expired token shouldn't take out the rest
- Exponential backoff on 429 responses, with jitter
The 10-concurrent limit is the tight constraint in practice. Most teams hit this before the 500/minute ceiling.
Where do QuickBooks integrations become operationally complex?
Direct QuickBooks integrations require you to own:
- OAuth lifecycle and refresh token rotation
- Multi-tenant
realmIdscoping - SyncToken versioning and version-conflict retry
- CDC incremental sync design
- Webhook signature validation
- Chart-of-accounts mapping per customer
- Rate limit management per company
- Error handling and observability across all of the above
For a single internal workflow, this is manageable. For a B2B SaaS serving hundreds or thousands of QuickBooks companies, it becomes sustained infrastructure — typically one engineer's part-time job, often more.
The harder reality: QuickBooks is rarely the only accounting integration a B2B SaaS needs. Customers in different segments use Xero (international SMB), NetSuite (mid-market and enterprise), Sage (industry-specific), and FreshBooks (solo and microbusiness). Each has its own auth lifecycle, its own version-control model, its own webhook semantics. The operational load multiplies per integration.
How does Unified's Accounting API simplify QuickBooks integration?
Unified.to provides a category-level Accounting API that standardizes common financial objects across QuickBooks, Xero, NetSuite, Sage, FreshBooks, Microsoft Dynamics 365 Business Central, and others.
Setup
Configure your OAuth redirect URI in Intuit as:
https://api.unified.to/oauth/code
In your Unified workspace, activate QuickBooks, enter your Client ID and Client Secret, authorize the company, and store the connection_id. That connection_id is the only thing your application needs to know going forward.
Calling the API
List invoices:
GET https://api.unified.to/accounting/invoice/{connection_id}?limit=50
Authorization: Bearer YOUR_API_KEY
Create an invoice:
POST https://api.unified.to/accounting/invoice/{connection_id}
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
The same code works for Xero, NetSuite, Sage, and other accounting integrations — the only thing that changes is the connection_id.
Unified's Accounting API supports the standard accounting objects: Invoice, Bill, CreditMemo, Payment, Account, Journal, Transaction, Contact, PurchaseOrder, Expense, and reports including BalanceSheet, TrialBalance, ProfitLoss, and CashFlow. For QuickBooks-specific fields not in the normalized schema, the raw passthrough mechanism provides direct access to provider-specific endpoints while keeping the unified authentication and connection management.
Webhooks
Unified handles webhook signature validation, CDC orchestration, and event normalization. Your application receives:
- Created events
- Updated events
- Deleted events
In a consistent payload format across all accounting integrations.
Direct vs. Unified — when to choose each
| Consideration | Direct QuickBooks integration | Unified Accounting API |
|---|---|---|
| Setup time | Days to weeks | Minutes |
| OAuth lifecycle management | You implement and maintain | Handled |
| SyncToken / version conflict logic | You implement | Handled |
| CDC and incremental sync | You implement | Handled |
| Webhook signature validation | You implement | Handled |
| Rate limit per-tenant queueing | You implement | Handled |
| Multi-platform support | Separate implementation per vendor | Same code, different connection_id |
| Vendor-specific feature depth | Full access | Normalized + raw passthrough |
| Pricing | Free (engineering cost only) | Usage-based per API call |
Build directly if
- QuickBooks Online is your only accounting integration
- You need full provider-specific flexibility for advanced QuickBooks features
- You want complete control over OAuth, CDC, and webhook implementation
Use Unified if
- You support (or plan to support) multiple accounting platforms
- You want standardized accounting objects across vendors
- You'd rather not maintain OAuth lifecycle, SyncToken, CDC, and webhook logic per vendor
- You want consistent webhook semantics across systems
- You want usage-based pricing instead of per-connection fees
Mycroft, an AI-driven security and compliance platform, used Unified.to specifically to avoid this build-vs-buy trap. CEO Mike Kim: "Unified.to transformed how we add integrations at Mycroft, reducing launch time to just 15 minutes. It's not just about speed — it's allowed us to free up 25% of our development time for innovation."
Teams evaluating integration architecture more broadly often compare ETL pipelines, workflow automation platforms, and unified APIs. Our article on ETL vs. iPaaS vs. Unified API breaks down how each approach affects long-term engineering overhead.
If your product specifically needs to handle accounting data across multiple platforms, our guide on Accounting API Integration: Invoices, Bills, Transactions, and Financial Reporting Across Platforms explains the common objects and patterns used across accounting APIs.
Final thoughts
A QuickBooks API integration is often a purchasing requirement for SMB-focused B2B SaaS products. At the endpoint level, the API is straightforward.
At scale, the complexity lies in:
- OAuth lifecycle management
- Multi-tenant isolation
- SyncToken versioning
- CDC incremental sync
- Rate limit compliance
- Data mapping per customer
If QuickBooks Online is the only accounting platform you'll ever support, build directly — the engineering investment is contained and you keep full provider-specific flexibility.
If your roadmap includes QuickBooks plus other accounting platforms, every additional integration repeats the OAuth lifecycle, sync logic, and rate-limit work. A unified accounting API turns that linear cost into a constant.
Unified.to's Accounting API supports QuickBooks alongside Xero, NetSuite, Sage, FreshBooks, Microsoft Dynamics 365 Business Central, and others through a single normalized schema.
Start a free trial or book a demo to see it work.