Reports: filters, drill-down and Excel
Every report in Evenbead can be narrowed with filters, opened down to the transactions behind each amount, and downloaded as CSV, PDF, an Excel workbook (.xlsx) or JSON. The same filters work in the app, over the REST API and through the MCP tools. (Dated 2026-10-16; ADR-0167, building on the drill-down of ADR-0081.)
Filters
| Report | Class | Project | Customer | Vendor |
|---|---|---|---|---|
| Profit and loss (accrual and cash), comparative P&L | yes | yes | yes | yes |
| General ledger | yes | yes | yes | yes |
| Trial balance, balance sheet, comparative balance sheet | yes | yes | ||
| AR aging, AR detail | yes | |||
| AP aging, AP detail | yes | |||
| Sales by customer | yes | yes | yes | |
| Expenses by vendor | yes | yes | yes | |
| Job costing | yes | yes |
What each filter keeps:
- Class and project: the journal lines tagged with that class or project.
- Customer and vendor: the lines of the entries that belong to that customer's (vendor's) invoices, sales receipts, credit memos, refunds, bills, expenses, checks, vendor credits and payments, their voids and their edits. A customer's profit and loss therefore has exactly the income that sales by customer gives the customer. A line tagged only with a customer's project does not count for the customer: filter by the project, or use job costing. Journal entries made by hand belong to no customer or vendor.
- Filters combine (class North and customer Alder Homes = Alder's North lines). Choose a customer or a vendor, not both.
- On the cash basis, an invoice or bill counts for its customer (vendor) as it is paid.
- A filtered trial balance or balance sheet need not balance: an entry balances as a whole, not per class or project. The report says whether it balances.
- A filtered AR or AP aging still ties out: the control account's balance shown is that customer's (vendor's) part.
The cash-flow statement, sales by item, the transaction list and the 1099 summary take no filters: a filtered cash flow would not tie to the change in cash.
In the app, the filters sit beside the dates on each report, stay in the page address (so a link or a bookmark keeps them), and show as a Filtered: line with Clear filters. Every amount on a filtered report opens the transactions behind it with the same filters, and its total equals the amount. A project's page also shows its budget beside its actuals when the project has a budget for those dates (compared over whole budget months).
Over the API, pass class and project by name and customer_id / vendor_id by id:
GET /v1/reports/profit-and-loss?from=2026-01-01&to=2026-09-30&customer_id=…&class=North
GET /v1/reports/ar-aging?as_of=2026-09-30&customer_id=…
GET /v1/reports/drill-down?section=income&from=2026-01-01&to=2026-09-30&customer_id=…
Each filtered report's JSON carries filters (class, project, customer {id, name}, vendor {id, name}). A filter a report does not take is refused (unknown query parameter), as is an unknown class, project or contact, in plain words. The MCP report tools (get_profit_and_loss, get_general_ledger, get_ar_aging and the rest) take the same arguments.
Downloads
Every report with a CSV also offers Download Excel (.xlsx) (over the API: format=xlsx, content type application/vnd.openxmlformats-officedocument.spreadsheetml.sheet). The workbook is made on Evenbead's own server; nothing is sent anywhere else. It opens in Excel, LibreOffice Calc and Google Sheets:
- The top rows say the report, the company, the period, the basis and the filters ("Filters: none" when unfiltered).
- The column headings are bold and stay in view as you scroll; sections and totals are bold; columns are sized to their content.
- Money is a number with a dollar format (negatives in parentheses), dates are real dates ("Oct 3, 2026"), counts are whole numbers, percentages are percentages, so you can sum, sort and chart them.
- Totals are the report's own values, not formulas: the file shows exactly the numbers on the screen.
- Reports with several parts have several sheets (AR/AP aging: Summary, Open documents and Retainage; sales tax: By rate, By agency, By period; a reconciliation: Summary and Items).
- The file name names the report, the company, the period and the filters, e.g.
profit-and-loss_riverbend-bakery_2026-01-01_2026-09-30_customer-alder-homes.xlsx.
A filtered CSV starts with a Filters row and a blank row before the column headings (an unfiltered CSV is unchanged); a filtered PDF names the filters under its title.
Downloading the transactions behind an amount
The page that lists the transactions behind an amount (open any amount on a report) has Download CSV and Download Excel (.xlsx) beside its total; on a phone they are under More. The file holds what the page shows, with the same period, basis and filters: one row per transaction line (date, entry number, description, line memo, customer or vendor, account, class, project, the invoice, bill or payment it comes from, amount and running total), then a total row that equals the amount you opened. Dates are written 2026-09-30 and amounts as plain decimals (1234.56), as in every other CSV; text that a spreadsheet would treat as a formula is written so it stays text. The page shows the first 5,000 lines of a very large amount; the download has all of them, up to 50,000 (beyond that it asks you to narrow the period). The same works for an aging amount (the open invoices or bills behind it).
Over the API, add format=csv or format=xlsx to GET /v1/reports/drill-down or GET /v1/reports/aging/drill-down.
Files for AI agents (MCP)
The MCP report tools (get_profit_and_loss, get_balance_sheet, get_ar_aging, get_budget_vs_actual and the rest: every report that has an Excel workbook) and the two drill-down tools take format: json (the default, the report as data), csv or xlsx. A file comes back as an embedded resource with its type (for a workbook, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, base64-encoded; a CSV as text) and its address on the API, next to a short note with the file name, size and SHA-256, so the AI app can save it or hand it to you without reading it all. It is the same file the app and the API give, with the same filters and the same permissions. A file larger than 8 MB is not sent through the tool: the answer says so and gives the API address to download it with the same connection.