Downtime
Downtime records capture when a machine stops and why. From these records Haltless computes uptime summaries and reliability KPIs (MTTR and MTBF), both per machine and across the fleet. All endpoints require a bearer JWT.
Endpoints
| Method | Path | Description |
|---|---|---|
POST | /api/v1/machines/{machine_id}/downtime | Record downtime |
GET | /api/v1/machines/{machine_id}/downtime | List a machine's downtime |
PUT | /api/v1/machines/{machine_id}/downtime/{record_id} | Update a downtime record |
POST | /api/v1/machines/{machine_id}/downtime/{record_id}/end | End an ongoing downtime |
GET | /api/v1/machines/{machine_id}/uptime-summary | Uptime summary |
GET | /api/v1/machines/{machine_id}/mttr-mtbf | MTTR and MTBF for a machine |
GET | /api/v1/fleet/downtime | Downtime across the fleet |
GET | /api/v1/fleet/mttr-mtbf | MTTR and MTBF across the fleet |
GET | /api/v1/reason-codes | List reason codes |
GET | /api/v1/reason-codes/tree | Reason codes as a tree |
POST | /api/v1/reason-codes | Create a reason code |
PUT | /api/v1/reason-codes/{code_id} | Update a reason code |
Record downtime
POST /api/v1/machines/{machine_id}/downtime
Requires an operator or administrator role.
| Field | Type | Required | Description |
|---|---|---|---|
started_at | datetime | Yes | When downtime began (ISO 8601 UTC) |
ended_at | datetime | No | When it ended; omit for ongoing downtime |
reason_type | string | No | One of planned, unplanned, changeover, maintenance (default unplanned) |
reason_code_id | uuid | No | A reason code to categorize the cause |
reason_note | string | No | Free-text note (up to 2,000 chars) |
{
"started_at": "2026-08-07T08:15:00Z",
"reason_type": "unplanned",
"reason_code_id": "b1c2...",
"reason_note": "Bearing failure on the main spindle."
}
Response — 201 Created
{
"id": "d3e4...",
"machine_id": "550e8400-e29b-41d4-a716-446655440000",
"started_at": "2026-08-07T08:15:00Z",
"ended_at": null,
"duration_minutes": null,
"reason_type": "unplanned",
"reason_code_id": "b1c2...",
"reason_code": {
"id": "b1c2...",
"code": "BRG-FAIL",
"label": "Bearing failure",
"category": "unplanned",
"oee_loss_category": "availability_loss"
},
"reason_note": "Bearing failure on the main spindle.",
"created_at": "2026-08-07T08:16:00Z"
}
List a machine's downtime
GET /api/v1/machines/{machine_id}/downtime
Paginated with page and page_size (default 20, max 100). Returns an array of downtime records.
Update and end downtime
PUT /api/v1/machines/{machine_id}/downtime/{record_id} updates a record's end time, reason, or note. POST /api/v1/machines/{machine_id}/downtime/{record_id}/end closes an ongoing downtime by setting its end time to now and computing duration_minutes. Both require an operator or administrator role.
Uptime summary
GET /api/v1/machines/{machine_id}/uptime-summary
When start and end are omitted, the last 30 days are used.
| Parameter | Type | Description |
|---|---|---|
start | datetime | Start of the period (ISO 8601 UTC) |
end | datetime | End of the period (ISO 8601 UTC) |
{
"machine_id": "550e8400-e29b-41d4-a716-446655440000",
"total_hours": 720.0,
"downtime_hours": 18.5,
"uptime_percent": 97.43,
"by_reason": {
"unplanned": 12.0,
"maintenance": 6.5
}
}
MTTR and MTBF (machine)
GET /api/v1/machines/{machine_id}/mttr-mtbf
Accepts a days query parameter (default 90, range 1–90).
{
"machine_id": "550e8400-e29b-41d4-a716-446655440000",
"mttr_hours": 2.5,
"mtbf_hours": 168.0,
"repair_event_count": 7,
"failure_event_count": 5,
"lookback_days": 90
}
- MTTR (Mean Time To Repair) averages the duration of repair events (
unplannedandmaintenance). It isnullif there are too few repair events. - MTBF (Mean Time Between Failures) averages the uptime between
unplannedfailures. It isnullif there are fewer than two failures.
Fleet downtime
GET /api/v1/fleet/downtime
Paginated downtime records across all machines, or filtered to one.
| Parameter | Type | Description |
|---|---|---|
machine_id | uuid | Filter by machine |
reason_type | string | One of planned, unplanned, changeover, maintenance |
status | string | ongoing or completed |
date_from | datetime | Records started on or after this time |
date_to | datetime | Records started on or before this time |
page | integer | Page number (default 1) |
page_size | integer | Items per page (default 20, max 100) |
sort_by | string | Column to sort by |
sort_dir | string | asc or desc |
Returns an items array with a pagination object.
Fleet MTTR and MTBF
GET /api/v1/fleet/mttr-mtbf
Accepts a days query parameter (default 90, range 1–90). Returns per-machine KPIs plus fleet-wide averages.
{
"machines": [
{
"machine_id": "550e8400-e29b-41d4-a716-446655440000",
"mttr_hours": 2.5,
"mtbf_hours": 168.0,
"repair_event_count": 7,
"failure_event_count": 5,
"lookback_days": 90
}
],
"fleet_mttr_hours": 2.5,
"fleet_mtbf_hours": 168.0
}
Reason codes
Reason codes are a hierarchical taxonomy for categorizing downtime causes and mapping them to OEE loss buckets.
List reason codes
GET /api/v1/reason-codes returns a flat list; GET /api/v1/reason-codes/tree returns the same codes as a nested hierarchy. Both accept an active_only query parameter (default true).
Create and update
POST /api/v1/reason-codes and PUT /api/v1/reason-codes/{code_id} require an account administrator role.
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | Short code (1–50 chars) |
label | string | Yes | Human-readable label (1–200 chars) |
category | string | Yes | One of planned, unplanned, changeover, maintenance |
oee_loss_category | string | Yes | One of availability_loss, performance_loss, quality_loss, not_scheduled |
description | string | No | Free-text description |
parent_id | uuid | No | Parent code for nesting |
sort_order | integer | No | Ordering hint (default 0) |
{
"code": "BRG-FAIL",
"label": "Bearing failure",
"category": "unplanned",
"oee_loss_category": "availability_loss"
}
Response — 201 Created
{
"id": "b1c2...",
"code": "BRG-FAIL",
"label": "Bearing failure",
"category": "unplanned",
"oee_loss_category": "availability_loss",
"description": null,
"parent_id": null,
"is_active": true,
"sort_order": 0,
"created_at": "2026-08-07T10:00:00Z"
}