Machines
Machines are the core resource in Haltless. Every reading, alert, work order, and downtime record is attached to a machine. This page also covers machine groups, tag mappings, and unit preferences. All endpoints require a bearer JWT.
Endpoints
| Method | Path | Description |
|---|---|---|
POST | /api/v1/machines | Create a machine |
GET | /api/v1/machines | List machines |
GET | /api/v1/machines/{machine_id} | Get a machine |
PATCH | /api/v1/machines/{machine_id} | Update a machine |
DELETE | /api/v1/machines/{machine_id} | Deactivate a machine |
POST | /api/v1/machines/import | Bulk import from CSV or XLSX |
POST | /api/v1/machine-groups | Create a group |
GET | /api/v1/machine-groups | List groups |
GET | /api/v1/machine-groups/tree | Group hierarchy as a tree |
GET | /api/v1/machine-groups/{group_id} | Get a group with members |
PUT | /api/v1/machine-groups/{group_id} | Update a group |
DELETE | /api/v1/machine-groups/{group_id} | Delete a group |
PUT | /api/v1/machine-groups/{group_id}/members | Replace a group's members |
POST | /api/v1/tag-mappings/auto-map | Suggest standardized names for raw tags |
PATCH | /api/v1/tag-mappings/{mapping_id} | Correct a tag mapping |
POST | /api/v1/tag-mappings/{mapping_id}/confirm | Confirm a tag mapping |
GET | /api/v1/units/supported | List supported units and conversions |
GET | /api/v1/settings/units | Get unit preferences |
PATCH | /api/v1/settings/units | Update unit preferences |
Create a machine
POST /api/v1/machines
Requires an operator or administrator role.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Human-readable name (1–255 chars) |
machine_identifier | string | Yes | Unique identifier used during ingestion (1–255 chars) |
protocol | string | Yes | One of opc_ua, modbus_tcp, csv, json |
location | string | No | Physical location (up to 500 chars) |
{
"name": "CNC Mill #1",
"machine_identifier": "CNC-001",
"protocol": "json",
"location": "Building A, Line 3"
}
Response — 201 Created
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"tenant_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"name": "CNC Mill #1",
"machine_identifier": "CNC-001",
"protocol": "json",
"status": "offline",
"location": "Building A, Line 3",
"is_active": true,
"created_at": "2026-08-07T10:00:00Z",
"updated_at": "2026-08-07T10:00:00Z"
}
List machines
GET /api/v1/machines
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
page_size | integer | 20 | Items per page (max 100) |
group_id | uuid | — | Filter by machine group |
search | string | — | Match name or identifier (up to 200 chars) |
status | string | — | One of healthy, warning, critical, offline |
sort_by | string | name | One of name, machine_identifier, status, location, updated_at, created_at |
sort_dir | string | asc | asc or desc |
Response — 200 OK
{
"items": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"tenant_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"name": "CNC Mill #1",
"machine_identifier": "CNC-001",
"protocol": "json",
"status": "critical",
"location": "Building A, Line 3",
"is_active": true,
"created_at": "2026-08-07T10:00:00Z",
"updated_at": "2026-08-07T10:00:00Z"
}
],
"pagination": {
"total": 1,
"page": 1,
"page_size": 20
}
}
Get a machine
GET /api/v1/machines/{machine_id}
Returns a single machine. Returns 404 if the machine does not exist or is not accessible to you.
Update a machine
PATCH /api/v1/machines/{machine_id}
Requires an operator or administrator role. Include only the fields you want to change.
| Field | Type | Description |
|---|---|---|
name | string | New name (1–255 chars) |
location | string | New location |
status | string | One of healthy, warning, critical, offline |
is_active | boolean | Active flag |
Deactivate a machine
DELETE /api/v1/machines/{machine_id}
Requires an operator or administrator role. Deactivates the machine (a soft delete). Returns 204 No Content.
Bulk import
POST /api/v1/machines/import
Requires an operator or administrator role. Upload a CSV or XLSX file as multipart/form-data under the file field. Up to 500 rows per upload.
- Required columns:
name,machine_identifier,protocol - Optional columns:
location - Valid protocols:
opc_ua,modbus_tcp,csv,json
Response — 200 OK
{
"total_rows": 48,
"success_count": 45,
"failed_count": 3,
"errors": [
{ "row": 12, "reason": "Duplicate machine_identifier: CNC-003" }
],
"created_machine_ids": ["550e8400-e29b-41d4-a716-446655440000"]
}
Machine groups
Organize machines into a hierarchy of sites, lines, and departments.
Create a group
POST /api/v1/machine-groups
Requires an operator or administrator role.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Group name (1–200 chars) |
group_type | string | No | One of site, line, department, custom (default custom) |
description | string | No | Free-text description |
color | string | No | Hex color, for example #3B82F6 |
parent_id | uuid | No | Parent group for nesting |
machine_ids | array of uuid | No | Machines to add on creation |
Response — 201 Created
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "Building A",
"group_type": "site",
"description": "Main production facility",
"color": "#3B82F6",
"machine_count": 0,
"parent_id": null,
"created_at": "2026-08-07T10:00:00Z"
}
List groups and tree
GET /api/v1/machine-groups returns a flat list of groups. GET /api/v1/machine-groups/tree returns the same groups as a nested hierarchy, with each node carrying a children array.
Get, update, and delete a group
GET /api/v1/machine-groups/{group_id} returns a group including its machine_ids. PUT /api/v1/machine-groups/{group_id} and DELETE /api/v1/machine-groups/{group_id} require an operator or administrator role.
Replace group members
PUT /api/v1/machine-groups/{group_id}/members
Requires an operator or administrator role. Replaces the group's members with the supplied list.
{
"machine_ids": [
"550e8400-e29b-41d4-a716-446655440000",
"7c9e6679-7425-40de-944b-e07fc1f90ae7"
]
}
Tag mappings
Tag mappings translate a source system's raw tag names into standardized metric names. To list the mappings for a machine, see Sensor Data.
Suggest mappings
POST /api/v1/tag-mappings/auto-map
Requires an operator or administrator role. Submits raw tags and returns standardized-name suggestions, which are also saved for review.
| Field | Type | Required | Description |
|---|---|---|---|
tags | array | Yes | 1–50 raw-tag entries |
tags[].raw_tag | string | Yes | Original tag name (1–500 chars) |
tags[].machine_id | uuid | Yes | Machine the tag belongs to |
tags[].context | string | No | Optional hint about the tag |
{
"tags": [
{
"machine_id": "550e8400-e29b-41d4-a716-446655440000",
"raw_tag": "ns2_i1001_temp_motor_1"
}
]
}
Response — 200 OK
{
"results": [
{
"raw_tag": "ns2_i1001_temp_motor_1",
"standardized_name": "motor_temperature",
"unit": "celsius",
"confidence_score": 0.94
}
],
"saved_count": 1
}
Correct or confirm a mapping
PATCH /api/v1/tag-mappings/{mapping_id} updates a mapping's standardized name and unit. POST /api/v1/tag-mappings/{mapping_id}/confirm marks a suggested mapping as confirmed without changes. Both require an operator or administrator role.
{
"standardized_name": "motor_temperature",
"unit": "celsius"
}
Units
GET /api/v1/units/supported returns supported unit types and the available conversion pairs. It does not require authentication.
{
"conversions": [
{ "from_unit": "celsius", "to_unit": "fahrenheit" }
],
"default_preferences": {
"temperature": "celsius",
"pressure": "psi"
}
}
GET /api/v1/settings/units returns your account's unit preferences. PATCH /api/v1/settings/units updates them and requires an operator or administrator role.
{
"unit_preferences": {
"temperature": "fahrenheit",
"pressure": "bar"
}
}
Machine statuses
| Status | Description |
|---|---|
healthy | Metrics within normal baselines |
warning | A metric is above its warning threshold |
critical | A metric is above its critical threshold |
offline | No readings received recently |