GET /api/agent/revenue/summary
Returns AR totals + distributions WITHOUT individual records. Use FIRST for any 'how much revenue YTD?', 'who are my top customers?', 'monthly revenue breakdown' question - 50x token savings vs /api/agent/invoices for aggregate reads. PAID values are ex-GST (reconciles to Xero cash-basis P&L within +-1% via the line splitter). Default window = current FY YTD per XeroConnection.financialYearEndDay/Month; override via ?dateFrom=&dateTo=. Calendar-month buckets in Organization.timezone (default Australia/Sydney).
Auth
- Required scope:
READ_SUMMARY - Header:
Authorization: Bearer cr_live_<prefix>_<secret>
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
dateFrom | string | no | Inclusive lower bound (YYYY-MM-DD). Overrides the default FY YTD window. |
dateTo | string | no | Inclusive upper bound (YYYY-MM-DD; expanded to end-of-day UTC). |
topN | integer | no | Cap on topContacts length (1-100). Default 10. |
Responses
200 — Aggregate revenue summary
Body: RevenueSummaryResponse
| Field | Type | Required | Notes |
|---|---|---|---|
asOfDate | string (date) | yes | |
currency | string | yes | |
window | object | yes | |
grandTotal | SummaryBucket | yes | |
byStatus | object | yes | Keyed by Xero invoice status (PAID, AUTHORISED, ...). PAID = ex-GST cash-basis per the line splitter. AUTHORISED = gross outstanding amounts from source-doc rows. |
byMonth | array of SummaryMonthBucket | yes | |
topContacts | array of SummaryTopContact | yes | |
redactedItemCount | integer | yes | Number of topContacts rows whose name was rewritten to Sensitive contact. Always 0 when the key carries READ_SENSITIVE. Other aggregates (byMonth, byStatus, grandTotal) are NEVER masked. |
grossProfit | object | yes | Org-wide gross profit. COGS is derived from per-line P&L coding on Xero bill lines (accounts typed DIRECTCOSTS), NOT bank-feed category descriptors. This is a STABLE trailing-window reading (buffered last-3-full-months) and intentionally does NOT honour the request's dateFrom/dateTo — it reports the org's structural margin, not the margin over the requested window. The same number drives the dashboard GP% panel and the customer LTV card. Present only on the revenue summary (the expenses summary has no gross-profit reading). |
billingAlert | BillingAlert | no | |
xeroAlert | XeroAlert | no |
401 — Unauthorized
Body: ErrorResponse
| Field | Type | Required | Notes |
|---|---|---|---|
error | string | yes |
403 — Key lacks the required scope
Body: ErrorResponse
| Field | Type | Required | Notes |
|---|---|---|---|
error | string | yes |
429 — Rate-limited or quota-exhausted
Body: ErrorResponse
| Field | Type | Required | Notes |
|---|---|---|---|
error | string | yes |
Response headers
Every successful response carries X-CashRunway-Subscription, X-CashRunway-Plan, X-CashRunway-Quota-Remaining, and X-CashRunway-Quota-Reset. Trialing subscriptions also include X-CashRunway-Trial-Days-Remaining. See the overview for details.