Militime API

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

KeyUnitNotes
hours_trackedhoursAll tracked time
billable_hourshoursTime marked billable
non_billable_hourshours
entry_countcountNumber of time entries
billable_percentagepercentBillable ÷ total hours
billable_amountcurrencyRevenue, 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

  • labels resolves entity dimension ids (client/project/user/team) to display names.
  • Rows are sorted by the first metric, descending, then capped at limit (max 1000). truncated is true if there were more groups than returned.
  • Time bucket values: day/week → a date (YYYY-MM-DD, week = Monday), monthYYYY-MM, quarterYYYY-Q#, yearYYYY.
  • 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.