Custom reports
Build ad-hoc reports — pick metrics, group by dimensions, filter, over a date range.
The custom-report endpoint is a small analytics engine: choose metrics (the numbers), group by dimensions (the rows), apply filters, over a date range. It powers the in-app report builder and is available over the API and MCP.
Discover what's available
GET /api/v1/reports/metadata — scope reports:read
Returns the catalog of metrics, dimensions and filterable fields (plus limits). Use it to build a picker or to check valid keys before querying.
curl https://app.militime.ai/api/v1/reports/metadata \
-H "Authorization: Bearer mt_live_your_token"Metrics
| Key | Unit | Notes |
|---|---|---|
hours_tracked | hours | All tracked time |
billable_hours | hours | Time marked billable |
non_billable_hours | hours | |
entry_count | count | Number of time entries |
billable_percentage | percent | Billable ÷ total hours |
billable_amount | currency | Revenue, attributed with the same rate logic as invoices |
Dimensions
client, project, user, team, category, billable, and one time bucket:
day, week, month, quarter, year.
Revenue is only valid at client / project / time grain. billable_amount
cannot be grouped by user, team, category or billable, and requesting it
with an incompatible dimension returns invalid_request. Hourly/retainer work
is recognized at its effective rate on billable time; fixed-price work is
straight-lined over the project's start–end dates (a fixed-price project with
no end date recognizes nothing).
Filters
client_id, project_id, user_id (eq / in), category (eq / in),
billable (eq).
Run a report
POST /api/v1/reports/query — scope reports:read
curl -X POST https://app.militime.ai/api/v1/reports/query \
-H "Authorization: Bearer mt_live_your_token" \
-H "Content-Type: application/json" \
-d '{
"metrics": ["hours_tracked", "billable_amount"],
"dimensions": ["client", "month"],
"filters": [{ "field": "billable", "op": "eq", "value": true }],
"date_range": { "start": "2026-01-01", "end": "2026-07-01" },
"limit": 100
}'{
"object": "report",
"range": { "start": "2026-01-01T00:00:00.000Z", "end": "2026-07-01T00:00:00.000Z" },
"columns": [
{ "key": "client", "label": "Client", "kind": "dimension" },
{ "key": "month", "label": "Month", "kind": "dimension" },
{ "key": "hours_tracked", "label": "Hours tracked", "kind": "metric", "unit": "hours" },
{ "key": "billable_amount", "label": "Billable amount", "kind": "metric", "unit": "currency" }
],
"rows": [
{ "client": "cl_123", "month": "2026-06", "hours_tracked": 42.5, "billable_amount": 6375 }
],
"totals": { "hours_tracked": 120, "billable_amount": 18000 },
"labels": { "client": { "cl_123": "Acme Inc." } },
"row_count": 1,
"truncated": false
}Notes
labelsresolves entity dimension ids (client/project/user/team) to display names.- Rows are sorted by the first metric, descending, then capped at
limit(max 1000).truncatedistrueif there were more groups than returned. - Time bucket values:
day/week→ a date (YYYY-MM-DD, week = Monday),month→YYYY-MM,quarter→YYYY-Q#,year→YYYY. - Limits: up to 6 metrics, 3 dimensions (one time bucket), and a 2-year range.
- Durations are hours (rounded to 2 dp); revenue is in your workspace currency.
Over MCP
The same engine is exposed as the run_report and report_metadata MCP tools,
so an agent can answer "how many billable hours per client last quarter?" directly.