Skip to content

feat(quickbooks): add QuickBooks Online integration#4452

Open
waleedlatif1 wants to merge 6 commits intostagingfrom
waleedlatif1/quickbooks-integration
Open

feat(quickbooks): add QuickBooks Online integration#4452
waleedlatif1 wants to merge 6 commits intostagingfrom
waleedlatif1/quickbooks-integration

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

Summary

  • Add QuickBooks Online integration with 16 tools (customer, invoice, vendor, bill, payment, item, account, estimate CRUD + query + company info)
  • Wire QuickBooks OAuth provider with realmId capture via cookie and refresh token rotation
  • Add QuickBooks block, icon, and docs

Type of Change

  • New feature

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link
Copy Markdown

vercel Bot commented May 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped May 5, 2026 8:50pm

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 5, 2026

PR Summary

Medium Risk
Adds a new OAuth provider flow (cookie-based realmId capture) and exposes new token response fields, which could affect authentication/session handling and token refresh behavior. Also introduces a sizeable new set of external-API tools whose request/response transforms and query sanitization need validation against QuickBooks edge cases.

Overview
Adds a new QuickBooks Online integration end-to-end: documentation (quickbooks.mdx + meta.json), new QuickBooksIcon, and inclusion in both docs and landing-page icon/integration mappings.

Introduces a QuickBooks OAuth provider with realmId capture: the auth callback interceptor stores realmId in an httpOnly cookie, account creation/update persists it into the credential scope as __qb_realm__:*, and the OAuth token endpoint now parses and returns realmId (contract + tools context updated).

Implements a new QuickBooks block and tool suite (quickbooks_*) for listing/querying and creating/updating core QBO entities (customers, invoices, vendors, items, payments, bills, accounts, estimates) plus send_invoice and get_company_info, including QQL where-clause sanitization and environment-based API base URL selection.

Reviewed by Cursor Bugbot for commit d026d58. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 5, 2026

Greptile Summary

This PR adds a full QuickBooks Online integration: 22 tools covering customers, invoices, vendors, bills, payments, items, accounts, estimates, and a raw query escape-hatch. It wires a custom Intuit OAuth provider into Better Auth using a cookie-based realmId relay (qb_pending_realm) and stores the realmId as a tagged prefix in the account's scope field so it can be surfaced to tools via the existing token route.

  • The cookie-based realmId capture in the callback interceptor, getUserInfo, and the two DB hooks is a well-structured workaround for Intuit's non-standard realmId delivery; the stable quickbooks-${realmId} account ID and sanitizeWhereClause close the two previously flagged issues.
  • coerceJsonArray in utils.ts calls JSON.parse without a try/catch, so malformed line-item JSON from an LLM produces a raw SyntaxError instead of the contextual message the label argument is meant to provide.
  • The account.update.after realmId guard silently skips the update whenever __qb_realm__: is already present in scope, which is correct for same-company re-auth but means changing a credential's linked company requires creating a new connection — this behaviour is implicit and could be documented.

Confidence Score: 5/5

Safe to merge — the OAuth flow, realmId relay, token extraction, and all 22 tool implementations are logically sound; previously flagged issues have been addressed.

The cookie-based realmId capture is correctly ordered (set before Better Auth processes the callback, read in getUserInfo and the two hooks, deleted in update.after). All tools guard against missing realmId and accessToken at runtime. The only open items are a missing try/catch around JSON.parse in coerceJsonArray and an implicit same-company-only update constraint in account.update.after — neither affects correctness for the expected usage paths.

No files require special attention; the most complex logic is in auth.ts around the hook ordering, which is correctly sequenced.

Important Files Changed

Filename Overview
apps/sim/lib/auth/auth.ts Adds QuickBooks OAuth provider with cookie-based realmId capture in getUserInfo, account.create.before, and account.update.after hooks; stable account ID prevents duplicate rows
apps/sim/app/api/auth/[...all]/route.ts Intercepts QuickBooks OAuth callback to capture realmId into a secure httpOnly cookie before Better Auth processes it
apps/sim/app/api/auth/oauth/token/route.ts Extracts realmId from the qb_realm: prefix in the stored scope and surfaces it alongside the access token for tool use
apps/sim/tools/quickbooks/utils.ts Provides buildCompanyUrl, sanitizeWhereClause (with quoted-literal stripping), coerceJsonArray, and quickbooksAuthHeaders helpers
apps/sim/tools/quickbooks/query.ts Raw QQL passthrough tool with user-or-llm visibility; intentionally unrestricted, consistent with the documented run-arbitrary-query purpose
apps/sim/tools/quickbooks/send_invoice.ts No body property; Content-Type overridden to application/octet-stream; matches Intuit zero-byte body requirement
apps/sim/blocks/blocks/quickbooks.ts Comprehensive block config with 22 operations, conditional sub-block rendering, and correct params mapping
apps/sim/tools/quickbooks/update_invoice.ts Sparse update for invoice with correct at-least-one-field guard
apps/sim/tools/quickbooks/update_customer.ts Sparse update for customer with correct at-least-one-field guard and proper nested structures for email and phone

Reviews (5): Last reviewed commit: "fix(quickbooks): strip string literals b..." | Re-trigger Greptile

Comment thread apps/sim/lib/auth/auth.ts Outdated
Comment thread apps/sim/tools/quickbooks/list_customers.ts
Comment thread apps/sim/tools/quickbooks/send_invoice.ts
Comment thread apps/sim/tools/quickbooks/send_invoice.ts Outdated
Comment thread apps/sim/app/(landing)/integrations/data/integrations.json Outdated
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/tools/quickbooks/utils.ts Outdated
Comment thread apps/sim/tools/quickbooks/create_invoice.ts
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/blocks/blocks/quickbooks.ts
Comment thread apps/sim/tools/quickbooks/create_bill.ts Outdated
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/lib/auth/auth.ts
Comment thread apps/sim/tools/quickbooks/types.ts
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

Comment thread apps/sim/tools/quickbooks/utils.ts
Comment thread apps/sim/lib/auth/auth.ts
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d026d58. Configure here.

Comment thread apps/sim/lib/auth/auth.ts
return null
}
return {
id: `quickbooks-${realmId}`,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing unique ID suffix breaks account deduplication

High Severity

The QuickBooks getUserInfo returns id: \quickbooks-${realmId}`without appending-${generateId()}, unlike every other OAuth provider (Google, HubSpot, etc.). The account.create.afterhook's deduplication logic depends on a UUID suffix to identify stale accounts — it strips the UUID viaUUID_SUFFIX_REto find the stable prefix, then only runs migration whenstablePrefix !== account.accountId. Without the suffix, those are always equal, so stale account cleanup never fires. This also means Better Auth may block re-connections or cross-user connections to the same QuickBooks company because the accountId` collides.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d026d58. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant