Skip to content
Desktop Accounting API

Reports

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.

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.

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(" | "));
}
}

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.

{
"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.

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.