Role-to-scope mapping
There is no
?scope= parameter. A client that cannot see org-wide data cannot ask for it.
Requesting a report
weekly, that is the last complete Monday-to-Monday window. For monthly, it is the previous calendar month.
To request a historical period, pass an anchor date. The report covers the complete period immediately before that date:
Report contents
Total spend
Aggregate payroll cost of all meetings in scope for the period, plus meeting count, total person-hours, and percentage change against the previous period.
Spend by recurring series
Total and occurrence count per series, plus an annual run-rate derived from the average per-occurrence cost multiplied by the series cadence’s occurrences-per-year.
Largest single meetings
The top 10 most expensive individual meetings in the period, by actual cost.
Spend by team
Cost breakdown by the organiser’s team, sorted by total spend descending. Present only where team data is available in the directory.
change_percent field is the percentage change in total_spend versus the previous equivalent period — positive is an increase, negative a decrease.
The reduced_before_send metric
For org-wide scopes (Finance and Admin), the report includes a reduced_before_send object derived from the draft_id snapshot table:
reduced_percent is reduced / drafts × 100. This metric is only meaningful at org-wide scope and is absent from team-level and individual reports.
CSV export
- Report metadata — period, scope, currency, total spend, meeting count, person-hours, previous total, change percent
- Spend by team —
team_id,team_name,meetings,total - Spend by recurring series —
series_id,title,occurrences,total,annualised_run_rate - Largest single meetings —
meeting_id,title,started_at,headcount,duration_minutes,total
Periodic digests
Digests deliver the report to inboxes and chat webhooks on a schedule, so the people who need the data do not have to remember to go and fetch it. Each digest is scoped to the recipient’s own role — a team lead’s weekly email contains their team and nothing else. Digests are only sent to users who hold theteam_lead, finance, or admin role.
Scheduling with cron
Digests are not driven by an in-process timer. Run them from your scheduler:Idempotency via digest_runs
Every successful dispatch writes a row to the digest_runs table keyed on (period, period_start, audience). If the job runs twice for the same period and recipient — due to a retry, a cronjob overlap, or a manual re-run — the second execution skips the send rather than delivering a duplicate.
To force a resend (for example, after fixing a template):
--force updates the existing digest_runs row rather than inserting a second one, so the uniqueness guarantee is preserved.
If a recipient has no meetings in scope for the period, no digest is sent to them — an empty report email adds noise without value. The job logs this as a skip, not an error.