Skip to content
Back to skills

Reports

ASecurity

Xero Reports API: Profit and Loss, Balance Sheet, Aged Receivables and Payables, Trial Balance, Bank Summary and other management reports. Covers report parameters, date ranges, tracking-category filtering, the shared Rows/Cells response shape, and parsing results for MSP financial operations.

  • 48 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 2, 2026
ai-agentsjavascriptgojavabashapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned October 2, 2026

npx -y skills add wyre-technology/msp-claude-plugins --skill reports --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Reports?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Reports
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/wyre-technology-reports-msp-claude-plugins/badge)](https://www.skillsdirectory.com/skills/wyre-technology-reports-msp-claude-plugins)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: "Xero Reports"
description: >
  Xero Reports API: Profit and Loss, Balance Sheet, Aged Receivables and
  Payables, Trial Balance, Bank Summary and other management reports. Covers
  report parameters, date ranges, tracking-category filtering, the shared
  Rows/Cells response shape, and parsing results for MSP financial operations.
when_to_use: >-
  When generating, filtering, or parsing a Xero financial report. Use when: xero report, xero
  profit and loss, xero p&l, xero balance sheet, xero aged receivables, xero aged payables, xero
  trial balance, xero financial report, xero reporting, or msp financial report.
---

# Xero Financial Reports

## Overview

Xero exposes its financial reports through the API as structured, programmatically parseable data. For MSPs, these reports drive profitability tracking by service line, client payment-behavior monitoring, cash flow management, and financial statements for stakeholders.

## Anti-triggers

- **Individual transactions rather than aggregates** — reports return
  summarized rows with no drill-through; the underlying records are
  `xero-invoices` and `xero-payments`.
- **The GL structure a report groups by** — use `xero-accounts`.
- **The same reports in QuickBooks** — use `qbo-reports`.

## Core Concepts

### Available Reports

| Report | Endpoint | Description |
|--------|----------|-------------|
| Profit and Loss | `/Reports/ProfitAndLoss` | Revenue, expenses, and net profit |
| Balance Sheet | `/Reports/BalanceSheet` | Assets, liabilities, and equity |
| Aged Receivables | `/Reports/AgedReceivablesByContact` | Outstanding customer invoices by age |
| Aged Payables | `/Reports/AgedPayablesByContact` | Outstanding supplier bills by age |
| Trial Balance | `/Reports/TrialBalance` | All account balances at a point in time |
| Bank Summary | `/Reports/BankSummary` | Summary of bank account activity |
| Budget Summary | `/Reports/BudgetSummary` | Budget vs actual comparison |
| Executive Summary | `/Reports/ExecutiveSummary` | High-level financial overview |

### Report Response Structure

All Xero reports share one nested `Rows`/`Cells` shape. Values arrive as strings and must be parsed to numbers:

```json
{
  "Reports": [
    {
      "ReportID": "ProfitAndLoss",
      "ReportName": "Profit and Loss",
      "ReportType": "ProfitAndLoss",
      "ReportDate": "23 February 2026",
      "UpdatedDateUTC": "/Date(1772006400000)/",
      "Rows": [
        {
          "RowType": "Header",
          "Cells": [
            { "Value": "" },
            { "Value": "1 Mar 2026 to 31 Mar 2026" }
          ]
        },
        {
          "RowType": "Section",
          "Title": "Revenue",
          "Rows": [
            {
              "RowType": "Row",
              "Cells": [
                { "Value": "Managed Services Revenue", "Attributes": [{ "Value": "acc-id-200" }] },
                { "Value": "45000.00", "Attributes": [{ "Value": "acc-id-200" }] }
              ]
            }
          ]
        },
        {
          "RowType": "SummaryRow",
          "Cells": [
            { "Value": "Total Revenue" },
            { "Value": "67500.00" }
          ]
        }
      ]
    }
  ]
}
```

### Row Types

| RowType | Description |
|---------|-------------|
| `Header` | Column headers |
| `Section` | Group of related rows (e.g., Revenue, Expenses) |
| `Row` | Individual data row (account or contact) |
| `SummaryRow` | Total/subtotal row |

## API Patterns

Reports are GET-only and take their parameters in the query string. Period reports (P&L, Bank Summary) use `fromDate`/`toDate`; point-in-time reports (Balance Sheet, Aged Receivables/Payables, Trial Balance) use a single `date`. All dates are `YYYY-MM-DD`.

```bash
curl -s -X GET "https://api.xero.com/api.xro/2.0/Reports/ProfitAndLoss?fromDate=2026-03-01&toDate=2026-03-31" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "xero-tenant-id: ${XERO_TENANT_ID}" \
  -H "Accept: application/json"
```

Parameters worth knowing across reports:

| Parameter | Applies to | Description |
|-----------|-----------|-------------|
| `periods` + `timeframe` | P&L, Balance Sheet | Adds comparison columns (MONTH, QUARTER, YEAR) |
| `trackingCategoryID` / `trackingOptionID` | P&L, Balance Sheet | Filter to a service line or department |
| `paymentsOnly` | P&L, Balance Sheet, Trial Balance | `true` = cash basis, `false` = accrual |
| `contactID` | Aged Receivables/Payables | Restrict the report to one contact |

See [references/api.md](references/api.md) for the full request catalog, per-report parameter tables, and the complete endpoint reference.

## Common Workflows

### MSP Monthly Financial Review

Fetch P&L, Balance Sheet, Aged Receivables, and Aged Payables for the closing month in parallel, then parse each into a summary. Reports are independent requests, so parallelizing is safe and materially faster.

### Revenue and Margin Analysis

Walk the P&L `Rows` tree, matching `Section` titles (`Revenue`/`Income`, `Less Cost of Sales`/`Direct Costs`) and reading the `SummaryRow` totals. Section titles vary by chart-of-accounts layout — match on more than one candidate title.

### Overdue Client Review

Parse the Aged Receivables sections into per-contact aging buckets (current, 30, 60, 90, older) and sort by total overdue. Cells are positional, so index by column order rather than by name.

### Year-over-Year Comparison

Request the same P&L period for the current and prior year, then compare parsed revenue totals.

See [references/examples.md](references/examples.md) for working JavaScript implementations of each workflow.

## Error Handling

### Common API Errors

| Code | Message | Resolution |
|------|---------|------------|
| 400 | Invalid date format | Use YYYY-MM-DD format |
| 400 | fromDate must be before toDate | Swap date parameters |
| 400 | Invalid tracking category | Verify trackingCategoryID exists |
| 401 | Unauthorized | Refresh access token |
| 403 | Insufficient scope | Ensure `accounting.reports.read` scope |
| 404 | Report not found | Check report endpoint name |

### Report Parsing Errors

| Issue | Cause | Fix |
|-------|-------|-----|
| Empty rows | No data for period | Verify date range has transactions |
| Missing sections | No revenue or expenses | Normal for new organizations |
| Null cell values | Account has no balance | Default to 0 when parsing |

## Gotchas

- **Reports are expensive** - Cache results keyed on the report name plus its parameters; repeated identical requests burn rate limit for identical data.
- **Always specify dates explicitly** - Omitting `fromDate`/`toDate` or `date` yields Xero's default period, which is rarely the one you meant.
- **Parse defensively** - Cells can be absent or empty strings; coerce to 0 rather than assuming a numeric value.
- **Tracking categories are the MSP lever** - Filtering P&L by tracking category is the only way to get per-service-line profitability out of the standard reports.
- **Cash vs accrual changes the answer** - `paymentsOnly=true` reports cash movements only; use it for cash flow analysis, not for revenue recognition.

## Related Skills

- [Xero Invoices](../invoices/SKILL.md) - Invoice data feeding reports
- [Xero Payments](../payments/SKILL.md) - Payment data in reports
- [Xero Accounts](../accounts/SKILL.md) - Account structure for P&L and Balance Sheet
- [Xero Contacts](../contacts/SKILL.md) - Contact-level report filtering
- [Xero API Patterns](../api-patterns/SKILL.md) - API reference

Files in this skill

  • SKILL.md7.3 KB
  • references/api.md5.8 KB
  • references/examples.md5.1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…