Skip to main content
The reports endpoints surface periodic meeting-cost summaries — spend totals, recurring series run-rates, trend comparisons, and the “reduced before send” metric. The scope of what each caller sees is determined entirely by their role: there is no request parameter that widens it, and participants are blocked entirely. Both the JSON view and the CSV export are written to the audit log on every access.

Role-to-scope mapping

Scope is derived server-side from the caller’s role and team assignment. There is no scope request parameter — a caller cannot widen their own scope. A team_lead assigned to team_id=eng will always see only that team’s meetings.

GET /api/v1/reports

Returns a digest for the most recent complete period (weekly or monthly). Callers with the organiser role see only their own meetings; team_lead callers see their team’s data; finance and admin see org-wide data. Participants receive 403. Both JSON and CSV responses are recorded in the audit log on every access.

Query parameters

string
default:"weekly"
The reporting period. Must be weekly or monthly.
string
An ISO 8601 date (YYYY-MM-DD). When provided, the report covers the complete period before this date rather than the most recent complete period. Use this to retrieve historical periods.

Response body

string
The period label, e.g. "2026-W35" or "2026-08".
string
ISO 8601 date of the first day of the period.
string
ISO 8601 date of the last day of the period.
string
The scope actually applied to this report ("own_meetings", "own_team", or "org_wide"), derived from the caller’s role.
string
ISO 4217 currency code for all monetary figures in this response.
string
Total payroll cost of all meetings in the period, as a decimal string.
integer
Number of completed meetings in the period.
number
Aggregate person-hours (sum of attendees × duration_hours for all meetings).
string | null
Total spend for the equivalent prior period. null if no data exists for that period.
number | null
Percentage change from previous_total to total_spend. Positive = increase. null if previous_total is unavailable.
array
Spend broken down by team, for org-wide scoped reports.
array
Spend broken down by recurring meeting series.
array
The highest-cost individual meetings in the period.
object | null
The rollout metric showing whether organisers act on nudges. Present only for org-wide scoped reports (finance and admin roles). null for team-scoped or own-meetings reports.

Response example

Example request


GET /api/v1/reports/export.csv

Downloads an aggregate CSV of the same report data. Applies the same role-scoping rules as the JSON endpoint — organiser, team_lead, finance, and admin callers may all call this endpoint, each receiving data at their own scope level. Participants receive 403. The CSV is aggregate-only: no column identifies an individual person’s cost, salary, or rate. Every call creates an audit record.

Query parameters

Same as GET /api/v1/reports: period (weekly|monthly) and optional anchor (YYYY-MM-DD).

Response

Returns text/csv with a Content-Disposition: attachment header. The filename includes the period label and start date:

Example request

Every call to the CSV export writes an audit record. Automated scripts that call this endpoint repeatedly will produce a proportionally large audit trail. Schedule exports thoughtfully — a weekly download is typically sufficient for most compliance workflows.