{"openapi":"3.1.0","info":{"title":"POST /api/v1/reports","version":"1.0.0","description":"Generate report"},"servers":[{"url":"https://api.ondayzero.com","description":"Production"}],"paths":{"/api/v1/reports":{"post":{"tags":["reports"],"summary":"Generate report","description":"Queue a report for generation and return task ID for tracking.","operationId":"generate_report_api_v1_reports_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-business-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Business-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportCreateRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportTaskResponse"}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"example":{"detail":"Invalid request parameters"}}}},"401":{"description":"Unauthorized - Authentication required","content":{"application/json":{"example":{"detail":"Not authenticated"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"example":{"detail":"Not enough permissions"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ReportCreateRequest":{"properties":{"report_name":{"type":"string","title":"Report Name","description":"Report type identifier. Must match a supported report_name from the /reports endpoint. Examples: 'master_transactions', 'trial_balance', 'general_ledger', 'profit_and_loss_comparative', 'ar_report', 'cogs_report', 'shareholder_loans'. See GET /reports for the complete list of available report types."},"period_type":{"anyOf":[{"$ref":"#/components/schemas/ReportPeriodType"},{"type":"null"}],"description":"Controls how report dates are determined. 'custom' (default): Use start_date/end_date fields directly. 'tax_year': Calculate full fiscal year dates from business's tax_year_end_month config. 'tax_quarter': Calculate quarter dates within a fiscal year. When using tax_year or tax_quarter, the resolved dates will be stored in generation_params.","default":"custom"},"tax_year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tax Year","description":"The tax/fiscal year for period calculation. Required when period_type is 'tax_year' or 'tax_quarter'. Example: 2026. The actual date range depends on the business's tax_year_end_month setting. For a business with tax year ending March 31, tax_year=2026 covers April 1, 2025 through March 31, 2026."},"tax_quarter":{"anyOf":[{"type":"integer","maximum":4.0,"minimum":1.0},{"type":"null"}],"title":"Tax Quarter","description":"The quarter within the tax year (1-4). Required when period_type is 'tax_quarter'. Q1 is the FIRST quarter of the fiscal year, which may start in the prior calendar year for non-calendar fiscal years. Example: For a March fiscal year-end, Q1 of tax_year=2026 covers April 1-June 30, 2025."},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date","description":"Report period start date in YYYY-MM-DD format (e.g., '2026-01-01'). Required when period_type='custom' for reports with input_type='date_start_end' or similar. Ignored when period_type is 'tax_year' or 'tax_quarter' (dates calculated automatically)."},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date","description":"Report period end date in YYYY-MM-DD format (e.g., '2026-12-31'). Required when period_type='custom' for date-range reports. For point-in-time reports (input_type='date_end_only'), only end_date is needed. Ignored when period_type is 'tax_year' or 'tax_quarter'."},"comparison_period_type":{"anyOf":[{"$ref":"#/components/schemas/ReportPeriodType"},{"type":"null"}],"description":"Period type for the comparison/prior period in comparative reports. Same options as period_type: 'custom', 'tax_year', or 'tax_quarter'. Used with reports like 'profit_and_loss_comparative' and 'balance_sheet_comparative' to enable variance analysis between two periods."},"comparison_tax_year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Comparison Tax Year","description":"Tax year for the comparison period. Used when comparison_period_type is 'tax_year' or 'tax_quarter'. Example: Set to 2025 to compare against the current period's 2026 for year-over-year analysis."},"comparison_tax_quarter":{"anyOf":[{"type":"integer","maximum":4.0,"minimum":1.0},{"type":"null"}],"title":"Comparison Tax Quarter","description":"Quarter (1-4) for the comparison period. Required when comparison_period_type is 'tax_quarter'. Example: comparison_tax_quarter=1 with comparison_tax_year=2025 compares Q1 2025 against the current period."},"comparison_start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comparison Start Date","description":"Start date for comparison period in YYYY-MM-DD format. Used when comparison_period_type='custom' for comparative reports. Example: '2025-01-01' to compare against prior year."},"comparison_end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comparison End Date","description":"End date for comparison period in YYYY-MM-DD format. Used when comparison_period_type='custom' for comparative reports. Example: '2025-12-31' to compare full prior year."},"ledger_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ledger Id","description":"UUID of a specific ledger account to filter the report. Currently used with 'general_ledger' report to show transactions for only one account instead of all accounts. When omitted, the general_ledger report includes all accounts. Example: '019ab37c-ledg-7000-8000-000000000001'."},"instance_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instance Id","description":"Teal integration instance ID. Optional - if not specified, uses the business's default Teal instance. Only needed for businesses with multiple Teal instances or when overriding the default. Used for reports that fetch data from Teal (P&L, Balance Sheet)."},"file_s3_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File S3 Key","description":"S3 object key for file-based report inputs. Required for reports with input_type='file_upload' (e.g., 'cogs_report'). The file should be uploaded first via the upload endpoint. Example: 'uploads/business-123/cogs-data-2026.csv'."},"s3_keys":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"S3 Keys","description":"Array of S3 object keys when a report requires multiple input files. Each key should reference a previously uploaded file. Example: ['uploads/business-123/sales-q1.csv', 'uploads/business-123/sales-q2.csv']."},"tag_group_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tag Group Id","description":"UUID of a specific tag group to filter the report. Used with 'pnl_by_department' to segment by tags within this group."},"tag_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tag Ids","description":"List of specific tag UUIDs to filter the report. When multiple tags are provided for 'pnl_by_department', it generates a multi-sheet report with one P&L statement per tag."},"additional_params":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Additional Params","description":"Report-specific parameters that vary by report type. Supported parameters: **customer_id** (UUID): Filter customer_statements or pnl_by_customer to a specific customer. **vendor_id** (UUID): Filter vendor_statements to a specific vendor. **include_zero_balances** (bool): Include zero-balance accounts in trial_balance report. **tag_group_id** (UUID): Filter pnl_by_department to tags in a specific tag group. **forecast_days** (int): Number of days to forecast in cash_flow_forecast (default: 90). **raw** (bool): For general_ledger only — return a single flat sheet with no formatting or headers (default: false). Example: {'customer_id': '019abc-uuid', 'include_zero_balances': true}."},"output_format":{"$ref":"#/components/schemas/ReportOutputFormat","description":"Output file format for the report. 'xlsx' (default): Excel format with formatting, multiple tabs, headers, and currency formatting. 'csv': Comma-separated values format as a single flat file without formatting. CSV is useful for importing into other systems or programmatic analysis.","default":"xlsx"}},"type":"object","required":["report_name"],"title":"ReportCreateRequest","description":"Request schema for generating a financial report.\n\nThis schema supports all report types with flexible date period configuration.\nThe required fields depend on the report's `input_type` (see ReportTypeResponse).\n\n**Report Categories:**\n\nDate Range Reports (input_type='date_start_end'):\n    - `master_transactions`: Complete audit trail of all financial activity\n    - `profit_and_loss`: Standard P&L showing revenue, expenses, and net income\n    - `cash_flow_statement`: Cash flows by operating/investing/financing activities\n    - `sales_report`: Revenue analysis by customer, product, and time\n    - `tax_summary`: Sales tax collected by jurisdiction\n    - `sales_tax_by_jurisdiction`: Tax breakdown by state/jurisdiction\n    - `bank_reconciliation`: Reconciliation status for all bank accounts\n    - `report_1099`: Contractor payments for 1099 filing\n    - `journal_entry_report`: Audit trail of all journal entries\n    - `expense_by_category`: Expenses organized by category\n    - `check_register`: All payments and checks issued\n    - `retained_earnings`: Changes in equity over time\n    - `financial_ratios`: Key financial ratios dashboard\n    - `audit_trail`: Complete record of all changes\n    - `income_statement_details`: Transaction-level P&L detail\n    - `shareholder_loans`: Shareholder loan account tracking\n    - `subscription_costs`: Recurring subscription analysis\n    - `balance_sheet_monthly`: Month-by-month balance sheet over time\n    - `financial_summary_dashboard`: Executive-level financial dashboard\n    - `budget_vs_actual`: Compare actual performance against budget\n    - `payroll_summary`: Payroll expenses breakdown and trends\n    - `cogs_report`: Cost of goods sold analysis from ledger data\n\nComparative Reports (input_type='date_start_end_with_comparison'):\n    - `profit_and_loss_comparative`: P&L with period-over-period variance\n    - `balance_sheet_comparative`: Balance sheet with point-in-time comparison\n\nPoint-in-Time Reports (input_type='date_end_only'):\n    - `balance_sheet`: Standard balance sheet as of a specific date\n    - `working_capital`: Current assets vs liabilities analysis\n    - `aged_trial_balance`: Trial balance with aging buckets\n\nNo-Parameter Reports (input_type='no_params'):\n    - `ar_report`: Accounts receivable with aging\n    - `ar_aging_summary`: Standalone AR aging summary by customer\n    - `ap_report`: Accounts payable with aging\n    - `products_report`: Products, variants, and customers export\n    - `inventory_by_location`: Inventory by warehouse/location\n    - `chart_of_accounts`: Complete account listing\n\nPeriodic/Grouped Reports (input_type='date_start_end_with_grouping'):\n    - `income_statement_periodic`: Month-by-month or quarterly income statement\n    - `cash_flow_periodic`: Month-by-month or quarterly cash flow statement\n\nLedger-Filtered Reports (input_type='date_start_end_with_ledger'):\n    - `general_ledger`: Detailed transactions by account, optionally filtered\n\nOptions Reports (input_type='date_start_end_with_options'):\n    - `trial_balance`: Account balances with optional zero-balance inclusion\n\nCustomer-Filtered Reports (input_type='date_start_end_with_customer'):\n    - `customer_statements`: Statements for specific customer\n    - `pnl_by_customer`: Profitability by customer\n\nVendor-Filtered Reports (input_type='date_start_end_with_vendor'):\n    - `vendor_statements`: Vendor bills, payments, and balances\n\nTag-Filtered Reports (input_type='date_start_end_with_tag_group'):\n    - `pnl_by_department`: P&L segmented by department/tag\n\nForecast Reports (input_type='forecast_params'):\n    - `cash_flow_forecast`: Projected cash position based on AR/AP\n\n**Period Selection:**\nUse `period_type` to control how dates are determined:\n- `custom` (default): Provide explicit start_date/end_date\n- `tax_year`: Use business's fiscal year config with tax_year param\n- `tax_quarter`: Use specific quarter with tax_year + tax_quarter params","examples":[{"summary":"Custom date range","value":{"end_date":"2026-03-31","period_type":"custom","report_name":"profit_and_loss","start_date":"2026-01-01"}},{"summary":"Full tax year report","value":{"period_type":"tax_year","report_name":"profit_and_loss","tax_year":2026}},{"summary":"Quarterly report with prior year comparison","value":{"comparison_period_type":"tax_quarter","comparison_tax_quarter":1,"comparison_tax_year":2025,"period_type":"tax_quarter","report_name":"profit_and_loss_comparative","tax_quarter":1,"tax_year":2026}}]},"ReportOutputFormat":{"type":"string","enum":["xlsx","csv"],"title":"ReportOutputFormat","description":"Output format for generated reports.\n\n- **xlsx**: Microsoft Excel format with formatting, multiple tabs, headers,\n  currency formatting, and freeze panes. Best for interactive use and sharing.\n\n- **csv**: Comma-separated values format. Single flat file without formatting.\n  Best for importing into other systems, data analysis, or programmatic use."},"ReportPeriodType":{"type":"string","enum":["custom","tax_year","tax_quarter"],"title":"ReportPeriodType","description":"Type of period for report generation.\n\nDetermines how report date ranges are calculated:\n\n- **custom**: Use explicit start_date/end_date values provided in the request.\n  This is the default mode and gives full control over the date range.\n\n- **tax_year**: Calculate dates based on the business's tax year configuration.\n  Uses the business's `tax_year_end_month` setting to determine fiscal year\n  boundaries. For example, if tax_year_end_month=3 (March), tax_year=2026\n  would cover April 1, 2025 through March 31, 2026.\n\n- **tax_quarter**: Calculate dates for a specific quarter within a tax year.\n  Requires both `tax_year` and `tax_quarter` (1-4) parameters. Q1 is the\n  first quarter of the fiscal year, which may start in the prior calendar\n  year for non-calendar fiscal years."},"ReportTaskResponse":{"properties":{"task_id":{"type":"string","title":"Task Id","description":"Unique identifier for the report generation task. Use this to poll for status via GET /reports/task/{task_id}. Also serves as the Temporal workflow ID. Format: 'report-generation-{business_id}-{report_name}-{date_params}'. Example: 'report-generation-bus123-profit_and_loss-start-2026-01-01-end-2026-12-31'."},"status":{"type":"string","title":"Status","description":"Initial status of the task. Typically 'queued' for new requests or 'in_progress' if a duplicate request was made while an identical report is already being generated. Values: 'queued', 'in_progress', 'failed'."},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message","description":"Human-readable message about the task status. Provides context such as 'Report generation queued successfully with Temporal' or error details if the request failed validation."},"business_id":{"type":"string","title":"Business Id","description":"UUID of the business for which the report is being generated. Echoed from the request for confirmation."},"report_name":{"type":"string","title":"Report Name","description":"Type of report being generated. Echoed from the request for confirmation. Example: 'profit_and_loss', 'master_transactions', 'cogs_report'."}},"type":"object","required":["task_id","status","business_id","report_name"],"title":"ReportTaskResponse","description":"Response schema for async report generation task.\n\nReports are generated asynchronously via Temporal workflows. This response\nis returned immediately when a report generation request is submitted.\nUse the task_id to poll for status via GET /reports/task/{task_id}.\n\nThe task_id is also the Temporal workflow ID, which can be used for\ndebugging and monitoring in the Temporal UI.","example":{"business_id":"019ab37c-bus1-7000-8000-000000000001","message":"Report generation started","report_name":"profit_and_loss","status":"queued","task_id":"task_abc123xyz"}},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Token","description":"API token authentication. Format: `Bearer dz_...`"}}},"security":[{"BearerAuth":[]}]}