Skip to content

Reports

Generate financial reports as files (Excel by default; CSV, PDF or HTML on request). Generation runs in the background; finished reports are stored and downloadable through the API.

Available Reports

GET /api/v1/reports/types returns the full, current list. Each item has report_name, title, description, input_type (which tells you which request fields it needs) and requires_cfo_suite. Commonly used report_name values:

report_name Description Inputs
master_transactions All transactions across accounts start_date, end_date
journal_entry_report / audit_trail Journal entries and change history start_date, end_date
categorization_review Flagged transactions for the period: uncategorized, likely miscategorized, unpaired transfers start_date, end_date (optional additional_params.period)
close_verification Month-end exceptions: uncategorized, miscategorized, unpaired transfers, unmatched deposits, manual JEs start_date, end_date
trial_balance Debits/credits verification start_date, end_date (optional additional_params.include_zero_balances)
aged_trial_balance Trial balance with aging buckets end_date
general_ledger Transactions per account (optionally one ledger_id) start_date, end_date
chart_of_accounts Complete account listing none
profit_and_loss Income statement start_date, end_date
profit_and_loss_comparative P&L vs. a comparison period dates + comparison_* fields
income_statement_periodic / income_statement_details Month/quarter/year income statement; transaction-level P&L detail dates (periodic also takes additional_params.grouping: monthly, quarterly or yearly)
pnl_by_customer / pnl_by_department P&L segmented by customer or tag dates + additional_params.customer_id / tag_group_id, tag_ids
balance_sheet Assets, liabilities, equity as of a date end_date
balance_sheet_comparative Balance sheet vs. a comparison date end_date + comparison_end_date
balance_sheet_monthly Month-by-month balance sheet start_date, end_date
retained_earnings / statement_of_owners_equity / shareholder_loans Equity roll-forwards and shareholder loan tracking start_date, end_date
cash_flow_statement / cash_flow_periodic / cash_flow_forecast Cash flow, historical, by period, or projected start_date, end_date; forecast takes additional_params.forecast_days (default 90)
ar_report / ap_report Invoice and bill summaries with aging none
bills_pending_approval Bills waiting in the approval queue none
unpaid_ar_as_of / unpaid_ap_as_of Open receivables / payables at a date end_date
customer_statements / vendor_statements Statements per customer or vendor dates + additional_params.customer_id / vendor_id
customer_cash_receipts Bank deposits applied to receivables, by customer and quarter start_date, end_date
tax_summary, report_1099, check_register, bank_reconciliation Compliance and banking start_date, end_date
budget_vs_actual Budget vs. actual (optional additional_params.budget_id) start_date, end_date
expense_by_category, sales_report, cogs_report, payroll_summary, subscription_costs, fixed_assets_depreciation Operational reports start_date, end_date
inventory_by_location, products_report Inventory and product exports none
unrealized_fx_gain_loss, intercompany_reconciliation Multi-currency and intercompany end_date
financial_ratios, financial_summary_dashboard, saas_metrics, quality_of_earnings CFO analytics start_date, end_date
working_capital Current assets vs. liabilities end_date
deferred_revenue_waterfall Deferred revenue roll-forward dates + additional_params.grouping
dashboard_export, transactions_export, bespoke_document Saved-dashboard export, Transactions table workbook (xlsx only, 10,000 rows max), AI-built custom document see /reports/types

These report_name values require the CFO Suite add-on and return 403 without it: profit_and_loss_comparative, income_statement_periodic, income_statement_details, pnl_by_customer, pnl_by_department, balance_sheet_comparative, balance_sheet_monthly, cash_flow_periodic, cash_flow_forecast, financial_ratios, financial_summary_dashboard, budget_vs_actual, working_capital, retained_earnings, shareholder_loans, report_1099 and subscription_costs. An unknown report_name is a 400.

Generate a Report

bash
curl -X POST "https://api.ondayzero.com/api/v1/reports" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "report_name": "profit_and_loss",
    "start_date": "2026-01-01",
    "end_date": "2026-03-31",
    "output_format": "pdf"
  }'
