# Reports
Source: https://www.desktopaccountingapi.com/docs/quickbooks/reports/

> Run QuickBooks Desktop reports such as profit and loss, balance sheet and aging, and read their rows, columns and subtotals as JSON.

QuickBooks Desktop computes reports itself, with its own accounting rules, on the customer's computer. The report endpoints run those reports and return them as structured JSON, so the numbers you show match what your customer sees in QuickBooks.

## Report families

| Endpoint | Includes, for example |
| --- | --- |
| `GET /v1/quickbooks-desktop/reports/general-summary` | Profit and loss (standard, by class, by job, year-to-date comparison), balance sheet, trial balance, sales by customer or item, income and expense summaries, inventory valuation, sales tax liability |
| `GET /v1/quickbooks-desktop/reports/general-detail` | Transaction detail reports: general ledger, journal, transaction detail by account, open invoices, sales and purchase detail |
| `GET /v1/quickbooks-desktop/reports/aging` | Accounts receivable and payable aging, summary and detail, and the collections report |
| `GET /v1/quickbooks-desktop/reports/budget-summary` | Budget overview and budget versus actual |
| `GET /v1/quickbooks-desktop/reports/job` | Job profitability and estimates versus actuals |
| `GET /v1/quickbooks-desktop/reports/time` | Time by job, by item and by name |
| `GET /v1/quickbooks-desktop/reports/custom-summary` | Custom summary reports you define with rows and columns |
| `GET /v1/quickbooks-desktop/reports/custom-detail` | Custom transaction detail reports |
| `GET /v1/quickbooks-desktop/reports/payroll-summary` | Payroll summaries, when the company uses QuickBooks payroll |
| `GET /v1/quickbooks-desktop/reports/payroll-detail` | Payroll detail, when the company uses QuickBooks payroll |

`reportType` picks the report within a family, for example `profit_and_loss_standard` or `balance_sheet_standard` for general summary, or `ar_aging_summary` for aging. The API reference lists every value.

## Running a report

**TypeScript**

```ts
import { DesktopAccountingApi } from "@desktopaccountingapi/quickbooks-desktop";

const qb = new DesktopAccountingApi().forEndUser("eu_01j9...");

const report = await qb.qbd.reports.generalSummary({
  reportType: "profit_and_loss_standard",
  reportDateMacro: "last_month",
  basis: "accrual",
});

for (const row of report.rows) {
  if (row.kind === "data" || row.kind === "total") {
    console.log(row.rowDescriptor?.value, row.cells.map((c) => c.value).join(" | "));
  }
}
```

**Python**

```python
from desktopaccountingapi import DesktopAccountingApi

qb = DesktopAccountingApi().for_end_user("eu_01j9...")

report = qb.qbd.reports.general_summary(
    report_type="profit_and_loss_standard",
    report_date_macro="last_month",
    basis="accrual",
)

for row in report.rows:
    if row.kind in ("data", "total"):
        print(row.row_descriptor.value if row.row_descriptor else None, [c.value for c in row.cells])
```

**curl**

```sh
curl "https://api.desktopaccountingapi.com/v1/quickbooks-desktop/reports/general-summary?reportType=profit_and_loss_standard&reportDateFrom=2026-09-01&reportDateTo=2026-09-30" \
  -H "Authorization: Bearer $DAAPI_SECRET_KEY" \
  -H "Daapi-End-User-Id: eu_01j9..."
```

Common parameters: `reportDateFrom` / `reportDateTo` or `reportDateMacro` for the period; `basis` (`accrual` or `cash`) where it applies; `summarizeColumnsBy` to split columns by month, quarter, class or customer; filters by account, entity, item, class and transaction type.

## The report object

```json
{
  "objectType": "qbd_report",
  "category": "general_summary",
  "reportType": "profit_and_loss_standard",
  "title": "Profit & Loss",
  "subtitle": "September 2026",
  "basis": "accrual",
  "rowCount": 24,
  "columnCount": 2,
  "columnTitleRowCount": 1,
  "columns": [
    { "columnId": "1", "columnType": "label", "dataType": "strtype", "titles": [{ "rowNumber": 1, "value": null }] },
    { "columnId": "2", "columnType": "amount", "dataType": "amttype", "titles": [{ "rowNumber": 1, "value": "Sep 26" }] }
  ],
  "rows": [
    { "kind": "text", "rowNumber": 1, "text": "Income", "rowDescriptor": null, "cells": [] },
    {
      "kind": "data",
      "rowNumber": 2,
      "text": null,
      "rowDescriptor": { "type": "account", "value": "Sales" },
      "cells": [
        { "columnId": "1", "value": "Sales", "dataType": "strtype" },
        { "columnId": "2", "value": "48210.00", "dataType": "amttype" }
      ]
    },
    {
      "kind": "total",
      "rowNumber": 3,
      "text": null,
      "rowDescriptor": null,
      "cells": [
        { "columnId": "1", "value": "Total Income", "dataType": "strtype" },
        { "columnId": "2", "value": "48210.00", "dataType": "amttype" }
      ]
    }
  ]
}
```

- `columns` describe each column in display order. `titles` holds one entry per title row; multi-row headers (a month above "Actual" and "Budget") have several.
- `rows` come in display order. `kind` is `data` (a line of the report), `text` (a heading, in `text`), `subtotal` or `total`.
- `rowDescriptor` says what a data row describes, such as an account or customer, and its name.
- Every row has every field: a text row has `rowDescriptor: null` and empty `cells`; other rows have `text: null`. The names match Conductor's report rows.
- `cells` hold values keyed by `columnId`. Values are strings, as QuickBooks formats them; `dataType` tells you how to parse each one (`amttype` is an amount, `datetype` a date, `strtype` text, and so on; these are QuickBooks' own type names in lowercase).

Rows are flat. Use the order of `text`, `data`, `subtotal` and `total` rows to rebuild the hierarchy QuickBooks shows, or rely on `rowDescriptor` for the account or name of each data row.

## Performance

Reports run inside QuickBooks on the customer's computer and can take a while on large files, especially detail reports over long periods. Keep date ranges tight, use async mode (`Prefer: respond-async`) for heavy reports, and raise `Daapi-Timeout-Seconds` if you call them synchronously. A report too large to process returns `422 QBD_RESPONSE_TOO_LARGE`; narrow the period or the filters.

Payroll reports need a company that uses QuickBooks payroll. Without it, QuickBooks returns an error that we pass through with its status code.
