QuickBooks Online API: Complete Developer Guide for 2026

The QuickBooks Online (QBO) API is the primary interface for programmatically interacting with Intuit’s cloud accounting platform.

Whether you’re building a SaaS integration, automating invoice workflows, or syncing financial data between systems, this API is the backbone of the QuickBooks ecosystem.

This guide covers everything a developer needs to go from zero to production with the QuickBooks Online API in 2026 authentication, endpoints, rate limits, webhooks, code examples, and the hard-won lessons that save you weeks of debugging.

If you’re evaluating whether to build a QuickBooks integration in-house or hire a team, this guide will give you the technical depth to make that decision confidently.

TL;DR — Quick Start

  • What it is: A RESTful API for reading and writing accounting data in QuickBooks Online (invoices, customers, payments, journal entries, and more)
  • Auth: OAuth 2.0 (authorization code flow) — no API keys, no basic auth
  • Base URL: https://quickbooks.api.intuit.com/v3/company/{realmId}/
  • Sandbox URL: https://sandbox-quickbooks.api.intuit.com/v3/company/{realmId}/
  • SDKs: Official SDKs for Node.js, Python, Java, .NET, PHP, and Ruby
  • Rate limits: 500 requests/minute per realm, 40 concurrent requests
  • Fastest path to first call: Create an Intuit Developer account → create an app → use OAuth 2.0 Playground → make a GET request to /query?query=SELECT * FROM CompanyInfo

QuickBooks Online API Overview: How It Works

The QuickBooks Online API is a REST API that uses JSON for request and response payloads (XML is also supported but deprecated for most use cases).

Every API call targets a specific company (realm) identified by a realmId, and all requests require a valid OAuth 2.0 access token.

Architecture at a Glance

ComponentDetails
ProtocolHTTPS (TLS 1.2+)
Data FormatJSON (recommended) or XML
AuthenticationOAuth 2.0 (Authorization Code Grant)
Base URL (Production)https://quickbooks.api.intuit.com/v3/company/{realmId}/
Base URL (Sandbox)https://sandbox-quickbooks.api.intuit.com/v3/company/{realmId}/
VersioningMinor versions via minorversion query parameter (current: 75)
Response CodesStandard HTTP (200, 400, 401, 403, 404, 429, 500, 503)

Available SDKs

Intuit provides official SDKs that handle OAuth token management, request signing, and serialization:

LanguagePackage / RepositoryNotes
Node.jsnode-quickbooks (npm)Most popular community SDK; Intuit’s official SDK available via npm intuit-oauth
Pythonpython-quickbooks (PyPI)Well-maintained, supports all entity types
JavaQuickBooks-V3-Java-SDKOfficial Intuit SDK, Maven-compatible
.NETQuickBooks-V3-DotNET-SDKOfficial Intuit SDK, NuGet package available
PHPQuickBooks-V3-PHP-SDKOfficial Intuit SDK, Composer-compatible
Rubyquickbooks-ruby (gem)Community-maintained, actively updated

How to Authenticate with QuickBooks Online API Using OAuth 2.0

The QuickBooks Online API uses OAuth 2.0 Authorization Code flow exclusively. There are no API keys or basic auth options. Here’s how the flow works:

Step 1: Register Your App

Go to the Intuit Developer Portal (developer.intuit.com), create an account, and register a new app. You’ll receive:

  • Client ID (also called Consumer Key)
  • Client Secret (also called Consumer Secret)

Configure your redirect URI this is where Intuit sends the authorization code after the user grants access.

Before going live, developers should also understand the full app setup process inside the Intuit Developer Portal.

Step 2: Authorization Request

Redirect the user to Intuit’s authorization endpoint:

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=YOUR_CSRF_TOKEN

Scopes available:

  • com.intuit.quickbooks.accounting Full access to accounting data
  • com.intuit.quickbooks.payment Access to payment processing
  • openid profile email User identity information

Step 3: Exchange Authorization Code for Tokens

After the user authorizes, Intuit redirects to your redirect URI with an authorization_code. Exchange it for tokens:

// Node.js — Token Exchange
const axios = require("axios");

