A fast, production-grade command-line interface for the QuickBooks Online Accounting API. Built in Rust with zero runtime dependencies.
- 36 entity types — Full CRUD for all QuickBooks Online entities (customers, invoices, bills, payments, and 32 more)
- 25+ financial reports — Profit & Loss, Balance Sheet, General Ledger, Aged Receivables, and more with automatic tabular flattening
- OAuth 2.0 PKCE — Browser-based login in under 60 seconds with automatic token refresh and rotation handling
- 4 output formats — Table, JSON, CSV, YAML with auto-detection (table for TTY, JSON for pipes)
- SQLite response cache — Configurable TTL, per-entity invalidation, zero-config setup
- Rate limiting — Client-side enforcement of QuickBooks' 500 req/min limit with exponential backoff
- Raw query support — Execute QBO query language directly:
qb query run "SELECT * FROM Invoice WHERE Balance > '0'" - Cross-platform — macOS, Linux, Windows. Single static binary, no OpenSSL dependency
- CI/CD ready —
QBO_ACCESS_TOKENenv var for headless environments, structured exit codes (0-10)
# Homebrew (macOS/Linux) brew install osodevops/tap/qb # Cargo cargo install quickbooks-cli # Pre-built binaries curl -LO https://github.com/osodevops/quickbooks-cli/releases/latest/download/qb-aarch64-apple-darwin.tar.gzRegister an app at the Intuit Developer Portal, then:
qb config init qb config set auth.client_id YOUR_CLIENT_ID qb config set auth.client_secret YOUR_CLIENT_SECRETqb auth login # Opens browser for OAuth2 PKCE flow qb auth login --sandbox # Authenticate against sandbox qb auth status # Verify connectionqb customers list qb invoices list --where "Balance > '0'" --output json qb reports run profit-and-loss --date-macro "Last Quarter"qb auth login [--sandbox] [--port 8844] [--manual] qb auth status qb auth refresh qb auth logoutEvery entity follows a consistent pattern:
qb <entity> list [--where "Field = 'value'"] [--order-by "Field ASC"] [--all-pages] qb <entity> get <ID> qb <entity> create [--file data.json | --inline-flags...] qb <entity> update <ID> [--file updates.json | --inline-flags...] qb <entity> delete <ID> --confirm| Entity | Command | Operations |
|---|---|---|
| Account | qb accounts | list, get, create, update, delete |
| Customer | qb customers | list, get, create, update, delete |
| Vendor | qb vendors | list, get, create, update, delete |
| Employee | qb employees | list, get, create, update, delete |
| Item | qb items | list, get, create, update, delete |
| Class | qb classes | list, get, create, update, delete |
| Department | qb departments | list, get, create, update, delete |
| PaymentMethod | qb payment-methods | list, get, create, update, delete |
| Term | qb terms | list, get, create, update, delete |
| TaxCode | qb tax-codes | list, get, create, update |
| TaxRate | qb tax-rates | list, get, create, update |
| TaxAgency | qb tax-agencies | list, get |
| Budget | qb budgets | list, get, create, update, delete |
| CompanyInfo | qb company-info | get, update |
| Preferences | qb preferences | get, update |
| CompanyCurrency | qb currencies | list, get, create, update, delete |
| ExchangeRate | qb exchange-rates | get, update |
| Entity | Command | Extra Operations |
|---|---|---|
| Invoice | qb invoices | send, pdf |
| Estimate | qb estimates | send |
| SalesReceipt | qb sales-receipts | send |
| Payment | qb payments | |
| CreditMemo | qb credit-memos | send |
| RefundReceipt | qb refund-receipts | |
| Bill | qb bills | |
| BillPayment | qb bill-payments | |
| VendorCredit | qb vendor-credits | |
| Purchase | qb purchases | |
| PurchaseOrder | qb purchase-orders | send |
| JournalEntry | qb journal-entries | |
| Transfer | qb transfers | |
| Deposit | qb deposits | |
| TimeActivity | qb time-activities | |
| RecurringTransaction | qb recurring | |
| CreditCardPayment | qb cc-payments | |
| InventoryAdjustment | qb inventory-adjustments | |
| Attachable | qb attachments |
qb reports list-types # See all 25+ report types qb reports run profit-and-loss # Default date range qb reports run profit-and-loss --start-date 2026-01-01 --end-date 2026-03-31 qb reports run balance-sheet --date-macro "Last Month" qb reports run general-ledger --output csv # Auto-flattened to tabular qb reports run aged-receivables --output json qb reports run profit-and-loss --summarize-by Month --accounting-method CashAvailable report types: profit-and-loss, profit-and-loss-detail, balance-sheet, trial-balance, cash-flow, general-ledger, aged-receivables, aged-receivables-detail, aged-payables, aged-payables-detail, customer-income, customer-balance, customer-balance-detail, customer-sales, vendor-balance, vendor-balance-detail, vendor-expenses, item-sales, department-sales, class-sales, inventory-valuation, inventory-valuation-detail, journal-report, transaction-list, account-list
qb query run "SELECT * FROM Invoice WHERE TotalAmt > '1000'" qb query run "SELECT * FROM Customer WHERE Active = true" --all-pages qb query run "SELECT COUNT(*) FROM Invoice" qb query run "SELECT * FROM Invoice WHERE Balance > '0' ORDERBY DueDate DESC" --output csv# Create a customer qb customers create --display-name "Acme Corp" --email "billing@acme.com" --phone "555-1234" # Create an invoice with line items qb invoices create --customer "42" --line-item "Consulting,10,150.00" --line-item "Design,5,200.00" --due-date 2026-12-31 # Create a transfer qb transfers create --from-account "35" --to-account "36" --amount "5000.00" # Create a bill qb bills create --vendor "12" --due-date 2026-04-30 --file bill-lines.json # Dry run (validate without sending) qb invoices create --customer "42" --line-item "Test,1,100" --dry-runqb cache stats # Show cache entries, size, per-entity breakdown qb cache clear # Clear all cached responses qb cache clear --entity invoice # Clear only invoice cache| Flag | Short | Env Var | Default | Description |
|---|---|---|---|---|
--output | -o | QBO_OUTPUT | table | Output format: table, json, csv, yaml |
--profile | -p | QBO_PROFILE | default | Config profile name |
--compact | -c | — | false | Compact/minified output |
--no-color | — | NO_COLOR | false | Disable colored output |
--verbose | -v | — | false | Enable debug logging |
--quiet | -q | — | false | Suppress non-data output |
--dry-run | — | — | false | Preview without executing |
--sandbox | — | QBO_SANDBOX | false | Target sandbox environment |
--page-size | — | QBO_PAGE_SIZE | 100 | Results per page |
--all-pages | — | — | false | Auto-paginate all results |
--no-cache | — | QBO_NO_CACHE | false | Bypass response cache |
--config | — | QBO_CONFIG | Platform default | Config file path |
--minor-version | — | QBO_MINOR_VERSION | 75 | QBO API minor version |
Config file location: ~/.config/quickbooks-cli/config.toml
[default] output_format = "table" page_size = 100 minor_version = 75 sandbox = false [auth] client_id = "ABc123..." client_secret = "xyz789..." callback_port = 8844 redirect_uri = "http://localhost:8844/callback" scopes = ["com.intuit.quickbooks.accounting", "openid", "profile", "email"] [cache] enabled = true list_ttl_secs = 300 # 5 minutes for list queries get_ttl_secs = 900 # 15 minutes for get-by-ID max_size_mb = 100 [rate_limit] requests_per_minute = 500 max_concurrent = 10 batch_per_minute = 40 retry_max = 3 retry_backoff_ms = 1000 [profiles.acme] realm_id = "123456789" environment = "production" company_name = "Acme Corp" [profiles.sandbox] realm_id = "987654321" environment = "sandbox" company_name = "Sandbox Company"| Variable | Description |
|---|---|
QBO_CLIENT_ID | OAuth2 client ID (overrides config) |
QBO_CLIENT_SECRET | OAuth2 client secret (overrides config) |
QBO_ACCESS_TOKEN | Direct bearer token (bypasses OAuth, for CI/CD) |
QBO_REALM_ID | Company realm ID (required with QBO_ACCESS_TOKEN) |
QBO_PROFILE | Active profile name |
QBO_OUTPUT | Default output format |
QBO_SANDBOX | Set to 1 for sandbox environment |
QBO_PAGE_SIZE | Default page size |
QBO_MINOR_VERSION | API minor version |
QBO_CONFIG | Custom config file path |
QBO_NO_CACHE | Disable response caching |
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error |
| 2 | Configuration / usage error |
| 3 | Authentication error (run qb auth login) |
| 4 | Authorization error (insufficient scopes) |
| 5 | Rate limited / budget exhausted |
| 6 | Entity not found |
| 7 | Stale object (SyncToken conflict) |
| 8 | Validation error (invalid data) |
| 9 | Network / IO error |
| 10 | Server error (QBO 5xx) |
# Authenticate with environment variables (no browser needed) export QBO_ACCESS_TOKEN="your-access-token" export QBO_REALM_ID="your-realm-id" # Run commands qb invoices list --where "TxnDate >= '2026-01-01'" --output json > invoices.json qb reports run profit-and-loss --date-macro "Last Month" --output csv > pl.csv qb customers list --all-pages --output csv > customers.csv# Bash eval "$(qb completions bash)" # Zsh qb completions zsh > "${fpath[1]}/_qb" # Fish qb completions fish > ~/.config/fish/completions/qb.fish # Man pages qb completions man --output-dir /usr/local/share/man/man1CLI Layer (clap) GlobalArgs + 43 SubCommands (one module per entity) ├── Output Layer │ Table (comfy-table) │ JSON │ CSV │ YAML ├── Cache Layer │ SQLite (rusqlite) with TTL-based eviction ├── API Client Layer │ QBClient (reqwest + rustls-tls) │ ├── Rate Limiter (500/min sliding window + 10 concurrent semaphore) │ ├── Retry + Backoff (exponential with jitter, 3 retries) │ └── SyncToken Manager (auto-fetch before writes) └── Auth Layer ├── PKCE (OAuth2 browser flow) ├── Token Refresh (with rotation + file lock) └── Keyring Store (OS-native credential storage) git clone https://github.com/osodevops/quickbooks-cli cd quickbooks-cli cargo build --release # Binary at ./target/release/qbMIT — see LICENSE for details.