{"skill":{"slug":"qbo-automation","displayName":"QBO Automation","summary":"QuickBooks Online automation: chart of accounts setup, bank rule configuration, recurring transaction templates, reconciliation workflows, and journal entry...","description":"---\nname: qbo-automation\ndescription: >\n  QuickBooks Online automation: chart of accounts setup, bank rule configuration,\n  recurring transaction templates, reconciliation workflows, and journal entry generation.\n  Use when a user needs to configure or automate QBO accounting operations. Domain-specific\n  accounting knowledge included. NOT for tax filing, payroll processing, or direct QBO\n  OAuth setup (use qbo-to-tax-bridge for tax mapping, and a separate auth skill for OAuth).\nmetadata:\n  openclaw:\n    requires:\n      bins: []\n    tags:\n      - accounting\n      - quickbooks\n      - finance\n      - automation\n      - bookkeeping\n---\n\n# QBO Automation Skill\n\nAutomates QuickBooks Online operations: chart of accounts, bank rules, recurring transactions,\nreconciliation, and journal entries. Backed by accounting domain knowledge.\n\n---\n\n## Prerequisites\n\n- QBO account with admin or accountant access\n- QBO API credentials (Client ID, Client Secret, Refresh Token) stored in environment:\n  - `QBO_CLIENT_ID`\n  - `QBO_CLIENT_SECRET`\n  - `QBO_REFRESH_TOKEN`\n  - `QBO_REALM_ID` (Company ID)\n- Node.js or Python environment for API calls (or use QBO's web UI with guided steps below)\n\n---\n\n## 1. Chart of Accounts Setup\n\n### Standard Account Hierarchy (US Small Business)\n\n```\nASSETS\n  1000  Checking Account              (Bank)\n  1010  Savings Account               (Bank)\n  1100  Accounts Receivable           (Accounts Receivable)\n  1200  Inventory Asset               (Other Current Asset)\n  1500  Computer Equipment            (Fixed Asset)\n  1510  Accumulated Depreciation      (Fixed Asset)\n\nLIABILITIES\n  2000  Accounts Payable              (Accounts Payable)\n  2100  Credit Card                   (Credit Card)\n  2200  Payroll Liabilities           (Other Current Liability)\n  2300  Sales Tax Payable             (Other Current Liability)\n  2700  Notes Payable                 (Long Term Liability)\n\nEQUITY\n  3000  Owner's Equity                (Equity)\n  3100  Owner's Draw                  (Equity)\n  3200  Retained Earnings             (Equity)\n\nINCOME\n  4000  Services Revenue              (Income)\n  4100  Product Sales                 (Income)\n  4200  Other Income                  (Other Income)\n\nCOST OF GOODS SOLD\n  5000  Cost of Goods Sold            (Cost of Goods Sold)\n\nEXPENSES\n  6000  Advertising & Marketing       (Expense)\n  6010  Bank Charges & Fees           (Expense)\n  6020  Dues & Subscriptions          (Expense)\n  6030  Insurance                     (Expense)\n  6040  Meals & Entertainment         (Expense)\n  6050  Office Supplies               (Expense)\n  6060  Professional Fees             (Expense)\n  6070  Rent or Lease                 (Expense)\n  6080  Utilities                     (Expense)\n  6090  Vehicle Expense               (Expense)\n  6100  Travel                        (Expense)\n  6200  Payroll Expenses              (Expense)\n  6300  Depreciation                  (Expense)\n```\n\n### QBO API — Create Account (Python/requests)\n\n```python\nimport requests, json, base64, os\n\ndef get_access_token():\n    \"\"\"Exchange refresh token for access token.\"\"\"\n    credentials = base64.b64encode(\n        f\"{os.environ['QBO_CLIENT_ID']}:{os.environ['QBO_CLIENT_SECRET']}\".encode()\n    ).decode()\n    resp = requests.post(\n        \"https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer\",\n        headers={\n            \"Authorization\": f\"Basic {credentials}\",\n            \"Content-Type\": \"application/x-www-form-urlencoded\"\n        },\n        data={\n            \"grant_type\": \"refresh_token\",\n            \"refresh_token\": os.environ[\"QBO_REFRESH_TOKEN\"]\n        }\n    )\n    return resp.json()[\"access_token\"]\n\ndef create_account(access_token, realm_id, name, account_type, account_sub_type, acct_num=None):\n    \"\"\"Create a QBO account.\"\"\"\n    payload = {\n        \"Name\": name,\n        \"AccountType\": account_type,\n        \"AccountSubType\": account_sub_type\n    }\n    if acct_num:\n        payload[\"AcctNum\"] = acct_num\n    resp = requests.post(\n        f\"https://quickbooks.api.intuit.com/v3/company/{realm_id}/account\",\n        headers={\n            \"Authorization\": f\"Bearer {access_token}\",\n            \"Content-Type\": \"application/json\",\n            \"Accept\": \"application/json\"\n        },\n        json=payload\n    )\n    return resp.json()\n\n# Example: Create a new expense account\ntoken = get_access_token()\nrealm = os.environ[\"QBO_REALM_ID\"]\nresult = create_account(token, realm,\n    name=\"Software Subscriptions\",\n    account_type=\"Expense\",\n    account_sub_type=\"OtherMiscellaneousExpense\",\n    acct_num=\"6025\"\n)\nprint(result)\n```\n\n### Bulk Account Import (CSV → QBO)\n\nQBO supports bulk import via **Accountant Toolbox > Chart of Accounts > Import**.\n\nCSV format:\n```csv\nAccount Name,Type,Detail Type,Account Number,Description,Balance\nChecking Account,Bank,Checking,1000,Main operating account,0\nAccounts Receivable,Accounts receivable,Accounts Receivable (A/R),1100,,0\nSoftware Subscriptions,Expense,Other Miscellaneous Service Cost,6025,SaaS tools,,\n```\n\n---\n\n## 2. Bank Rules Configuration\n\nBank rules auto-categorize imported bank/credit card transactions.\n\n### Rule Types\n- **Category Rules** — assign account + class/location\n- **Split Rules** — divide transaction across multiple accounts\n- **Vendor Rules** — auto-assign payee name\n\n### QBO UI Steps (no API — bank rules not in QBO API v3)\n\n1. Go to **Banking > Rules > New rule**\n2. Set:\n   - Rule name: descriptive (e.g., \"AWS Monthly Charges\")\n   - Apply to: Money out / Money in\n   - Bank account: select account\n   - Conditions:\n     - `Description` **contains** `AMAZON WEB SERVICES`\n   - Then:\n     - Category: `Software Subscriptions (6025)`\n     - Payee: `Amazon Web Services`\n     - Class (if tracking): `Operations`\n3. Save and run rule against unreviewed transactions\n\n### Common Bank Rule Templates\n\n| Rule Name | Condition | Category | Notes |\n|-----------|-----------|----------|-------|\n| AWS Charges | Description contains \"AMAZON WEB SERVICES\" | Software Subscriptions | |\n| Stripe Payouts | Description contains \"STRIPE\" + Money In | Services Revenue | |\n| Payroll - Gusto | Description contains \"GUSTO\" | Payroll Expenses | |\n| Rent | Description contains \"ACH RENT\" | Rent or Lease | |\n| Google Ads | Description contains \"GOOGLE ADS\" | Advertising & Marketing | |\n| Bank Fee | Description contains \"SERVICE FEE\" | Bank Charges & Fees | |\n| Owner Draw | Description contains \"OWNER DRAW\" | Owner's Draw | Equity |\n\n### Split Rule Example (Mixed Expense)\n\n- Rule: \"Office & Meals Split\"\n- Condition: Payee is `Costco`\n- Split:\n  - 60% → Office Supplies (6050)\n  - 40% → Meals & Entertainment (6040)\n\n---\n\n## 3. Recurring Transaction Templates\n\n### Recurring Bill Template (API)\n\n```python\ndef create_recurring_transaction(access_token, realm_id):\n    \"\"\"Create a monthly recurring bill template.\"\"\"\n    payload = {\n        \"RecurDataRef\": {\n            \"type\": \"Bill\",\n        },\n        \"RecurType\": \"Scheduled\",\n        \"ScheduleInfo\": {\n            \"StartDate\": \"2026-01-01\",\n            \"NextDate\": \"2026-04-01\",\n            \"EndDate\": None,\n            \"NumRemaining\": None,\n            \"RecurFrequency\": \"Monthly\",\n            \"IntervalType\": \"Monthly\",\n            \"MaxOccurrences\": None\n        },\n        \"Name\": \"Monthly Rent - 123 Main St\",\n        \"Active\": True,\n        \"VendorRef\": {\"value\": \"VENDOR_ID_HERE\"},\n        \"Line\": [\n            {\n                \"DetailType\": \"AccountBasedExpenseLineDetail\",\n                \"Amount\": 3500.00,\n                \"AccountBasedExpenseLineDetail\": {\n                    \"AccountRef\": {\"value\": \"ACCOUNT_ID_FOR_RENT\"}\n                }\n            }\n        ]\n    }\n    resp = requests.post(\n        f\"https://quickbooks.api.intuit.com/v3/company/{realm_id}/recurringtransaction\",\n        headers={\n            \"Authorization\": f\"Bearer {access_token}\",\n            \"Content-Type\": \"application/json\",\n            \"Accept\": \"application/json\"\n        },\n        json=payload\n    )\n    return resp.json()\n```\n\n### Common Recurring Templates\n\n| Template | Type | Frequency | Amount | Account |\n|----------|------|-----------|--------|---------|\n| Office Rent | Bill | Monthly | Fixed | Rent or Lease |\n| AWS | Bill | Monthly | Variable | Software Subscriptions |\n| Liability Insurance | Bill | Monthly | Fixed | Insurance |\n| Owner's Draw | Check | Bi-weekly | Fixed | Owner's Draw |\n| Depreciation Entry | Journal Entry | Monthly | Calculated | Depreciation |\n\n### Depreciation Journal Entry (Straight-Line)\n\nMonthly entry template:\n```\nDEBIT  Depreciation Expense (6300)    $[amount]\nCREDIT Accumulated Depreciation (1510) $[amount]\nMemo: Monthly depreciation - [asset name]\n```\n\n---\n\n## 4. Reconciliation Workflows\n\n### Monthly Reconciliation Checklist\n\n1. **Gather statements** — Download bank/CC statements for the period\n2. **Review unreviewed transactions** — Banking > For Review; categorize all\n3. **Run reconciliation** — Accounting > Reconcile > select account\n4. **Match ending balance** to bank statement\n5. **Investigate discrepancies**:\n   - Duplicate transactions\n   - Missing transactions (manually add)\n   - Wrong amounts (edit/split)\n   - Timing differences (outstanding checks/deposits)\n6. **Finish reconciliation** — generate reconciliation report\n7. **Document** — save PDF of reconciliation report\n\n### Reconciliation Discrepancy Quick-Fix Guide\n\n| Discrepancy | Likely Cause | Fix |\n|-------------|--------------|-----|\n| $X off exactly | Transposition error | Search for transposed digits |\n| Amount doubled | Duplicate import | Delete duplicate |\n| Amount missing | Manual transaction needed | Add from source doc |\n| Off by fraction | Rounding | Check bank rounding rules |\n| Persistent gap | Beginning balance wrong | Correct prior period |\n\n### API: Fetch Unreconciled Transactions\n\n```python\ndef get_unreconciled_transactions(access_token, realm_id, account_id, start_date, end_date):\n    \"\"\"Query unreconciled transactions for reconciliation.\"\"\"\n    query = f\"\"\"\n        SELECT * FROM Purchase\n        WHERE AccountRef = '{account_id}'\n        AND TxnDate >= '{start_date}'\n        AND TxnDate <= '{end_date}'\n        AND Cleared = 'false'\n        ORDERBY TxnDate ASC\n        MAXRESULTS 1000\n    \"\"\"\n    resp = requests.get(\n        f\"https://quickbooks.api.intuit.com/v3/company/{realm_id}/query\",\n        headers={\"Authorization\": f\"Bearer {access_token}\", \"Accept\": \"application/json\"},\n        params={\"query\": query}\n    )\n    return resp.json()\n```\n\n---\n\n## 5. Journal Entry Generation\n\n### Standard Journal Entry Template\n\n```python\ndef create_journal_entry(access_token, realm_id, txn_date, memo, lines):\n    \"\"\"\n    Create a QBO journal entry.\n    \n    lines: list of dicts with keys:\n      - account_id: QBO account ID\n      - posting_type: \"Debit\" or \"Credit\"\n      - amount: float\n      - description: str (optional)\n    \"\"\"\n    line_items = []\n    for i, line in enumerate(lines):\n        line_items.append({\n            \"Id\": str(i + 1),\n            \"Description\": line.get(\"description\", memo),\n            \"Amount\": line[\"amount\"],\n            \"DetailType\": \"JournalEntryLineDetail\",\n            \"JournalEntryLineDetail\": {\n                \"PostingType\": line[\"posting_type\"],\n                \"AccountRef\": {\"value\": line[\"account_id\"]}\n            }\n        })\n    \n    payload = {\n        \"TxnDate\": txn_date,\n        \"PrivateNote\": memo,\n        \"Line\": line_items\n    }\n    \n    resp = requests.post(\n        f\"https://quickbooks.api.intuit.com/v3/company/{realm_id}/journalentry\",\n        headers={\n            \"Authorization\": f\"Bearer {access_token}\",\n            \"Content-Type\": \"application/json\",\n            \"Accept\": \"application/json\"\n        },\n        json=payload\n    )\n    return resp.json()\n\n# Example: Record depreciation\nentry = create_journal_entry(\n    access_token=token,\n    realm_id=realm,\n    txn_date=\"2026-03-31\",\n    memo=\"March 2026 Depreciation\",\n    lines=[\n        {\"account_id\": \"DEPR_EXPENSE_ID\", \"posting_type\": \"Debit\", \"amount\": 250.00},\n        {\"account_id\": \"ACCUM_DEPR_ID\", \"posting_type\": \"Credit\", \"amount\": 250.00}\n    ]\n)\n```\n\n### Common Journal Entry Templates\n\n**Accrued Revenue**\n```\nDEBIT  Accounts Receivable (1100)   $X\nCREDIT Services Revenue (4000)       $X\nMemo: Accrue revenue for [client] - [period]\n```\n\n**Prepaid Expense Recognition**\n```\nDEBIT  Insurance Expense (6030)     $X\nCREDIT Prepaid Insurance (1200)      $X\nMemo: Recognize prepaid insurance - [month]\n```\n\n**Owner Investment**\n```\nDEBIT  Checking Account (1000)      $X\nCREDIT Owner's Equity (3000)         $X\nMemo: Owner capital contribution [date]\n```\n\n**Crypto Asset Purchase (On-Chain)**\n```\nDEBIT  Crypto Assets (1201)         $X   [at cost basis in USD]\nCREDIT Checking Account (1000)       $X\nMemo: Purchased [X ETH] at $[price] on [date] - TxHash: [0x...]\n```\n\n---\n\n## 6. Reporting & Queries\n\n### Useful QBO Queries (SQL-like)\n\n```python\ndef run_qbo_query(access_token, realm_id, sql):\n    resp = requests.get(\n        f\"https://quickbooks.api.intuit.com/v3/company/{realm_id}/query\",\n        headers={\"Authorization\": f\"Bearer {access_token}\", \"Accept\": \"application/json\"},\n        params={\"query\": sql}\n    )\n    return resp.json()\n\n# Trial Balance components - fetch all accounts with balances\naccounts = run_qbo_query(token, realm,\n    \"SELECT * FROM Account WHERE CurrentBalance != '0' ORDERBY AccountType ASC MAXRESULTS 200\"\n)\n\n# Unpaid invoices (AR aging)\nar = run_qbo_query(token, realm,\n    \"SELECT * FROM Invoice WHERE Balance > '0' ORDERBY DueDate ASC MAXRESULTS 200\"\n)\n\n# Monthly P&L check — all transactions this month\ntxns = run_qbo_query(token, realm,\n    \"SELECT * FROM Transaction WHERE TxnDate >= '2026-03-01' ORDERBY TxnDate ASC MAXRESULTS 1000\"\n)\n```\n\n---\n\n## Negative Boundaries — When NOT to Use This Skill\n\n- **Tax filing** — use `qbo-to-tax-bridge` for IRS schedule mapping and tax workpaper generation\n- **Payroll processing** — QBO Payroll and Gusto have dedicated APIs; this skill doesn't cover payroll runs or W-2/1099 filing\n- **OAuth setup** — Getting QBO Client ID/Secret and initial token exchange requires a separate auth flow; this skill assumes credentials already exist\n- **Multi-entity consolidations** — Each QBO realm is separate; consolidation across entities requires a dedicated reporting layer\n- **Audit-level assurance** — This produces bookkeeping outputs; CPA review and sign-off are required for audit-level work\n- **Non-QBO accounting software** — Xero, FreshBooks, Wave, Sage have different APIs; this skill is QBO-specific\n- **Real-time inventory management** — QBO inventory has limitations; dedicated WMS systems (Fishbowl, etc.) are better for complex inventory\n\n---\n\n## Environment Variables Reference\n\n```bash\nexport QBO_CLIENT_ID=\"your_client_id\"\nexport QBO_CLIENT_SECRET=\"your_client_secret\"\nexport QBO_REFRESH_TOKEN=\"your_refresh_token\"\nexport QBO_REALM_ID=\"your_company_id\"\n\n# Sandbox vs Production\nexport QBO_BASE_URL=\"https://quickbooks.api.intuit.com\"  # Production\n# export QBO_BASE_URL=\"https://sandbox-quickbooks.api.intuit.com\"  # Sandbox\n```\n\n---\n\n## Quick Reference — QBO Account Types & Sub-Types\n\n| Account Type | Common Sub-Types |\n|---|---|\n| Bank | Checking, Savings, MoneyMarket |\n| Accounts Receivable | AccountsReceivable |\n| Other Current Asset | Prepaid Expenses, UndepositedFunds |\n| Fixed Asset | Machinery, FurnitureAndFixtures, Vehicles |\n| Accounts Payable | AccountsPayable |\n| Credit Card | CreditCard |\n| Other Current Liability | DirectDepositPayable, SalesTaxPayable |\n| Long Term Liability | NotesPayable, OtherLongTermLiabilities |\n| Equity | OpeningBalanceEquity, OwnersEquity, RetainedEarnings |\n| Income | SalesOfProductIncome, ServiceFeeIncome |\n| Cost of Goods Sold | SuppliesMaterialsCogs |\n| Expense | AdvertisingPromotional, Insurance, RentOrLeaseOfBuildings |\n| Other Income | OtherMiscellaneousIncome |\n| Other Expense | Depreciation, OtherMiscellaneousExpense |\n","tags":{"latest":"98.0.1"},"stats":{"comments":0,"downloads":751,"installsAllTime":1,"installsCurrent":1,"stars":0,"versions":3},"createdAt":1773648925278,"updatedAt":1779078273360},"latestVersion":{"version":"98.0.1","createdAt":1773724970048,"changelog":"Corrected display name","license":"MIT-0"},"metadata":{"setup":[],"os":null,"systems":null},"owner":{"handle":"samledger67-dotcom","userId":"s17e6161jqcyaq82bkvewk1rz583ndyf","displayName":"samledger67-dotcom","image":"https://avatars.githubusercontent.com/u/261800271?v=4"},"moderation":{"isSuspicious":false,"isMalwareBlocked":false,"verdict":"clean","reasonCodes":["review.llm_review"],"summary":"Review: review.llm_review","engineVersion":"v2.4.24","updatedAt":1780089924954}}