const tokenResponse = await axios.post(
  "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer",
  new URLSearchParams({
    grant_type: "authorization_code",
    code: authorizationCode,
    redirect_uri: YOUR_REDIRECT_URI,
  }),
  {
    headers: {
      Authorization: `Basic ${Buffer.from(
        `${CLIENT_ID}:${CLIENT_SECRET}`
      ).toString("base64")}`,
      "Content-Type": "application/x-www-form-urlencoded",
    },
  }
);

const { access_token, refresh_token, expires_in } = tokenResponse.data;
// access_token expires in 1 hour (3600s)
// refresh_token expires in 100 days

Step 4: Make Authenticated API Calls

Include the access token as a Bearer token in every request:

const response = await axios.get(
  `https://quickbooks.api.intuit.com/v3/company/${realmId}/companyinfo/${realmId}`,
  {
    headers: {
      Authorization: `Bearer ${access_token}`,
      Accept: "application/json",
    },
  }
);

Token Lifecycle

  • Access token: Valid for 1 hour (3,600 seconds)
  • Refresh token: Valid for 100 days. Use it to get a new access token before it expires

Critical: If the refresh token expires, the user must re-authorize. Store refresh tokens securely and implement proactive refresh logic

QuickBooks Online API Endpoints for Invoices, Customers, Payments & Bills

Every endpoint follows the pattern: GET|POST /v3/company/{realmId}/{entity}. Here are the most-used endpoints:

EntityCreateReadUpdateDeleteQuery
InvoicePOST /invoiceGET /invoice/{id}POST /invoicePOST /invoice?operation=deleteGET /query?query=SELECT * FROM Invoice
CustomerPOST /customerGET /customer/{id}POST /customer— (deactivate only)GET /query?query=SELECT * FROM Customer
PaymentPOST /paymentGET /payment/{id}POST /paymentPOST /payment?operation=deleteGET /query?query=SELECT * FROM Payment
BillPOST /billGET /bill/{id}POST /billPOST /bill?operation=deleteGET /query?query=SELECT * FROM Bill
Bill PaymentPOST /billpaymentGET /billpayment/{id}POST /billpaymentPOST /billpayment?operation=deleteGET /query?query=SELECT * FROM BillPayment
Journal EntryPOST /journalentryGET /journalentry/{id}POST /journalentryPOST /journalentry?operation=deleteGET /query?query=SELECT * FROM JournalEntry
AccountPOST /accountGET /account/{id}POST /account— (deactivate only)GET /query?query=SELECT * FROM Account
VendorPOST /vendorGET /vendor/{id}POST /vendor— (deactivate only)GET /query?query=SELECT * FROM Vendor
ItemPOST /itemGET /item/{id}POST /item— (deactivate only)GET /query?query=SELECT * FROM Item
Purchase OrderPOST /purchaseorderGET /purchaseorder/{id}POST /purchaseorderPOST /purchaseorder?operation=deleteGET /query?query=SELECT * FROM PurchaseOrder

Important notes on CRUD operations:

  • Update = Full object replacement. You must send the complete entity object including the SyncToken (optimistic locking). Partial updates are not supported.
  • Delete is only available on transaction entities (invoices, payments, bills). Name-list entities (customers, vendors, items, accounts) can only be deactivated by setting Active: false.

Query language uses a SQL-like syntax. Example: SELECT * FROM Invoice WHERE TotalAmt > ‘1000’ ORDERBY MetaData.CreateTime DESC MAXRESULTS 100

QuickBooks Online API Rate Limits and Throttling Rules

Understanding rate limits is critical for production integrations. Here are the current limits as of 2026:

Limit TypeThresholdScope
Requests per minute500Per realmId (company)
Concurrent requests40Per realmId (company)
Batch size30 entities per batch requestPer API call

If your integration handles high transaction volumes, review the deeper breakdown of QuickBooks API rate limits and limitations before designing sync logic.

Handling 429 (Too Many Requests) Errors

When you hit rate limits, the API returns a 429 status. Implement exponential backoff with jitter:

