Reports API
The Reports API returns the analytics used by Insights & Analytics. It includes rate-card-derived financial figures, staff performance, delivery, workload, client analytics, exports, and financial year options.
Every endpoint requires an API key. See API Keys & Authentication.
Permissions
Section titled “Permissions”The API key uses the current permissions of the person who created it.
| Endpoint | Required capability |
|---|---|
summary, budget, performance, clients, and POST insights | View financial data (report:financial) |
delivery, workload, and financial-years | View reports (report:view) |
| Export | Export reports (report:export), plus report:financial for budget, performance, or clients, or report:view for delivery or workload |
These checks apply to API calls even if the person doesn’t use the in-app Insights page.
Financial definitions
Section titled “Financial definitions”Financial reports calculate values from the rates captured when each time entry was recorded:
realizedRevenue: billable time multiplied by its captured billable rate.actualInternalCostortotalCost: all logged time multiplied by its captured internal cost rate.totalProfitorprofitMargin: realised revenue minus internal cost.profitPercent: profit divided by realised revenue.budgetVariance: project budget minus realised revenue.
Changing a rate card doesn’t rewrite existing time-entry rates. Older entries
without a captured rate use their available legacy hourly rate. Summary and
budget responses include rateCoverage, so integrations can identify periods
that contain legacy fallbacks.
All money values are in the organisation’s reporting currency, converted
through the exchange-rate snapshots frozen on each time entry (see the
Rate Cards API for managing rates). The
currency field on summaries and rows carries that reporting currency.
Budget comparisons use each project’s reporting-currency valuation
(budgetReporting on budget rows); the native budget and budgetCurrency
are still returned. rateCoverage.missingFxRates counts entries that have
no conversion rate yet; their amounts are included unconverted until a rate
is published. Rejected time entries are excluded from every figure.
actualCost, totalSpent, and billableSpend remain compatibility aliases for
realised revenue on budget responses. Don’t treat project budget as revenue or
these aliases as internal cost.
Common query parameters
Section titled “Common query parameters”Report endpoints, except financial-years, accept these filters:
| Name | Type | Required | Description |
|---|---|---|---|
startDate | ISO 8601 date | No | First date in the reporting window. Defaults to the start of the current financial year. |
endDate | ISO 8601 date | No | Last date in the reporting window. This date is inclusive and defaults to the end of the current financial year. |
fyType | string | No | Default financial year convention: australia (July to June), calendar (January to December), or uk (April to March). |
An invalid date falls back to the relevant financial year boundary. Each
response echoes the resolved window in data.filter.
All standard report responses use this envelope:
{ "success": true, "data": {}}GET /api/v1/reports/summary
Section titled “GET /api/v1/reports/summary”Returns the Insights headline metrics, recent budget and delivery alerts, quick activity totals, and rate coverage.
curl "https://api.runnit.io/api/v1/reports/summary?fyType=australia" \ -H 'Authorization: Bearer rnk_your_key'The kpis object contains:
totalRevenue, from billable time and captured billable rates;totalProfitandprofitMargin, after captured internal cost;onTimeDeliveryRate, using completed projects with both target and actual dates;avgEstimationAccuracy, as a bounded score from 0 to 1;teamUtilization,activeProjects, andcompletedProjects.
Each KPI has label, value, formattedValue, trend, and
trendIsPositive. No eligible delivery or estimation records produce zero,
not an assumed successful value.
rateCoverage has this shape:
{ "timeEntryCount": 120, "billableEntryCount": 95, "missingBillableRateSnapshots": 2, "missingActualCostRateSnapshots": 3, "missingFxRates": 0, "snapshotCoveragePercent": 98, "basis": "time_entry_snapshots"}GET /api/v1/reports/budget
Section titled “GET /api/v1/reports/budget”Returns budget, realised revenue, internal cost, profit, and margin by project, client, and month.
curl "https://api.runnit.io/api/v1/reports/budget?startDate=2026-01-01&endDate=2026-06-30" \ -H 'Authorization: Bearer rnk_your_key'data contains summary, rateCoverage, byProject, byClient, byMonth,
and financialYearSummary. A byProject item includes:
{ "projectId": "<project-id>", "projectName": "Autumn campaign", "jobNumber": "RUN-1042", "clientName": "Example Client", "rateCardName": "Example Client 2026", "budget": 50000, "realizedRevenue": 18000, "actualInternalCost": 9000, "profitMargin": 9000, "profitPercent": 50, "budgetVariance": 32000, "missingBillableRateSnapshots": 0, "missingActualCostRateSnapshots": 0, "status": "under_budget"}Monthly rows group revenue and cost by the time-entry month. Their budget is the sum of projects created in that month.
GET /api/v1/reports/performance
Section titled “GET /api/v1/reports/performance”Returns staff rankings and trends for completion, estimation, delivery, time, and revenue-to-cost performance.
curl https://api.runnit.io/api/v1/reports/performance \ -H 'Authorization: Bearer rnk_your_key'data contains summary, rankings, topPerformers, needsImprovement, and
trends. Ranking rows include task totals, estimationAccuracy (0 to 1),
onTimeRate, logged and billable hours, average charge and cost rates,
totalRevenueAmount, totalCostAmount, revenueCostRatio, overallScore, and
rank.
Estimation accuracy treats proportional over-estimation and under-estimation equally. A task needs both positive estimated hours and positive actual hours to contribute to the score.
GET /api/v1/reports/delivery
Section titled “GET /api/v1/reports/delivery”Returns project delivery status, recent late tasks, weekly trends, and a client breakdown.
curl "https://api.runnit.io/api/v1/reports/delivery?startDate=2026-01-01&endDate=2026-06-30" \ -H 'Authorization: Bearer rnk_your_key'data contains summary, projectDeliveries, recentLateDeliveries,
trends, and byClient. A delivery only contributes to an on-time or late
rate when both its target and actual completion dates exist. The summary still
reports all completed projects separately.
Project rows include projectName, clientName, targetDate, actualDate,
isOnTime, daysVariance, and taskCompletionRate.
GET /api/v1/reports/workload
Section titled “GET /api/v1/reports/workload”Returns current workload and capacity by person, project, and client, plus a capacity forecast and utilisation heatmap.
curl https://api.runnit.io/api/v1/reports/workload \ -H 'Authorization: Bearer rnk_your_key'data contains summary, byStaff, byProject, byClient,
capacityForecast, and utilizationHeatmap. Staff rows include allocated and
available hours, utilisation, active and overdue tasks, scheduled hours, and
capacity flags.
GET /api/v1/reports/clients
Section titled “GET /api/v1/reports/clients”Returns financial, time, project, and delivery analytics by client.
curl "https://api.runnit.io/api/v1/reports/clients?startDate=2026-01-01&endDate=2026-06-30" \ -H 'Authorization: Bearer rnk_your_key'data contains summary, clients, topClientsByRevenue,
topClientsByProjects, spendTrends, and recentActivity. Client rows include
totalBudget, totalRevenue, totalCost, totalProfit, profitPercent,
logged and billable hours, project totals, and avgOnTimeRate.
Revenue and cost use time entries inside the selected period. The on-time rate uses completed projects in that period that have both required dates.
POST /api/v1/reports/insights
Section titled “POST /api/v1/reports/insights”This compatibility endpoint accepts a natural-language reporting question. The in-app Ask AI report tab has been removed. New user workflows should open the global Chat Assistant instead.
| Body field | Type | Required | Description |
|---|---|---|---|
question | string | Yes | Reporting question in plain language. |
conversationId | string | No | Continues an earlier reporting conversation. |
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 over budget?" }'The response can include answer, confidence, sources,
suggestedFollowUps, conversationId, and timestamp. If reporting AI isn’t
available, the endpoint returns a fallback answer with confidence: 0.
The endpoint returns 400 when question is missing or isn’t a string.
GET /api/v1/reports/export/:type
Section titled “GET /api/v1/reports/export/:type”Downloads budget, performance, delivery, workload, or clients as CSV
or JSON. The export accepts the common date and financial year filters.
| Parameter | Location | Required | Description |
|---|---|---|---|
type | Path | Yes | One of the five report types above. |
format | Query | No | csv (default) or json. |
curl -L -o budget-report.csv \ "https://api.runnit.io/api/v1/reports/export/budget?format=csv" \ -H 'Authorization: Bearer rnk_your_key'JSON contains the full report body. Budget CSV columns are Project, Job Number, Client, Rate Card, Budget, Realized Revenue, Internal Cost, Gross Profit, Margin, Variance, and Status.
Delivery exports use Not measured when a project is missing a target or actual
completion date. Client exports include Revenue, Internal Cost, Gross Profit,
and Margin as separate columns.
The endpoint returns 400 for an unsupported report type or format.
GET /api/v1/reports/financial-years
Section titled “GET /api/v1/reports/financial-years”Returns the current Australian financial year, the previous five options, and
the supported australia, calendar, and uk conventions. This endpoint has
no query parameters.
curl https://api.runnit.io/api/v1/reports/financial-years \ -H 'Authorization: Bearer rnk_your_key'The available year list uses July to June boundaries. Pass fyType to a report
endpoint when its default window should follow a different convention.
Next steps
Section titled “Next steps”Review how captured rates are configured in the Rate Cards API, or check report capabilities in the Permissions & Search API.