Reports API
The Reports API returns the same analytics as the in-app Reports area: a KPI summary, budget and profitability, staff performance, on-time delivery, workload and capacity, and client analytics, plus AI-answered questions and data export.
Authentication: every endpoint requires an API key. See API Keys & Authentication.
Permissions: every endpoint on this page needs report viewing access, which all roles from member up have by default. There is no separate gate on the financial figures inside these endpoints: the summary, budget, and clients reports include revenue, cost, and profit data for anyone with report access, so only give report access to people who may see those numbers.
All reports run against your key’s organisation and respond with
{ "success": true, "data": { ... } }.
Common query parameters
Section titled “Common query parameters”Every report endpoint (except financial-years) accepts the same filters:
| Name | Type | Required | Description |
|---|---|---|---|
| startDate | ISO 8601 date | No | Start of the reporting window. Defaults to the start of the current financial year. |
| endDate | ISO 8601 date | No | End of the reporting window. Defaults to the end of the current financial year. |
| fyType | string | No | Financial year convention used for the defaults: australia (July to June, the default), calendar (January to December), or uk (April to March). |
| clientId | UUID | No | Limit to one client organisation. |
| projectId | UUID | No | Limit to one project. |
| userId | UUID | No | Limit to one person. |
An unparseable startDate or endDate silently falls back to the financial
year default rather than returning an error. Each response echoes the
resolved window in data.filter.
GET /api/v1/reports/summary
Section titled “GET /api/v1/reports/summary”The dashboard summary: headline KPIs, recent alerts, and quick stats for the reporting window.
Example request
curl "https://api.runnit.io/api/v1/reports/summary?fyType=australia" \ -H 'Authorization: Bearer rnk_your_key'Response
{ "success": true, "data": { "filter": { "startDate": "2026-06-30T14:00:00.000Z", "endDate": "2027-06-29T14:00:00.000Z", "financialYearType": "australia" }, "generatedAt": "2026-07-08T12:29:38.271Z", "kpis": { "totalRevenue": { "label": "Total Revenue", "value": 250000, "formattedValue": "$250.0k", "trend": "up", "trendIsPositive": true }, "totalProfit": { "label": "Total Profit", "value": 61000, "formattedValue": "$61.0k", "trend": "up", "trendIsPositive": true } }, "recentAlerts": [], "quickStats": {} }}kpis contains totalRevenue, totalProfit, profitMargin,
onTimeDeliveryRate, avgEstimationAccuracy, teamUtilization,
activeProjects, and completedProjects, each with label, value,
formattedValue, trend (up, down, or neutral), and
trendIsPositive.
GET /api/v1/reports/budget
Section titled “GET /api/v1/reports/budget”Budget and profitability: budget versus actual cost per project, client totals, monthly trends, and a financial year summary.
Example request
curl "https://api.runnit.io/api/v1/reports/budget?startDate=2026-01-01&endDate=2026-06-30" \ -H 'Authorization: Bearer rnk_your_key'Response
data contains filter, generatedAt, summary, byProject, byClient,
byMonth, and financialYearSummary. Each byProject entry includes the
project name, job number, client name, budget, actualCost,
budgetVariance, and status. financialYearSummary gives the financial
year label with total revenue and cost.
GET /api/v1/reports/performance
Section titled “GET /api/v1/reports/performance”Staff performance: a ranked list of team members with completion and accuracy metrics.
Example request
curl https://api.runnit.io/api/v1/reports/performance \ -H 'Authorization: Bearer rnk_your_key'Response
data contains filter, generatedAt, summary, rankings,
topPerformers, needsImprovement, and trends. Each rankings entry
includes userName, roleTitle, tasksCompleted, estimationAccuracy
(0 to 1), onTimeRate (percentage), hoursLoggedThisPeriod, and rank.
GET /api/v1/reports/delivery
Section titled “GET /api/v1/reports/delivery”On-time delivery: per-project target versus actual dates and late-delivery history.
Example request
curl "https://api.runnit.io/api/v1/reports/delivery?clientId=<client-id>" \ -H 'Authorization: Bearer rnk_your_key'Response
data contains filter, generatedAt, summary, projectDeliveries,
recentLateDeliveries, trends, and byClient. Each projectDeliveries
entry includes projectName, clientName, targetDate, actualDate,
isOnTime, daysVariance, and taskCompletionRate.
GET /api/v1/reports/workload
Section titled “GET /api/v1/reports/workload”Workload and capacity: allocated versus available hours per person, project and client breakdowns, a capacity forecast, and a utilisation heatmap.
Example request
curl "https://api.runnit.io/api/v1/reports/workload?userId=<user-id>" \ -H 'Authorization: Bearer rnk_your_key'Response
data contains filter, generatedAt, summary, byStaff, byProject,
byClient, capacityForecast, and utilizationHeatmap. Each byStaff
entry includes userName, roleTitle, allocatedHours, availableHours,
utilizationPercent, activeTasks, and overdueTasks.
GET /api/v1/reports/clients
Section titled “GET /api/v1/reports/clients”Client analytics: revenue, hours, delivery rate, and lifetime value per client.
Example request
curl https://api.runnit.io/api/v1/reports/clients \ -H 'Authorization: Bearer rnk_your_key'Response
data contains filter, generatedAt, summary, clients,
topClientsByRevenue, topClientsByProjects, spendTrends, and
recentActivity. Each clients entry includes clientName,
totalProjects, activeProjects, totalRevenue, totalHoursLogged,
avgOnTimeRate, and lifetimeValue.
POST /api/v1/reports/insights
Section titled “POST /api/v1/reports/insights”Ask a natural-language question about your organisation’s data and get an
AI-generated answer with sources and suggested follow-ups. Send the returned
conversationId with your next question to continue the same conversation.
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| question | string | Yes | The question, in plain language. |
| conversationId | string | No | Continues an earlier insights conversation. |
Example request
curl -X POST https://api.runnit.io/api/v1/reports/insights \ -H 'Authorization: Bearer rnk_your_key' \ -H 'Content-Type: application/json' \ -d '{ "question": "Which projects are most over budget this quarter?" }'Response
{ "success": true, "data": { "query": "Which projects are most over budget this quarter?", "answer": "Two projects are tracking over budget...", "confidence": 0.8, "sources": [], "suggestedFollowUps": ["View Budget Report"], "conversationId": "b7e13f90-...", "timestamp": "2026-07-08T12:29:38.271Z" }}If AI insights are not configured on the deployment, the endpoint still
returns 200 with a fallback answer explaining that insights are
unavailable, and confidence is 0.
Errors
400ifquestionis missing or not a string.
GET /api/v1/reports/export/:type
Section titled “GET /api/v1/reports/export/:type”Export a report as a CSV or JSON file download. The export uses the same query filters as the report itself.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| type | string | Yes | budget, performance, delivery, workload, or clients. The summary report is not exportable. |
Query parameters
All the common filters, plus:
| Name | Type | Required | Description |
|---|---|---|---|
| format | string | No | csv (default) or json. |
Example request
curl -L -o budget-report.csv \ "https://api.runnit.io/api/v1/reports/export/budget?format=csv" \ -H 'Authorization: Bearer rnk_your_key'Response
A file download (Content-Disposition: attachment). The CSV form flattens
the report’s main table; for example, the budget export has the columns
Project, Job Number, Client, Budget, Spent, Variance, and Status. The JSON
form is the full report body.
Errors
400iftypeis not one of the five exportable reports, orformatis notcsvorjson.
GET /api/v1/reports/financial-years
Section titled “GET /api/v1/reports/financial-years”List the financial year options you can use to frame report windows: the current year, the previous five, and the supported financial year conventions. This endpoint takes no query parameters.
Example request
curl https://api.runnit.io/api/v1/reports/financial-years \ -H 'Authorization: Bearer rnk_your_key'Response
{ "success": true, "data": { "current": { "value": "2026-2027", "label": "FY26/27", "startDate": "2026-06-30T14:00:00.000Z", "endDate": "2027-06-29T14:00:00.000Z" }, "available": [ { "value": "2026-2027", "label": "FY26/27" } ], "types": [ { "value": "australia", "label": "Australia (Jul-Jun)" }, { "value": "calendar", "label": "Calendar Year (Jan-Dec)" }, { "value": "uk", "label": "UK (Apr-Mar)" } ] }}The year list always uses July to June boundaries; pass fyType to the
report endpoints to reframe the default window for calendar or uk
conventions.
Next steps
Section titled “Next steps”Drill into the underlying records with the Projects API, or check who can see reports with the Permissions & Search API.