async function apiCallWithRetry(fn, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (error.response?.status === 429 && attempt < maxRetries - 1) {
        const baseDelay = Math.pow(2, attempt) * 1000;
        const jitter = Math.random() * 1000;
        await new Promise((r) => setTimeout(r, baseDelay + jitter));
        continue;
      }
      throw error;
    }
  }
}

Pro tips for staying under limits:

  • Use batch operations where possible (up to 30 entities per batch)
  • Use Change Data Capture (CDC) instead of polling individual entities: GET /cdc?entities=Invoice,Customer&changedSince=2026-01-01T00:00:00Z
  • Cache frequently-read reference data (Chart of Accounts, Items, Tax Codes) locally
  • Implement request queuing with rate limiting in your application layer

Common QuickBooks Online API Issues Developers Should Avoid

We’ve built dozens of QuickBooks integrations at Satva Solutions. Here are the top gotchas that trip up developers:

1. SyncToken Conflicts

Every entity has a SyncToken that increments on each update. If you send a stale SyncToken, the API returns a 400 error. Always fetch the latest entity before updating.

2. No Partial Updates

Unlike modern APIs (e.g., PATCH support), the QBO API requires you to send the entire entity object on every update. Missing fields will be set to null.

This is the single most common source of data loss in QBO integrations. (Fix common QuickBooks Online Accounting API errors, 2026)

These limitations are not just theoretical. Missing fields and unsupported objects often require practical workarounds in real-world QuickBooks integrations.

3. Sparse Updates Misconception

Intuit documents a sparse=true parameter, but it has significant limitations.

It works inconsistently across entity types, and relying on it is risky. Our recommendation: always send the full object.

4. Currency and Locale Issues

Multi-currency companies require extra handling. You must specify CurrencyRef on transactions, and exchange rates are not automatically applied.

If you’re building for international users, plan for this complexity upfront.

5. Sandbox vs. Production Gaps

The sandbox environment doesn’t perfectly mirror production behavior. Certain edge cases (webhooks, specific error codes, rate limiting behavior) may differ.

Always perform thorough testing in production with a test company.

How to Test QuickBooks Online API in Sandbox

Setting Up Your Sandbox

  • Log into the Intuit Developer Portal at developer.intuit.com
  • Navigate to your app’s Dashboard
  • Click “Sandbox” in the left menu — Intuit provides pre-populated sandbox companies with sample data
  • Use sandbox credentials (Client ID + Secret from the “Development” keys section)
  • Point API calls to: https://sandbox-quickbooks.api.intuit.com/v3/company/{realmId}/

Sandbox Test Data

Sandbox companies come pre-loaded with sample customers, invoices, items, and accounts. You can also:

  • Create additional test data via API calls
  • Reset sandbox data from the developer portal
  • Use the API Explorer in the developer portal for interactive testing

Testing Best Practices

  • Write integration tests against sandbox before deploying to production
  • Test error handling: intentionally send malformed requests, expired tokens, and duplicate entities
  • Verify webhook delivery using tools like ngrok or webhook.site for local development
  • Test with multi-currency sandbox companies if your integration handles international clients

Teams planning wider accounting integrations should also compare QuickBooks with other accounting APIs before finalizing the architecture

QuickBooks Online API Webhooks: Events, Setup & Payloads

QuickBooks Online webhooks notify your application when data changes, eliminating the need for constant polling.

Available Webhook Events

Webhooks fire on Create, Update, and Delete operations for these entities:

Account, Bill, BillPayment, Budget, Class, CreditMemo, Currency

Customer, Department, Deposit, Employee, Estimate, Invoice

Item, JournalEntry, Payment, Purchase, PurchaseOrder

RefundReceipt, SalesReceipt, TimeActivity, Transfer, Vendor, VendorCredit

Webhook Setup

  • In the Intuit Developer Portal, navigate to Webhooks in your app settings
  • Enter your endpoint URL (must be HTTPS)
  • Select the entities you want to subscribe to
  • Intuit generates a verifier token for signature validation

Webhook Payload Format

