Monthly Reports
Generate, review, override, and share monthly performance reports with clients
Overview
Monthly reports compile client performance data — calls, bookings, agent metrics, and more — into a structured document stored as a MonthlyReport. Reports follow a lifecycle: draft → reviewed → sent, and can be shared with clients through the portal or via a public report token.
Generating Reports
Via API
Endpoint: POST /admin/reports/monthly/generate
Body:
{
"clientId": "client_abc",
"intervalDays": 30
}
| Parameter | Required | Values | Description |
|---|---|---|---|
clientId | Yes | Any client ID | The client to generate a report for |
intervalDays | No | 30 or 90 | Reporting window. Defaults to 30. |
The generateReport utility in utils/analytics.js compiles call history, agent metrics, and a monthly summary. If a structured summary is available, it uses generateMonthlyReportSummary; otherwise it falls back to buildFallbackMonthlyReportSummary.
List All Reports
Endpoint: GET /admin/reports/monthly?clientId=xxx&period=YYYY-MM&status=draft
| Filter | Description |
|---|---|
clientId | Filter by client |
period | Filter by YYYY-MM |
status | Filter by draft, reviewed, or sent |
intervalDays | Filter by reporting window (30 or 90) |
Returns up to 100 reports sorted by generatedAt descending.
View a Single Report
Endpoint: GET /admin/reports/monthly/:id
Returns the full report with mergedMetrics (base metrics merged with overrides). If the report has no previousMetrics, the system automatically fetches the previous report for period-over-period comparison.
Report Lifecycle
Reports progress through three statuses:
| Status | Meaning |
|---|---|
draft | Newly generated, pending review. Can be deleted. |
reviewed | Reviewed by an operator. Ready to share. |
sent | Shared with the client. A reportToken is generated for portal access. |
Updating Status
Endpoint: PUT /admin/reports/monthly/:id/status
Body:
{
"status": "sent"
}
When a report is moved to sent:
emailSentAtis set (if not already set)- A
reportTokenis generated (cryptographically random, 48 hex characters) for public/portal access
Only draft reports can be deleted. Once a report is reviewed or sent, it must stay in the system for audit purposes.
Deleting a Draft
Endpoint: DELETE /admin/reports/monthly/:id
Only reports with status: "draft" can be deleted. The delete action is audit-logged.
Overriding Metrics
After generation, you can override specific metric values without regenerating the entire report. This is useful for correcting known data gaps or adding context.
Endpoint: PUT /admin/reports/monthly/:id/overrides
Body:
{
"overrides": {
"totalCalls": 152,
"note": "Adjusted for 3 test calls excluded from production data"
}
}
The overrides object is merged with the base metrics to produce mergedMetrics, which is what the portal and API return.
Adding Notes
Endpoint: PUT /admin/reports/monthly/:id/notes
Body:
{
"notes": "Strong booking month. Campaign X drove 40% of new leads."
}
Notes are stored on the report and visible in the admin UI. They are not currently exposed to clients in the portal.
Client Portal Access
Clients can view their reports through the portal:
List Reports
Endpoint: GET /secure/reports
Returns all reports for the authenticated client, sorted by generatedAt descending. The overrides field is stripped from the list view.
View a Single Report
Endpoint: GET /secure/reports/:id
Returns the full report with mergedMetrics and previousMetrics (for period comparison). On first view, the report is marked as seenAt / seenBy.
Public Report Access
When a report status is set to sent, a reportToken is generated. This token can be used to construct a public report URL:
https://YOUR_API_HOST/public-reports/:reportToken
Public report links are unauthenticated. Treat the reportToken as a secret — do not share it in public channels. If a token is compromised, change the report status back to reviewed and then re-send it to generate a new token.
Monthly Summary (Portal)
The client portal also provides a lightweight monthly summary with daily breakdowns, separate from the formal MonthlyReport documents:
Endpoint: GET /secure/reports/monthly?year=2025&month=6
Returns:
| Field | Description |
|---|---|
totalCalls | Calls in the period |
booked | Calls with booked_appointment status |
totalMinutes | Total call minutes |
pickupRate | Percentage of calls with duration > 0 |
prevTotalCalls | Previous month's call count (for trend) |
daily | Array of { date, calls, duration } per day |
CSV Export
Endpoint: GET /secure/reports/export?from=2025-06-01&to=2025-06-30
Exports the client's own call history as a CSV file. Date range is optional; omit for all history.
Report Data Sources
Monthly reports aggregate data from:
| Source | Data Provided |
|---|---|
| Call records | Volume, duration, outcomes, status |
| Agent metrics | Per-agent calls, bookings, AI-handled calls |
| Analytics summary | Monthly performance summary with trend data |
| Overrides | Manual corrections applied after generation |
| Previous period | Prior report metrics for comparison |
