API reference
Machines
The Machines API reads and updates the machines a costing environment prices against: fetch one, see where it is used across calculations, and update it.
The Machines API reads and updates the machines a costing environment prices against: fetch one, see where it is used across calculations, and update it.
Auto-generated from the public OpenAPI spec — this page never drifts from the running API. Base URL
https://api.arcnm.io. Authenticate with theX-API-Keyheader (see Authentication).
One machine record, with the number of environments it is in
GET /api/v1/machines/{machine_id}
The machine as its record states it — rates, class, capabilities — plus environment_count: how many of your costing environments hold it in their fleet today, which is how far an edit to its rates reaches.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
machine_id |
path | string | yes | Identifier of the machine. |
Request
curl -X GET https://api.arcnm.io/api/v1/machines/{machine_id} \
-H "X-API-Key: $ARCNM_API_KEY"
import requests
resp = requests.get(
"https://api.arcnm.io/api/v1/machines/{machine_id}",
headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/machines/{machine_id}", {
method: "GET",
headers: {
"X-API-Key": process.env.ARCNM_API_KEY!,
},
})
const data = await resp.json()
Responses
| Status | Description |
|---|---|
200 |
Successful Response |
422 |
Validation Error |
Errors
Standard error responses — see the Errors catalog for the full envelope, request_id, and retry-safety table.
| Status | Code | When |
|---|---|---|
401 |
invalid_api_key |
Missing, malformed, or revoked API key. |
403 |
insufficient_scope |
The key is valid but lacks a scope this endpoint requires. |
404 |
not_found |
A referenced resource doesn't exist or isn't visible to your organisation. |
429 |
rate_limited |
Per-key or per-org rate limit exceeded — back off with jitter and retry. |
Response body 200
| Field | Type | Description |
|---|---|---|
burden_rate_eur |
number | Overhead burden added on top of the machine-hour rate, in EUR per hour. |
capabilities |
object | Raw stored capability matrix; empty for library-derived instances (see effective_capabilities). |
environment_count |
integer | Number of your costing environments whose fleet holds this machine today — the scope of an edit to its rates. Present on GET /machines/{machine_id}; absent on fleet rows. |
hourly_rate_eur |
number | Machine-hour rate in EUR per hour. |
id |
string | Unique identifier of the machine definition. |
klass |
string | Machine class (e.g. milling, turning, laser_cutter). |
model_no |
string | Vendor model number of the machine. |
name |
string | Human-readable name of the machine. |
programming_rate_eur |
number | Programming rate in EUR/h; null = the environment labour rate applies. |
rate_operator_eur_per_h |
number | Operator wage already contained in hourly_rate_eur, in EUR per hour. 0 means the rate covers the machine only and operator labour is billed separately. |
rate_operator_share |
number | Share of an operator this machine consumes while it runs (0-1); setup is always fully attended. Null falls back to the machine class default. |
setup_rate_eur |
number | Setup rate in EUR/h; null = the machine hourly rate applies. |
source |
string | 'library' if instantiated from a catalog entry, else 'custom'. |
subclass |
string | Machine subclass refining the class (e.g. small, medium, large). |
valid_from |
string | ISO date (YYYY-MM-DD) from which this machine definition is effective. |
valid_to |
string | ISO date (YYYY-MM-DD) the machine stops being effective; null = open-ended. |
vendor |
string | Manufacturer or vendor of the machine. |
Example response
{
"burden_rate_eur": 0,
"capabilities": {},
"environment_count": 0,
"hourly_rate_eur": 0,
"id": "string",
"klass": "string",
"model_no": "string",
"name": "string",
"programming_rate_eur": 0,
"rate_operator_eur_per_h": 0,
"rate_operator_share": 0,
"setup_rate_eur": 0,
"source": "custom",
"subclass": "string",
"valid_from": "string",
"valid_to": "string",
"vendor": "string"
}
Update Machine
PATCH /api/v1/machines/{machine_id}
Change one of your machines: its name, machine class, hourly rates (machine, burden, programming, setup, operator) and capability overrides. Calculations run afterwards use the new values.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
machine_id |
path | string | yes | Identifier of the machine. |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
burden_rate_eur |
number | no | Capital/overhead burden charged alongside the machine-hour rate in EUR/h, on run time and setup time alike; 0 = none. Omit to leave. |
capability_overrides |
object | no | Capability fields to change. For a library-derived machine these merge over the library default (sparse override); for a bespoke machine they merge into its own capability matrix. |
hourly_rate_eur |
number | no | New flat machine-hour rate in EUR/h; omit to leave. |
klass |
milling.3axis_vmc | milling.5axis_full | milling.indexable_3plus2 | turning.2axis_cnc | turning.live_tool | turning.swiss_type | turning.mill_integrex | press_brake | laser_cutter | plasma_cutter | guillotine_shear | tube_bender | turret_punch | waterjet | wire_edm | sinter.dmls | fdm_industrial | injection_molding_press | grinder.surface | grinder.cylindrical | slotter | sink_edm | weld_station | saw.band | saw.circular | drill.pillar |
no | Correct the machine's process class (e.g. a lathe entered from a milling template). The machine is re-based on the new class's standard capability matrix and detached from its catalogue entry, because that entry describes a different kind of machine; name, rates and fleet memberships are kept. Omit to leave. |
name |
string | no | New machine name; omit to leave. |
programming_rate_eur |
number | no | Programming rate in EUR/h; -1 clears it (fall back to the environment labour rate); omit to leave. |
rate_operator_eur_per_h |
number | no | Operator wage already contained in hourly_rate_eur — and in setup_rate_eur, which is the same rate on the setup envelope — in EUR/h; omit to leave. 0 means the rate covers the machine only and operator labour is billed separately — the default. Set it when the rate is all-in, so the operator is not charged twice. It cannot exceed either rate it is declared inside. |
rate_operator_share |
number | no | Share of an operator this machine consumes while it runs (0-1); omit to leave. Setup is always fully attended. Unset falls back to the machine class default. |
setup_rate_eur |
number | no | Setup rate in EUR/h; -1 clears it (fall back to the machine hourly rate); omit to leave. |
Request
curl -X PATCH https://api.arcnm.io/api/v1/machines/{machine_id} \
-H "X-API-Key: $ARCNM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"burden_rate_eur": 0,
"capability_overrides": {},
"hourly_rate_eur": 0,
"klass": "milling.3axis_vmc",
"name": "string",
"programming_rate_eur": 0,
"rate_operator_eur_per_h": 0,
"rate_operator_share": 0,
"setup_rate_eur": 0
}'
import requests
resp = requests.patch(
"https://api.arcnm.io/api/v1/machines/{machine_id}",
headers={"X-API-Key": "YOUR_API_KEY"},
json={
"burden_rate_eur": 0,
"capability_overrides": {},
"hourly_rate_eur": 0,
"klass": "milling.3axis_vmc",
"name": "string",
"programming_rate_eur": 0,
"rate_operator_eur_per_h": 0,
"rate_operator_share": 0,
"setup_rate_eur": 0
},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/machines/{machine_id}", {
method: "PATCH",
headers: {
"X-API-Key": process.env.ARCNM_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
"burden_rate_eur": 0,
"capability_overrides": {},
"hourly_rate_eur": 0,
"klass": "milling.3axis_vmc",
"name": "string",
"programming_rate_eur": 0,
"rate_operator_eur_per_h": 0,
"rate_operator_share": 0,
"setup_rate_eur": 0
}),
})
const data = await resp.json()
Responses
| Status | Description |
|---|---|
200 |
Successful Response |
422 |
Validation Error |
Errors
Standard error responses — see the Errors catalog for the full envelope, request_id, and retry-safety table.
| Status | Code | When |
|---|---|---|
401 |
invalid_api_key |
Missing, malformed, or revoked API key. |
403 |
insufficient_scope |
The key is valid but lacks a scope this endpoint requires. |
404 |
not_found |
A referenced resource doesn't exist or isn't visible to your organisation. |
409 |
conflict |
A conflicting change, or an Idempotency-Key reused with a different body. |
429 |
rate_limited |
Per-key or per-org rate limit exceeded — back off with jitter and retry. |
Response body 200
| Field | Type | Description |
|---|---|---|
burden_rate_eur |
number | Overhead burden added on top of the machine-hour rate, in EUR per hour. |
capabilities |
object | Raw stored capability matrix; empty for library-derived instances (see effective_capabilities). |
environment_count |
integer | Number of your costing environments whose fleet holds this machine today — the scope of an edit to its rates. Present on GET /machines/{machine_id}; absent on fleet rows. |
hourly_rate_eur |
number | Machine-hour rate in EUR per hour. |
id |
string | Unique identifier of the machine definition. |
klass |
string | Machine class (e.g. milling, turning, laser_cutter). |
model_no |
string | Vendor model number of the machine. |
name |
string | Human-readable name of the machine. |
programming_rate_eur |
number | Programming rate in EUR/h; null = the environment labour rate applies. |
rate_operator_eur_per_h |
number | Operator wage already contained in hourly_rate_eur, in EUR per hour. 0 means the rate covers the machine only and operator labour is billed separately. |
rate_operator_share |
number | Share of an operator this machine consumes while it runs (0-1); setup is always fully attended. Null falls back to the machine class default. |
setup_rate_eur |
number | Setup rate in EUR/h; null = the machine hourly rate applies. |
source |
string | 'library' if instantiated from a catalog entry, else 'custom'. |
subclass |
string | Machine subclass refining the class (e.g. small, medium, large). |
valid_from |
string | ISO date (YYYY-MM-DD) from which this machine definition is effective. |
valid_to |
string | ISO date (YYYY-MM-DD) the machine stops being effective; null = open-ended. |
vendor |
string | Manufacturer or vendor of the machine. |
Example response
{
"burden_rate_eur": 0,
"capabilities": {},
"environment_count": 0,
"hourly_rate_eur": 0,
"id": "string",
"klass": "string",
"model_no": "string",
"name": "string",
"programming_rate_eur": 0,
"rate_operator_eur_per_h": 0,
"rate_operator_share": 0,
"setup_rate_eur": 0,
"source": "custom",
"subclass": "string",
"valid_from": "string",
"valid_to": "string",
"vendor": "string"
}
The costing environments whose fleet holds a machine
GET /api/v1/machines/{machine_id}/usage
A machine record is shared by every environment whose fleet holds it, so a change to its hourly rate moves every part priced on it in each of them. This says how many, and which, so a save from one calculation's cost sheet can state its scope before it writes.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
machine_id |
path | string | yes | Identifier of the machine. |
Request
curl -X GET https://api.arcnm.io/api/v1/machines/{machine_id}/usage \
-H "X-API-Key: $ARCNM_API_KEY"
import requests
resp = requests.get(
"https://api.arcnm.io/api/v1/machines/{machine_id}/usage",
headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/machines/{machine_id}/usage", {
method: "GET",
headers: {
"X-API-Key": process.env.ARCNM_API_KEY!,
},
})
const data = await resp.json()
Responses
| Status | Description |
|---|---|
200 |
Successful Response |
422 |
Validation Error |
Errors
Standard error responses — see the Errors catalog for the full envelope, request_id, and retry-safety table.
| Status | Code | When |
|---|---|---|
401 |
invalid_api_key |
Missing, malformed, or revoked API key. |
403 |
insufficient_scope |
The key is valid but lacks a scope this endpoint requires. |
404 |
not_found |
A referenced resource doesn't exist or isn't visible to your organisation. |
429 |
rate_limited |
Per-key or per-org rate limit exceeded — back off with jitter and retry. |
Response body 200
| Field | Type | Description |
|---|---|---|
environment_count |
integer | Number of your costing environments whose fleet holds this machine today. An edit to the machine's own rate reaches every one of them. |
environments |
MachineUsageEnv[] | Those environments, enabled and disabled memberships alike. |
machine_id |
string | Identifier of the machine. |
Example response
{
"environment_count": 0,
"environments": [
{
"env_id": "string",
"env_name": "string",
"is_enabled": true
}
],
"machine_id": "string"
}