# Business Lending with the Accounting API

Underwriting a business loan or line of credit means reading a borrower's books: balance sheet, profit and loss, working capital trends, and the aging of what they are owed and what they owe. This guide shows how to pull those reports from a borrower's accounting system through Apideck's [Accounting API](/apis/accounting/reference), covering QuickBooks, Xero, NetSuite, Sage Intacct, Exact Online, and the long tail of regional and vertical ERPs lenders encounter in the wild.

## Why a Unified API

Borrowers do not all run QuickBooks. A lender that hard-codes one connector loses every applicant on Xero, NetSuite, or a regional system, and writing a separate ingestion pipeline per ERP burns engineering time that does not move underwriting accuracy.

- One OAuth flow through Apideck Vault handles every supported ERP.
- One JSON shape for the balance sheet, P&L, and aged reports across connectors.
- Native bucketing from the source system, so partial payments and time-zone effects do not have to be reconciled in the lender's pipeline.
- One pull cadence and one webhook surface to keep underwriting models fresh.

## Resource mapping

| Underwriting input | Apideck resource | Endpoint |
| --- | --- | --- |
| Balance sheet | Balance Sheet | [`GET /accounting/balance-sheet`](/apis/accounting/reference#operation/balanceSheetOne) |
| Profit and loss | Profit and Loss | [`GET /accounting/profit-and-loss`](/apis/accounting/reference#operation/profitAndLossOne) |
| Aged receivables | Aged Debtors | [`GET /accounting/aged-debtors`](/apis/accounting/reference#operation/agedDebtorsOne) |
| Aged payables | Aged Creditors | [`GET /accounting/aged-creditors`](/apis/accounting/reference#operation/agedCreditorsOne) |
| Operating cash movement | Payments + Bill Payments | [`GET /accounting/payments`](/apis/accounting/reference#operation/paymentsAll), [`GET /accounting/bill-payments`](/apis/accounting/reference#operation/billPaymentsAll) |
| Revenue line detail | Invoices | [`GET /accounting/invoices`](/apis/accounting/reference#operation/invoicesAll) |
| Cost detail | Bills | [`GET /accounting/bills`](/apis/accounting/reference#operation/billsAll) |
| Trial balance fallback | Journal Entries + Ledger Accounts | [`GET /accounting/journal-entries`](/apis/accounting/reference#operation/journalEntriesAll) |

>
> There is no unified cash flow statement endpoint. For most lending models, the operating cash signal comes from `payments` and `bill-payments` against the company's bank ledger accounts, plus the period-over-period change in cash on the balance sheet. Pull the dedicated reports first, then fall back to transaction-level data when the connector does not expose them.

## Walkthrough

The flow below assumes the borrower has already connected their accounting system through Apideck Vault and that you have stored the resulting `consumer_id`. Replace the service ID in `x-apideck-service-id` with the connector the borrower selected. The dedicated report endpoints in this walkthrough are read-only across every connector that exposes them, which is the right shape for an underwriting pull.

### 1. Pull the balance sheet

The balance sheet anchors leverage and liquidity ratios: current assets versus current liabilities, total debt versus equity, and the asset base available as collateral. Hit the dedicated endpoint rather than re-aggregating ledger accounts so the response reflects the source system's own classification of current versus non-current.

Send this to [`GET /accounting/balance-sheet`](/apis/accounting/reference#operation/balanceSheetOne).

```bash
curl -G https://unify.apideck.com/accounting/balance-sheet \
  -H "Authorization: Bearer ${APIDECK_API_KEY}" \
  -H "x-apideck-app-id: ${APIDECK_APP_ID}" \
  -H "x-apideck-consumer-id: borrower_01H8X9Y2A3K4M5N6P7Q8R9S0TU" \
  -H "x-apideck-service-id: quickbooks" \
  --data-urlencode "filter[start_date]=2024-01-01" \
  --data-urlencode "filter[end_date]=2024-12-31"
```

A trimmed response looks like this:

```json
{
  "data": {
    "id": "bs_2024_fy",
    "currency": "USD",
    "start_date": "2024-01-01",
    "end_date": "2024-12-31",
    "assets": {
      "total": 1842500.42,
      "current_assets": {
        "total": 612300.18,
        "items": [
          { "account_id": "acct_01H8X9Y2A3CASH", "name": "Operating Checking", "value": 184200.55 },
          { "account_id": "acct_01H8X9Y2A3AR", "name": "Accounts Receivable", "value": 348100.00 },
          { "account_id": "acct_01H8X9Y2A3INV", "name": "Inventory", "value": 79999.63 }
        ]
      },
      "fixed_assets": {
        "total": 1230200.24,
        "items": [
          { "account_id": "acct_01H8X9Y2A3PPE", "name": "Equipment, net", "value": 1230200.24 }
        ]
      }
    },
    "liabilities": {
      "total": 985400.10,
      "current_liabilities": {
        "total": 312800.10,
        "items": [
          { "account_id": "acct_01H8X9Y2A3AP", "name": "Accounts Payable", "value": 198500.00 },
          { "account_id": "acct_01H8X9Y2A3CC", "name": "Credit Card Payable", "value": 114300.10 }
        ]
      },
      "long_term_liabilities": {
        "total": 672600.00,
        "items": [
          { "account_id": "acct_01H8X9Y2A3LOAN", "name": "SBA Term Loan", "value": 672600.00 }
        ]
      }
    },
    "equity": {
      "total": 857100.32,
      "items": [
        { "account_id": "acct_01H8X9Y2A3RE", "name": "Retained Earnings", "value": 612400.32 },
        { "account_id": "acct_01H8X9Y2A3CS", "name": "Common Stock", "value": 244700.00 }
      ]
    }
  }
}
```

### 2. Pull the profit and loss

The P&L drives revenue trend, gross margin, and EBITDA approximations. Pull it on the same period as the balance sheet plus the prior comparable period, so the model has year-over-year deltas.

Send this to [`GET /accounting/profit-and-loss`](/apis/accounting/reference#operation/profitAndLossOne).

```bash
curl -G https://unify.apideck.com/accounting/profit-and-loss \
  -H "Authorization: Bearer ${APIDECK_API_KEY}" \
  -H "x-apideck-app-id: ${APIDECK_APP_ID}" \
  -H "x-apideck-consumer-id: borrower_01H8X9Y2A3K4M5N6P7Q8R9S0TU" \
  -H "x-apideck-service-id: xero" \
  --data-urlencode "filter[start_date]=2024-01-01" \
  --data-urlencode "filter[end_date]=2024-12-31"
```

Trimmed response:

```json
{
  "data": {
    "id": "pnl_2024_fy",
    "currency": "USD",
    "start_date": "2024-01-01",
    "end_date": "2024-12-31",
    "income": {
      "total": 4820100.00,
      "records": [
        { "account_id": "acct_01H8X9Y2A3REV", "name": "Product Revenue", "value": 4120100.00 },
        { "account_id": "acct_01H8X9Y2A3SVC", "name": "Service Revenue", "value": 700000.00 }
      ]
    },
    "cost_of_goods_sold": {
      "total": 2410050.00,
      "records": [
        { "account_id": "acct_01H8X9Y2A3COGS", "name": "Cost of Goods Sold", "value": 2410050.00 }
      ]
    },
    "gross_profit": 2410050.00,
    "expenses": {
      "total": 1689400.00,
      "records": [
        { "account_id": "acct_01H8X9Y2A3PAY", "name": "Payroll", "value": 1240000.00 },
        { "account_id": "acct_01H8X9Y2A3RNT", "name": "Rent", "value": 240000.00 },
        { "account_id": "acct_01H8X9Y2A3MKT", "name": "Marketing", "value": 209400.00 }
      ]
    },
    "net_income": 720650.00
  }
}
```

### 3. Pull aged receivables and payables

Aging buckets show how reliably the borrower collects and pays. The dedicated endpoints return the source system's native bucket boundaries (commonly Current, 1-30, 31-60, 61-90, 90+), so the underwriting model does not have to recompute them from invoice and payment dates.

Send this to [`GET /accounting/aged-debtors`](/apis/accounting/reference#operation/agedDebtorsOne).

```json
{
  "data": {
    "id": "ar_aging_2024_12_31",
    "report_date": "2024-12-31",
    "currency": "USD",
    "outstanding_balances": [
      {
        "customer_id": "cust_01H8X9Y2A3ACME",
        "customer_name": "Acme Robotics LLC",
        "balances": [
          { "period": "Current", "total_amount": 18400.00 },
          { "period": "1 - 30", "total_amount": 7200.00 },
          { "period": "31 - 60", "total_amount": 0.00 },
          { "period": "61 - 90", "total_amount": 0.00 },
          { "period": "91 and above", "total_amount": 0.00 }
        ]
      },
      {
        "customer_id": "cust_01H8X9Y2A3OASIS",
        "customer_name": "Oasis Distributing Co.",
        "balances": [
          { "period": "Current", "total_amount": 0.00 },
          { "period": "1 - 30", "total_amount": 12500.00 },
          { "period": "31 - 60", "total_amount": 12500.00 },
          { "period": "61 - 90", "total_amount": 6300.00 },
          { "period": "91 and above", "total_amount": 0.00 }
        ]
      }
    ]
  }
}
```

The mirror call for payables is [`GET /accounting/aged-creditors`](/apis/accounting/reference#operation/agedCreditorsOne) and returns the same shape keyed by supplier. Concentration ratios (top customer or top supplier as a share of the total) fall out of these responses directly.

### 4. Reconstruct cash movement

There is no unified cash flow statement, so for connectors that need it derived, pull customer receipts and supplier disbursements over the underwriting window and net them against the cash and credit-card ledger accounts.

```bash
curl -G https://unify.apideck.com/accounting/payments \
  -H "Authorization: Bearer ${APIDECK_API_KEY}" \
  -H "x-apideck-app-id: ${APIDECK_APP_ID}" \
  -H "x-apideck-consumer-id: borrower_01H8X9Y2A3K4M5N6P7Q8R9S0TU" \
  -H "x-apideck-service-id: xero" \
  --data-urlencode "filter[updated_since]=2024-01-01T00:00:00Z"
```

Pair this with [`GET /accounting/bill-payments`](/apis/accounting/reference#operation/billPaymentsAll) to capture supplier cash out, and use the cash and credit-card balances from the balance sheet at period start and period end to validate the net movement.

### 5. Pull line-level detail when needed

After the dedicated reports, drill into [`GET /accounting/invoices`](/apis/accounting/reference#operation/invoicesAll) and [`GET /accounting/bills`](/apis/accounting/reference#operation/billsAll) for line-item detail (customer concentration, COGS structure, recurring revenue identification). Page with `limit` and `cursor` and filter with `filter[updated_since]` to keep the post-funding monitoring sync incremental.

## Connector-specific behavior

The notes below reflect each connector's coverage of the resources most relevant to underwriting (balance sheet, profit and loss, invoices, bills, payments, journal entries, ledger accounts). Where the dedicated reports are not exposed, derive the equivalent figures from journal entries and ledger accounts only when those are themselves in coverage; otherwise, mark the connector as a partial input and pair it with another data source.

| Connector | Notes |
| --- | --- |
| `access-financials` | No balance sheet or P&L endpoint. Invoices, credit notes, payments, suppliers, and customers are available; ledger accounts are read-only. Derive financial position from ledger account balances rather than journal entries. |
| `acumatica` | No balance sheet or P&L endpoint. Strong transaction coverage (bills, invoices, journal entries, ledger accounts, payments, purchase orders). Derive reports from journals. |
| `banqup` | Read-only on customers and invoices; bills, payments, journal entries, and ledger accounts are not in coverage. Insufficient on its own for full underwriting; combine with bank statement data. |
| `campfire` | Balance sheet and P&L exposed read-only. Bill payments and payments coverage is limited, so cash movement is best reconstructed from journal entries (read+write) and ledger accounts. |
| `clearbooks-uk` | No balance sheet or P&L endpoint, and journal entries are not in coverage. Bills, credit notes, customers, invoices, and suppliers are read-only. Limited utility for full underwriting; verify against the coverage matrix before relying on it. |
| `digits` | Balance sheet and P&L are read-only and well-supported. Transaction-level resources are largely read-only or absent, so this connector is best used for report ingestion only. |
| `dualentry` | No balance sheet or P&L endpoint. Broad coverage including bills, invoices, payments, journal entries, and credit notes. Derive reports from journals. |
| `exact-online` | Balance sheet and P&L are read-only. Bills, invoices, journal entries, and payments are supported. Reports are returned in the entity's reporting currency. |
| `exact-online-nl` | Same coverage as `exact-online`. Tax rate detail follows Dutch BTW conventions. |
| `exact-online-uk` | Same report coverage as `exact-online`. Bills are read-only on this variant, so payable aging should come from `aged-creditors` rather than aggregating bills. |
| `freeagent` | Balance sheet and P&L exposed read-only. Bills are read-only, payments are not in coverage, and journal entries are read-only. Suitable for read-only underwriting flows. |
| `freshbooks` | Balance sheet and P&L are read-only. Strong invoice, bill, payment, and supplier coverage. Common for service-business borrowers. |
| `intuit-enterprise-suite` | Balance sheet and P&L are read-only and the broader resource surface (bills, invoices, journal entries, departments, locations, tracking categories) is read+write. Use multi-dimensional filters to underwrite specific business units. |
| `kashflow` | No balance sheet or P&L endpoint. Most resources are read-only, including journal entries and ledger accounts. Derive aggregates from those reads. |
| `microsoft-dynamics-365-business-central` | No balance sheet or P&L endpoint. Strong write coverage on bills, invoices, journal entries, and purchase orders; ledger accounts and payments are read-only. Derive reports from journal entries grouped by ledger account. |
| `moneybird` | No balance sheet or P&L endpoint. Bills, invoices, journal entries, and tracking categories are supported. Derive aggregates from journals. |
| `mrisoftware` | No balance sheet or P&L endpoint. Bills, journal entries, and suppliers are read+write; customers, ledger accounts, and most other underwriting resources are read-only or not in coverage. Common in real-estate and property-management lending. |
| `myob` | No balance sheet or P&L endpoint, and journal entries and bills are not in coverage. Customers, invoices, and ledger accounts are read+write. Coverage of underwriting resources is limited; expect to fall back to ledger accounts. |
| `myob-acumatica` | No balance sheet or P&L endpoint. Strong coverage across bills, invoices, credit notes, journal entries, and purchase orders. Derive reports from journals. |
| `netsuite` | Balance sheet and P&L are read-only. Subsidiaries are read+write; departments, classes, and locations are read-only. Pass `subsidiary_id` via `pass_through` or `filter` to scope reports to a single legal entity in multi-subsidiary borrowers. |
| `odoo` | No balance sheet or P&L endpoint. Bills, invoices, and journal entries are read+write; ledger accounts are read-only. Derive reports from journals. |
| `pennylane` | No balance sheet or P&L endpoint. Bills, invoices, and journal entries are supported; bill-payments are not in coverage. Common for French SMB borrowers. |
| `procountor-fi` | No balance sheet or P&L endpoint. Bills, invoices, journal entries, and purchase orders are supported; payments are read-only. Reports must be derived from ledger postings. |
| `quickbooks` | Balance sheet and P&L are read-only. The most common borrower system in the US SMB segment. Departments, locations, and tracking categories (classes) are available read+write for segment-level underwriting. |
| `rillet` | Balance sheet and P&L are read-only. Bills, invoices, and journal entries are read+write; ledger accounts are read-only. |
| `sage-business-cloud-accounting` | Balance sheet and P&L are read-only. Journal entries are read-only, so cash flow reconstruction relies on `payments` and `bill-payments`. |
| `sage-intacct` | Balance sheet and P&L are read-only. Tracking categories are read+write; subsidiaries, departments, and locations are read-only. Useful for multi-entity underwriting. |
| `sage-intacct-rest` | Limited or no coverage across underwriting resources; verify in the coverage matrix. Use `sage-intacct` where possible for borrower onboarding. |
| `stripe` | No balance sheet or P&L endpoint. Useful as a revenue and customer-payment source for borrowers whose primary book of record lives in Stripe (e.g. SaaS), but combine with a true ledger system for full underwriting. |
| `visma-netvisor` | No balance sheet or P&L endpoint. Bills, invoices, payments, and purchase orders are supported; journal entries are read-only and ledger accounts are not in coverage. |
| `wave` | Balance sheet and P&L are read-only. Invoices and ledger accounts are supported; bills and payments are not in coverage. |
| `workday` | No balance sheet or P&L endpoint. Strong coverage of bills, invoices, journal entries, expenses, and payments. Derive reports from journals; common for larger borrowers. |
| `xero` | Balance sheet and P&L are read-only. Tracking categories (read-only) carry departmental detail. Aged debtors and aged creditors return Xero's native bucket boundaries. |
| `yuki` | No balance sheet or P&L endpoint. Invoices and journal entries are supported; ledger accounts are read-only. Derive aggregates from journals. |
| `zoho-books` | No balance sheet or P&L endpoint. Strong coverage across bills, invoices, journal entries, payments, and purchase orders. Derive reports from journal entries. |

### NetSuite

For multi-subsidiary borrowers, request the report once per subsidiary identified through [`GET /accounting/subsidiaries`](/apis/accounting/reference#operation/subsidiariesAll) and consolidate on your side, or rely on the parent's consolidation if the borrower already books at the parent level. NetSuite's department, class, and location dimensions can be used to scope the P&L to a specific operating segment when the loan is asset-backed against that segment.

### Sage Intacct

Sage Intacct supports the full report set as read-only and exposes subsidiaries, departments, and locations (read-only) along with tracking categories (read+write). For entity-level underwriting in multi-entity tenants, scope each report request to a single entity rather than relying on consolidations that may include intercompany eliminations the model does not need to see.

### QuickBooks and Intuit Enterprise Suite

Both connectors expose departments, locations, and classes via tracking categories. For franchise or multi-location borrowers, segment the P&L by location to underwrite a single store rather than the whole company.

### Connectors without dedicated reports

For connectors without `balance-sheet` and `profit-and-loss`, build a derivation step:

1. Pull [`GET /accounting/ledger-accounts`](/apis/accounting/reference#operation/ledgerAccountsAll) to get the chart of accounts and each account's `classification` (asset, liability, equity, income, expense).
2. Pull [`GET /accounting/journal-entries`](/apis/accounting/reference#operation/journalEntriesAll) for the period, summing debits and credits per account.
3. Group by classification to produce a balance sheet at period end and a P&L over the period.

The trade-off: derived reports do not always match the borrower's own report run inside the ERP, because the source system may apply elimination or rounding rules the unified model does not surface. When the ERP exposes its own report endpoint, prefer it. When journal entries or ledger accounts are themselves not in coverage for a given connector, this derivation is not viable and the connector should be paired with an external data source.

## Next steps

- [Mark Invoices and Bills as Paid](/guides/mark-invoices-as-paid) for understanding how settled status flows back into the receivables and payables you pull.
- [Handling Bills and Expenses](/guides/expenses-bills) for cost-side data modeling.
- [Accounting API reference](/apis/accounting/reference) for the full resource and filter surface.
- [Webhooks reference](/apis/webhook/reference) to keep post-funding monitoring sync incremental rather than full-refresh.
