Charts
The charts endpoint exposes the same aggregated data that powers TrackMyMachines' built-in dashboards. Each chart type wraps an aggregator plus a configured ChartFilter, so passing the same query string you would use in the dashboard URL returns the data behind that chart.
Permissions
| Endpoint | Method | Read-only Access | Read-write Access | Description |
|---|---|---|---|---|
/api/v1/charts/:chart_type | GET | ✅ | ✅ | Retrieve the data for a chart |
GET /api/v1/charts/:chart_type
Required role: read-only or read-write
Path parameters:
chart_type: one of the supported chart types (see below). Unknown values return404 Not Foundwith{ "error": "Chart not found" }.
Supported chart types
chart_type | Description |
|---|---|
machine_utilisation | Spindle utilisation — uptime as a share of total available time. |
effective_utilisation | Effective utilisation — uptime plus productive downtime as a share of available time (excluding discounted downtime). |
utilisation_ranking | Machine utilisation ranked highest-first — one row per machine (or per cell / site via the grouping). |
machine_hours | Spindle uptime in hours — the time machines spent actively cutting. |
effective_hours | Effective hours — uptime plus productive downtime — over the selected period. |
downtime_hours | Downtime in hours over the selected period. |
downtime_analysis | Breakdown of how machine time was spent — uptime, productive downtime, unproductive downtime, discounted downtime, and unaccounted downtime. |
shift_breakdown | Utilisation broken down by shift pattern. |
calendar | Daily utilisation across the selected period (renders as a calendar heatmap in the dashboard). |
downtime_reason_hours | Time spent against each individual downtime reason. |
downtime_reason_percent | Downtime per reason as a fraction of available time. |
downtime_reason_category_hours | Time spent in each downtime reason category. |
downtime_reason_category_percent | Downtime per reason category as a fraction of available time. |
downtime_reason_horizontal | Downtime per reason ranked per entity — same rows as downtime_reason_hours, presented as ranked bars in the dashboard. |
downtime_reason_category_horizontal | Downtime per reason category ranked per entity. |
downtime_reason_pareto | Downtime reasons ranked by total time, with a cumulative share — the classic 80/20 view. |
energy | Energy consumption in kWh over the selected period. |
idle_energy | Energy consumed in kWh while machines were idle, with the idle time behind it. |
total_parts | Total parts counted across the window — a single whole-window figure. |
good_parts | Good parts (total minus scrap) across the window — a single whole-window figure. |
scrap_rate | Scrap as a 0–1 share of total parts across the window — a single whole-window figure. |
oee | Overall Equipment Effectiveness for the whole window — availability × performance × quality, with each factor's inputs. |
oee_availability | The availability factor for the whole window, with its inputs. |
oee_performance | The performance factor for the whole window, with its inputs. |
oee_quality | The quality factor for the whole window, with its inputs. |
Query parameters
Every parameter is optional — each chart type has sensible defaults (e.g. machine_utilisation defaults to the last 7 days bucketed by day).
from,to: ISO8601 start and end of the time range. Must be provided together; an unparseable value returns422 Unprocessable Entity.bucket: bucket size for time-series charts. One ofhour,day,week,month, ormax(a single bucket spanning the whole range). Buckets too coarse for the range are coerced to a finer one — check the response envelope for the bucket you actually got.group_by: how to group the data. One ofnone,machine,factory,area,shift_pattern.shift_type: one ofignore_shift,in_shift,out_of_shift,specific_shift. Defaults toin_shift.machine_foreign_ids[]: array of machine foreign IDs to filter by. A single bare value (machine_foreign_ids=CNC-01) is accepted as a one-element filter.shift_pattern_ids[]: array of shift pattern IDs to filter by.activity_reason_category_ids[]: array of activity reason category IDs to filter by.
Internal database IDs (machine_ids, etc.) are not accepted — only foreign / external identifiers cross the API boundary. Requests that include machine_ids will silently ignore it.
Period-over-period comparison (compare, previous_from, previous_to) is not supported on this endpoint and returns 400 Bad Request. Issue two requests with different windows instead.
Not every parameter is meaningful for every chart type — shift_breakdown always groups by shift_pattern, and the KPI types (the four oee* figures and the three part-count figures) always collapse to a single whole-window row regardless of bucket and group_by.
Example request
curl -X GET "https://your-org.trackmymachines.app/api/v1/charts/machine_utilisation?from=2025-05-20T00:00:00Z&to=2025-05-27T00:00:00Z&bucket=day&group_by=machine" \
-H "Authorization: Bearer YOUR_API_KEY"
Response shape
Every chart type returns the same envelope. group_by, bucket, from and to echo the resolved filter — defaults and coercions included — so you always see the window and grain the data actually covers:
{
"chart_type": "machine_utilisation",
"group_by": "machine",
"bucket": "day",
"from": "2025-05-20T00:00:00+00:00",
"to": "2025-05-27T00:00:00+00:00",
"rows": [
{
"entity_name": "CNC-01",
"from": "2025-05-20T00:00:00+00:00",
"to": "2025-05-21T00:00:00+00:00",
"uptime_seconds": 21600,
"downtime_seconds": 5400,
"offtime_seconds": 1800,
"productive_downtime_seconds": 3600,
"unproductive_downtime_seconds": 1800,
"discounted_downtime_seconds": 0,
"unaccounted_downtime_seconds": 0,
"total_seconds": 28800,
"percentage": 0.875,
"spindle_percentage": 0.75,
"shift_type": "in_shift",
"machine_foreign_id": "CNC-01"
}
]
}
The row fields depend on the chart type:
- Usage charts (
machine_utilisation,effective_utilisation,utilisation_ranking,machine_hours,effective_hours,downtime_hours,downtime_analysis,shift_breakdown,calendar): one row per entity per bucket, as in the example above. All durations are integer seconds;percentage/spindle_percentageare 0–1 fractions. - Downtime reason charts (
downtime_reason_hours,downtime_reason_percent, the_category_siblings and the_horizontalvariants):entity_name,bucket,duration_seconds, plusactivity_reason_nameoractivity_reason_category_namedepending on the grain. The_percenttypes addpercentage(downtime as a 0–1 fraction of available time). downtime_reason_pareto:activity_reason_name,duration_seconds,percent,cumulative_percent(both percents 0–100), ranked by duration.energy:entity_name,bucket,energy_kwh.idle_energy:entity_name,bucket,idle_seconds,idle_energy_kwh.- Part-count KPIs (
total_parts,good_parts,scrap_rate): exactly one row for the whole window —entity_name,good_parts,total_parts,scrap_parts,scrap_rate(0–1,nullwhen nothing was produced). - OEE KPIs (
oee,oee_availability,oee_performance,oee_quality): exactly one row for the whole window.factornames the requested figure andvaluecarries it (0–1,nullwhen uncomputable); the row also carries all four factors plus the inputs behind them —operating_seconds,planned_seconds,ideal_run_seconds,actual_run_seconds,good_parts,total_parts,scrap_parts,quantities_confirmed.
When the request is grouped by machine, each row carries machine_foreign_id so results can be joined back to the machine_foreign_ids you filtered by. Rows never contain internal database IDs.
Error responses
400 Bad Request—{ "error": "compare is not supported on the charts API" }whencompare/previous_from/previous_tois present.401 Unauthorized— missing, invalid, expired, or wrong-organisation API key.404 Not Found—{ "error": "Chart not found" }when:chart_typeis not in the supported list.422 Unprocessable Entity—from/tounparseable or provided without the other.