{
  "eventNotifications": [
    {
      "realmId": "1234567890",
      "dataChangeEvent": {
        "entities": [
          {
            "name": "Invoice",
            "id": "123",
            "operation": "Update",
            "lastUpdated": "2026-03-15T10:30:00Z"
          }
        ]
      }
    }
  ]
}

Validating Webhook Signatures

Always validate the webhook signature to ensure the payload is from Intuit:

const crypto = require("crypto");

function isValidWebhookSignature(payload, signature, verifierToken) {
  const hash = crypto
    .createHmac("sha256", verifierToken)
    .update(payload)
    .digest("base64");
  return hash === signature;
}

Important: Webhook payloads only contain entity IDs and operation types — not the full entity data. You must make a follow-up API call to fetch the updated entity.

QuickBooks Online API Best Practices for Production Integrations

Error Handling

  • Always check the Fault object in error responses for detailed error codes and messages
  • Implement retry logic for 429 (rate limit), 500 (server error), and 503 (service unavailable)
  • Do not retry 400 (bad request) or 401 (unauthorized) these require code or token fixes
  • Log all API errors with full request/response bodies for debugging

Pagination

The QBO query API supports STARTPOSITION and MAXRESULTS:

SELECT * FROM Invoice STARTPOSITION 1 MAXRESULTS 100
SELECT * FROM Invoice STARTPOSITION 101 MAXRESULTS 100

Maximum MAXRESULTS is 1000. For large datasets, implement pagination loops and consider using CDC for ongoing sync instead.

Minor Version Management

  • Always specify the minorversion parameter in your API calls: ?minorversion=75
  • Pin to a specific version in production don’t use “latest”
  • Test new minor versions in sandbox before upgrading production
  • Monitor Intuit’s changelog for breaking changes in new minor versions

Idempotency

  • The QBO API supports a Request-Id header for idempotent requests
  • Use a unique UUID for each create operation to prevent duplicates on retries
  • For production-grade systems, real-world validation, duplicate prevention, and error handling are just as important as API connectivity.

This is especially important for payment and invoice creation, where duplicates cause real financial issues

Security

  • Store OAuth tokens encrypted at rest (never in plain text or client-side storage)
  • Implement token refresh proactively (before expiry, not after failure)
  • Use HTTPS everywhere Intuit rejects non-TLS connections
  • Scope your OAuth permissions to only what your app needs

QuickBooks Online API Code Examples for Developers

Creating an Invoice (Node.js)

const axios = require("axios");

async function createInvoice(realmId, accessToken) {
  const invoice = {
    Line: [
      {
        Amount: 150.0,
        DetailType: "SalesItemLineDetail",
        SalesItemLineDetail: {
          ItemRef: { value: "1", name: "Services" },
          Qty: 1,
          UnitPrice: 150.0,
        },
      },
    ],
    CustomerRef: { value: "1" },
    BillEmail: { Address: "customer@example.com" },
    DueDate: "2026-04-15",
  };

  const response = await axios.post(
    `https://quickbooks.api.intuit.com/v3/company/${realmId}/invoice?minorversion=75`,
    invoice,
    {
      headers: {
        Authorization: `Bearer ${accessToken}`,
        "Content-Type": "application/json",
        Accept: "application/json",
      },
    }
  );

  return response.data.Invoice;
}

Querying Customers (Python)

import requests

def get_active_customers(realm_id, access_token, max_results=100):
    base_url = f"https://quickbooks.api.intuit.com/v3/company/{realm_id}"
    query = f"SELECT * FROM Customer WHERE Active = true MAXRESULTS {max_results}"

    response = requests.get(
        f"{base_url}/query",
        params={"query": query, "minorversion": "75"},
        headers={
            "Authorization": f"Bearer {access_token}",
            "Accept": "application/json",
        },
    )

    response.raise_for_status()
    data = response.json()
    return data.get("QueryResponse", {}).get("Customer", [])


# Usage
customers = get_active_customers(realm_id, access_token)
for customer in customers:
    print(f"{customer['DisplayName']} - {customer['PrimaryEmailAddr']['Address']}")

OAuth 2.0 Token Refresh