Field Description
report_name Required. One of the names from /reports/types
period_type custom (default — use start_date/end_date), tax_year or tax_quarter (use tax_year and tax_quarter; dates are derived from the business's fiscal year end)
start_date / end_date YYYY-MM-DD. Point-in-time reports need only end_date
output_format xlsx (default), csv, html, pdf
comparison_period_type, comparison_start_date / comparison_end_date, comparison_tax_year / comparison_tax_quarter Prior period for *_comparative reports
ledger_id, tag_group_id, tag_ids Narrow general_ledger to one account, or segment pnl_by_department; tag_ids also filters profit_and_loss, the periodic and comparative income statements and the financial summary
additional_params Report-specific options, e.g. {"customer_id": "…"} for customer_statements or pnl_by_customer, {"vendor_id": "…"} for vendor_statements
additional_params.basis accrual or cash for the income statement, balance sheet, cash flow, trial balance, general ledger and most analysis reports. Omitted means the business's configured default, which may be cash. Any other value is a 400. The file states the basis it was built on
additional_params.include_period_columns true adds "Quarter Ending" and "Calendar Year Ending" columns after every date column
instance_id Legacy ledger-engine instance override; normally omit
file_s3_key / s3_keys Input files for upload-driven reports (see File Uploads)

The response is 202 Accepted:

json
{
  "success": true,
  "data": {
    "task_id": "report-generation-…-profit_and_loss-start-2026-01-01-end-2026-03-31",
    "status": "queued",
    "report_name": "profit_and_loss",
    "business_id": "…",
    "message": "Report generation queued successfully with Temporal",
    "executor": "temporal"
  }
}

status is queued, or in_progress if an identical report is already being generated (the request is de-duplicated rather than run twice). The task_id is deterministic for the same report name, period and parameters.

Retrieve the Finished Report

Either poll the task with GET /api/v1/tasks/task/{task_id} (the response status becomes SUCCESS and result carries the s3_key and a download_link; an unknown task returns HTTP 200 with status: NOT_FOUND), or poll the report list — the newest reports come first — until one with your report_name and period appears:

bash
curl "https://api.ondayzero.com/api/v1/reports?limit=5" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

Each report has id, report_name, generation_params (the request you sent, with dates resolved, so you can match it), s3_key, created_at, downloaded_at, generated_by_name and a download_url. GET /api/v1/reports/{report_id} fetches one by ID. Add client_visible_only=true to the list to see only reports shared with clients.

Download

download_url points at GET /api/v1/reports/download?s3_key=… — a same-origin endpoint that validates ownership, records the download, and then 307-redirects to a short-lived presigned S3 URL (falling back to streaming the file itself). Send the usual Authorization and x-business-id headers and follow redirects:

bash
curl -L -o pnl-q1.pdf "https://api.ondayzero.com/api/v1/reports/download?s3_key=reports/YOUR_BUSINESS_ID/profit_and_loss_2026-01-01_2026-03-31.pdf" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

Add inline=true to get a Content-Disposition: inline response for viewing in a browser, or filename=… to rename the download. DELETE /api/v1/reports/{report_id} removes a stored report and its file.

To preview a stored PDF, Excel or PowerPoint file as images, GET /api/v1/reports/preview-info?s3_key=… returns available and page_count (up to 20 pages), and GET /api/v1/reports/preview-page?s3_key=…&page=1 returns that page as a PNG.

  • GET /api/v1/reports/subledger-gl-reconciliation — checks that the AR/AP sub-ledgers agree with the general ledger control accounts. Takes as_of_date (YYYY-MM-DD, default today) and parent_ledger_id (reconcile only that control account and its sub-ledgers; a liability account is read as the payables side). The ar and ap sections hold the totals in cents (open documents minus GL balance) and rows, largest difference first, hold one entry per customer (AR) or vendor (AP), plus one for lines that cannot be attributed to anyone. Each row has kind, customer_or_vendor, party_id (null when unattributed), subledger_balance_cents (the party's GL balance), open_documents_cents, difference_cents (GL balance minus open documents, the opposite sign to the section totals) and explanations: tagged causes (fee_shortfall, unapplied_credit, unposted_payment, rounding), each with an amount and whether it accounts for the difference. A manual journal entry posted straight to AR or AP carries no tag and shows as an unexplained difference. As-of figures are approximate for documents voided or written off after the date, because statuses are not historized. The MCP tool is get_subledger_gl_reconciliation.
  • POST /api/v1/reports/suggest — AI suggestions for which reports are worth running given recent activity.
  • GET /api/v1/reports/import-templates — CSV templates (and READMEs) for bulk imports of transactions, journal entries and more. import-templates.zip bundles them all; import-templates/{template_key}.csv and .md fetch one template or its README.