Skip to content

QuickBooks Online Batch API Sample (Java). Minimal Spring Boot app to demo QBO Accounting Batch API with optional idempotent retries via requestId, per-item parsing, and raw response display. Includes basic validation per docs (≤ 50 items, bId required

License

Notifications You must be signed in to change notification settings

IntuitDeveloper/SampleApp-Batch-Java

Repository files navigation

QuickBooks Online Batch API Sample (Java)

Short description

  • A minimal Spring Boot app that demonstrates the QuickBooks Online Accounting Batch API: posting batch payloads, optional idempotent retries via requestid, parsing per-item results, and surfacing raw responses. Includes basic payload validation aligned with documentation (≤ 50 items, bId required).

Demo

If the embedded player does not render in your environment, use the direct link: https://github.intuit.com/noneal/SampleApp-Webhooks-Java-CloudEvents/assets/86120/5171a8da-6b18-4fab-b5b6-69743cdec7bb

Local demo video (in this repo)

Direct link to the file in this repo: src/main/resources/static/images/Batch_Example.mp4?raw=1

Prerequisites

  • Java 17 or higher
  • Gradle 7.0 or higher
  • QuickBooks Developer account and a QuickBooks Online company
  • ngrok (for local development)

Setup (quick)

  1. Clone and run
git clone [email protected]:noneal/SampleApp-Batch-Java.git
cd SampleApp-Batch-Java
./gradlew bootRun

Dependencies

  • Spring Boot Web and Thymeleaf
  • QuickBooks Java SDKs: ipp-v3-java-devkit, oauth2-platform-api, ipp-v3-java-data (6.7.0)
  • JAXB for Java 17 compatibility: javax.xml.bind:jaxb-api, org.glassfish.jaxb:jaxb-runtime
  • Jackson Databind
  • Spring Session Core
  • Spring Boot Starter Test (test scope)
  1. Configure env (example)
export QB_CLIENT_ID=your_client_id
export QB_CLIENT_SECRET=your_client_secret
export QB_REDIRECT_URI=https://your-ngrok-url.ngrok-free.app/callback
export QB_ENVIRONMENT=production   # or sandbox
export QB_GRAPHQL_URL=https://qb.api.intuit.com/graphql
export QB_BASE_URL=https://quickbooks.api.intuit.com
export QB_MINOR_VERSION=75
export QB_SCOPES="com.intuit.quickbooks.accounting"
  1. Start ngrok to 8080 and set redirect URI in your app to https://<ngrok-domain>/callback

How it works

  1. Visit http://localhost:8080
  2. Click "Connect to QuickBooks" to authenticate
  3. Use “Step 2: Accounting Batch API”
    • Paste a batch payload (JSON) into the textarea.
    • Optionally provide a requestId (≤ 36 chars) to demo idempotent retries.
    • Submit to call POST /v3/company/{realmId}/batch?minorversion={mv}[&requestid=...].
    • The app shows:
      • Totals (success/fault)
      • Per-item status (by bId)
      • Raw response (pretty-printed)
    • Basic validation before send:
      • BatchItemRequest is an array
      • Count ≤ 50 (per docs)
      • Each item has a bId

Batch quick-start

  • Example payload:
{
  "BatchItemRequest": [
    { "bId": "C01", "operation": "create", "Customer": { "DisplayName": "Sandbox Demo Customer 001" } },
    { "bId": "Q01", "Query": "SELECT Id, DisplayName FROM Customer STARTPOSITION 1 MAXRESULTS 5" }
  ]
}
  • Idempotent retry (requestId): send the same URL/body twice:
POST /v3/company/{realmId}/batch?minorversion=75&requestid=7f7a1c1c-5c4f-4b2a-8e0c-abcd1234abcd
  • Business rules highlighted in the app:
    • ≤ 50 items per batch
    • ≤ 40 batch requests per minute per realmId
    • Items are independent; execution order isn’t guaranteed
    • Use requestid + stable bIds for safe retries

API Endpoints

  • / — Home page
  • /qbo-login — Initiates OAuth flow
  • /callback — OAuth callback handler
  • /batch — Executes a batch payload (optional requestId form field)
  • /logout — Clears session and logs out

Postman collection

  • Import postman/QBO-Batch.postman_collection.json into Postman.
  • Set collection variables:
    • baseUrl (default https://quickbooks.api.intuit.com)
    • realmId, accessToken, minorversion (75), requestId
  • Run:
    • “Query - First 5 Customers”
    • “Batch - Idempotent Create + Query” (send twice with the same requestId to demo idempotency)

Common Issues

  1. Forbidden (403) or Insufficient Scope
  • Ensure both scopes are configured and granted during auth
  • Re-authenticate after changing scopes
  1. Invalid client or redirect URI
  • Verify Client ID/Secret
  • Ensure redirect-uri exactly matches the app settings in the Developer Portal
  1. Environment mismatch
  • Make sure environment matches the company you are connecting to (sandbox vs production)
  1. JAVA_HOME is set to an invalid directory (e.g., /usr/bin/java)
  • Symptom: Gradle prints ERROR: JAVA_HOME is set to an invalid directory: /usr/bin/java.
  • Cause: JAVA_HOME points to the java launcher, not the JDK folder that contains bin/javac.
  • Fix (macOS, zsh):
    /usr/libexec/java_home -V                   # list installed JDKs
    export JAVA_HOME=$(/usr/libexec/java_home -v 17)
    export PATH="$JAVA_HOME/bin:$PATH"
    # persist for new shells
    echo 'export JAVA_HOME=$(/usr/libexec/java_home -v 17)' >> ~/.zshrc
    echo 'export PATH="$JAVA_HOME/bin:$PATH"' >> ~/.zshrc
    source ~/.zshrc
  • Using jenv: If you use jenv, prefer configuring via jenv instead of manually setting JAVA_HOME:
    jenv versions
    jenv global 17
    jenv which java
    echo $JAVA_HOME
  • Linux example:
    # find your JDK install path, then set e.g.
    export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
    export PATH="$JAVA_HOME/bin:$PATH"
  • Windows (PowerShell):
    setx JAVA_HOME "C:\\Program Files\\Eclipse Adoptium\\jdk-17"
    setx PATH "$($env:JAVA_HOME)\\bin;$env:PATH"
  • Gradle-only fallback: Create ~/.gradle/gradle.properties with:
    org.gradle.java.home=/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home
    

ngrok troubleshooting

  • ERR_NGROK_8012 (connection refused to upstream)

    • Symptom: ngrok shows target http://localhost:3000 but your app listens on 8080.
    • Fix: Start ngrok to 8080: ngrok http 8080 or change server.port to 3000.
  • Wrong redirect URI during OAuth

    • Ensure quickbooks.redirect-uri matches your current ngrok domain and ends with /callback.
    • Update QB_REDIRECT_URI env var or application.yml, and in the Intuit Developer Portal.
  • Tunnel not active / 404

    • Start ngrok before starting auth, and use the HTTPS forwarding URL in your app config.
    • Confirm the URL in the browser matches the latest ngrok session domain.
  • Mixed environment URLs

    • Sandbox company requires sandbox base URL: https://sandbox-quickbooks.api.intuit.com.
    • Production uses https://quickbooks.api.intuit.com.
  • Local firewall/port in use

    • Verify the app is running: open http://localhost:8080 directly.
    • If port is busy, change server.port in application.yml and re-run: ngrok http <new-port>.

Project Structure

SampleApp-Batch-Java/
├── src/main/java/com/quickbooks/demo/
│   ├── Application.java
│   ├── config/
│   ├── controller/
│   └── service/
├── src/main/resources/
│   ├── application.yml
│   ├── graphql/
│   ├── static/
│   └── templates/
└── README.md

License

This project is licensed under the Apache License 2.0 — see LICENSE.

Support

For support, visit the Intuit Developer Community (https://help.developer.intuit.com/s/) or open an issue in this repository.

GitHub repository metadata

  • Topics: quickbooks, batch-api, accounting-api, java, spring-boot, qbo, idempotency, rest, oauth2

About

QuickBooks Online Batch API Sample (Java). Minimal Spring Boot app to demo QBO Accounting Batch API with optional idempotent retries via requestId, per-item parsing, and raw response display. Includes basic validation per docs (≤ 50 items, bId required

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published