async function refreshAccessToken(refreshToken, clientId, clientSecret) {
  const response = await axios.post(
    "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer",
    new URLSearchParams({
      grant_type: "refresh_token",
      refresh_token: refreshToken,
    }),
    {
      headers: {
        Authorization: `Basic ${Buffer.from(
          `${clientId}:${clientSecret}`
        ).toString("base64")}`,
        "Content-Type": "application/x-www-form-urlencoded",
      },
    }
  );

  const { access_token, refresh_token, expires_in } = response.data;
  // IMPORTANT: Store the NEW refresh_token — it rotates on each refresh
  // The old refresh_token is invalidated immediately
  return { access_token, refresh_token, expires_in };
}

QuickBooks Online API FAQs

Is the QuickBooks API free?

Yes, the QuickBooks Online API itself is free to use. There are no per-call charges or monthly API fees. However, you need an active QuickBooks Online subscription for the company data you’re accessing. If you’re publishing an app on the Intuit Marketplace, there may be listing and revenue-sharing requirements.

What languages does the QuickBooks API support?

The QuickBooks Online API is language-agnostic since it’s a REST API. Intuit provides official SDKs for Java, .NET, PHP, Node.js, Python, and Ruby. You can also use any HTTP client in any programming language (Go, Rust, Swift, etc.) to interact with the API directly.

How do I get a QuickBooks API key?

QuickBooks doesn’t use traditional API keys. Instead, you register an app at developer.intuit.com to get OAuth 2.0 Client ID and Client Secret credentials. These are used in the OAuth 2.0 authorization flow to obtain access tokens. See our step-by-step guide to setting up an app on the Intuit Developer Portal.

What are QuickBooks API rate limits?

The current rate limits are 500 requests per minute per company (realmId) and 40 concurrent connections. Batch operations can include up to 30 entities per request. If you exceed these limits, you’ll receive a 429 Too Many Requests response. Implement exponential backoff with jitter to handle throttling gracefully.

Can I use the QuickBooks API with Desktop?

The QuickBooks Online API does not work with QuickBooks Desktop. Desktop uses a separate integration method via the QuickBooks Web Connector (QBWC) or the QuickBooks Desktop SDK, which uses XML-based messaging (qbXML). If you need to support both, you’ll need to build two separate integrations. Consider migrating Desktop clients to QuickBooks Online for API access.

How do I handle OAuth 2.0 token expiration?

Access tokens expire after 1 hour (3,600 seconds). Use the refresh token to obtain a new access token before the current one expires. Critical: The refresh token itself expires after 100 days and rotates on every use (the old token is invalidated). If the refresh token expires, the user must re-authorize your app. Best practice: refresh tokens proactively (e.g., at 50 minutes) and always store the new refresh token immediately.

Need Help Building Your QuickBooks Integration?

Satva Solutions has built 50+ QuickBooks Online integrations for SaaS companies, accounting firms, and enterprise teams. Whether you need a custom QuickBooks integration, API integration services, or AI-powered accounting automation, our team can help you ship faster and avoid the pitfalls covered in this guide.

Contact us

Article by

Chintan Prajapati

Chintan Prajapati is the Founder and CEO of Satva Solutions and a seasoned computer engineer with over two decades of experience in the software industry. His expertise spans Accounting & ERP Integrations, Robotic Process Automation, and the development of technology solutions built around leading ERP and accounting platforms with a particular focus on responsible AI and machine learning in fintech.Chintan holds a BE in Computer Engineering and carries an impressive roster of certifications, including Microsoft Certified Professional, Microsoft Certified Technology Specialist, Certified Azure Solution Developer, Certified Intuit Developer, Certified QuickBooks ProAdvisor, and Xero Developer.Over the course of his career, he has made a measurable impact on the accounting industry consulting on and delivering integration and automation solutions that have collectively saved thousands of man-hours. His writing aims to offer readers practical, insight-driven advice on harnessing technology to unlock greater business efficiency.When he steps away from the desk, Chintan can be found trekking through mountain trails or watching birds in the wild. Grounded in the philosophy of delivering the highest value to clients, he continues to champion innovation and excellence in digital transformation from his home base in Ahmedabad, India.