Skip to content

Add QuickBooks Online adapter (ChangeDataCapture)#286

Draft
maximelb wants to merge 1 commit into
masterfrom
add-quickbooks-adapter
Draft

Add QuickBooks Online adapter (ChangeDataCapture)#286
maximelb wants to merge 1 commit into
masterfrom
add-quickbooks-adapter

Conversation

@maximelb

@maximelb maximelb commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new quickbooks USP adapter that collects change/activity data from a QuickBooks Online company via the Accounting API's ChangeDataCapture (CDC) operation, over OAuth 2.0.

Important scoping note

QuickBooks Online's user-attributed "Audit Log" (the Settings → Audit Log UI feature showing who did what) is not exposed through any public Intuit API — Intuit confirms this repeatedly; it's an internal report only available in the web UI. The authoritative programmatic source of activity is ChangeDataCapture, which returns the full current state of every entity that changed since a timestamp, including deletions (status: "Deleted"). It tells you what changed and when, not the acting user or a field-level diff. The README is explicit about this so operators have correct expectations.

Authoritative sources used:

How it works

  • Auth: OAuth 2.0 refresh-token grant (HTTP Basic client creds → token endpoint). Access tokens (1h) are refreshed transparently; a 401 triggers a one-shot refresh-and-retry; rotated refresh tokens are adopted in-memory; a permanently rejected refresh token stops the adapter with a clear credential error.
  • Polling: one CDC request per poll over a rolling [since - overlap, now] window; the high-water mark advances only on success. An in-memory deduper keyed on entityType|Id|LastUpdatedTime gives exactly-once delivery across the overlap while still re-emitting when an object is edited again.
  • QBO constraints handled: clamps to CDC's 30-day horizon (with a warning), warns on the 1000-object response cap, and retries 429/5xx with exponential backoff.
  • Config: configurable entity set (sensible default of 15 core entities), sandbox/prod roots, minor-version pin, poll interval, overlap, initial lookback, dedupe TTL, retry tuning. Registered in containers/conf/all.go and containers/general/tool.go; usage is reflection-generated automatically.

Tests

go test ./quickbooks/ (also passing under -race):

  • Unit: CDC response parsing (grouping, deletions, faults, empty/invalid bodies, big-int precision, deterministic ordering), dedupe keying (incl. re-ship on new revision and SyncToken/content-hash fallbacks), config validation/defaults, base/token URL resolution, transient-error classification (incl. TokenError wrapping).
  • End-to-end against a mock QBO server (token + CDC endpoints): verbatim payload shipping with event type = entity type and event time from MetaData.LastUpdatedTime, exactly-once delivery, mid-run new change, updated-entity re-ship, deletion capture, transparent 401 token refresh, multi-poll overlap with no re-ship, and credential-failure shutdown.

Notes for reviewers

  • Pattern closely follows the existing threatlocker adapter (generic client + adapter + uspSink test seam + deduper).
  • Draft: opening for review of the CDC-vs-AuditLog approach and the default entity list before finalizing.

🤖 Generated with Claude Code

Collects change/activity data from a QuickBooks Online company via the
Accounting API's ChangeDataCapture (CDC) operation, over OAuth 2.0.

QuickBooks Online's user-attributed "Audit Log" UI feature is not exposed
through any public Intuit API; CDC is the authoritative programmatic source
of change activity (creations, updates, and deletions across entities), so
the adapter polls CDC on a rolling window and ships each changed entity to
LimaCharlie verbatim, tagged with its entity type.

Highlights:
- OAuth 2.0 refresh-token flow with transparent access-token refresh,
  one-shot 401 refresh-and-retry, refresh-token rotation handling, and a
  fatal stop on permanently rejected credentials.
- Rolling-window CDC polling with overlap + in-memory dedupe keyed on
  entityType|Id|LastUpdatedTime (re-emits a fresh event when an object is
  edited again). Clamps to CDC's 30-day horizon and warns on the 1000-object
  cap. Retries 429/5xx with exponential backoff.
- Configurable entity set (sensible default), sandbox/prod roots, minor
  version pin, poll interval, overlap, and initial lookback.
- Thorough tests: unit tests for CDC response parsing, dedupe keying,
  config validation, transient-error classification; plus end-to-end tests
  against a mock QBO server (token + CDC) covering verbatim shipping,
  exactly-once delivery, updated-entity re-ship, deletions, 401 token
  refresh, and credential-failure shutdown.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

2 participants