API reference
Machine Library
The Machine Library API lets you create, list, retrieve, update, and delete machine library.
The Machine Library API lets you create, list, retrieve, update, and delete machine library.
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).
List Library
GET /api/v1/machine-library
The browsable machine park: the shared platform catalog plus your organization's own entries, in one list.
The response is a plain array, so the page position travels in the
Link (RFC 8288) and X-Next-Cursor / X-Has-More response headers.
Paginated. Pass
cursor(from the previous response) to fetch the next page;limitcaps the page size.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
klass |
query | string | no | Filter to a single machine class (e.g. milling.5axis_full). |
cursor |
query | string | no | Opaque position token from the previous page's next_cursor (or the Link / X-Next-Cursor response header). Omit it for the first page. Keep every other query parameter identical for the whole walk — a cursor replayed against different filters is rejected. |
limit |
query | integer | no | Maximum rows to return in one page. |
offset |
query | integer | no | Rows to skip. Superseded by cursor, which is stable under concurrent writes; kept for existing integrations. Bounded — past the cap, page with cursor. |
Request
curl -X GET https://api.arcnm.io/api/v1/machine-library \
-H "X-API-Key: $ARCNM_API_KEY"
import requests
resp = requests.get(
"https://api.arcnm.io/api/v1/machine-library",
headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/machine-library", {
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. |
429 |
rate_limited |
Per-key or per-org rate limit exceeded — back off with jitter and retry. |
Create Library Entry
POST /api/v1/machine-library
Add a tenant-private machine to the library. Platform-catalog
entries are curated out-of-band (seed), never via this endpoint —
the row is always stamped with the caller's org_id.
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
default_capabilities |
MachineCapabilities | yes | Default capability matrix for the type; instances override individual fields. |
default_vdi_3258 |
VDI3258Inputs | no | Optional VDI 3258 cost-structure defaults enabling (machine, region) hour-rate resolution. |
is_generic |
boolean | no | True for a class-default type template; False for a representative named machine. |
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 | saw.band | saw.circular |
yes | Machine class (process family), e.g. milling.5axis_full. |
model_no |
string | yes | Vendor model number, or a generic-type slug. |
name |
string | yes | Human-readable catalog name (e.g. '3-axis VMC — generic' or 'DMG MORI CMX 800 V'). |
nominal_hourly_rate_eur |
number | no | Type-default machine-hour rate in EUR/h; copied into an instance on instantiation. |
nominal_rate_operator_eur_per_h |
number | no | Operator wage already contained in nominal_hourly_rate_eur, in EUR per hour; copied into an instance alongside the rate. 0 means the rate is machine-only and operator labour is billed separately. |
nominal_rate_operator_share |
number | no | Operator attendance the nominal rate was built at (0-1), and the type's run-attendance default. NULL falls back to the class default. |
subclass |
small | medium | large |
no | Size tier of the machine within its class (small/medium/large). |
valid_from |
string | yes | Date from which this library entry is effective (ISO 8601). |
valid_to |
string | no | Date after which this entry is superseded; null if open-ended (ISO 8601). |
vendor |
string | yes | Machine manufacturer / vendor (or 'generic'). |
Request
curl -X POST https://api.arcnm.io/api/v1/machine-library \
-H "X-API-Key: $ARCNM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"vendor": "string",
"model_no": "string",
"klass": "milling.3axis_vmc",
"default_capabilities": {
"axes_indexable": 0,
"axes_simultaneous": 0,
"certifications": [
"string"
],
"chatter_stability_lobe": {
"rpm_to_max_axial_depth_mm": [
{
"max_axial_depth_mm": 0,
"rpm": 0
}
]
},
"coolant": [
"flood"
],
"iso_286_achievable_grade": "IT01",
"klass": "milling.3axis_vmc",
"max_material_thickness_mm": 0,
"max_part_envelope_mm": [
null
],
"max_setups_per_part": 6,
"max_spindle_rpm": 0,
"max_table_load_kg": 0,
"max_tool_diameter_mm": 0,
"max_tool_length_mm": 0,
"min_material_thickness_mm": 0,
"nominal_tool_change_time_s_by_class": {},
"pallet_change_time_s": 0,
"positioning_accuracy_mm": 0.01,
"rapid_traverse_m_per_min": 24,
"repeatability_mm": 0.005,
"saw_blade_cost_eur": 0,
"saw_blade_life_mm2": 0,
"saw_blade_type": "bimetal",
"saw_kerf_mm": 0,
"schema_version": "1.0.0",
"spindle_power_kw": 0,
"subclass": "small",
"vdi_3258": {
"acquisition_cost_eur": 0,
"annual_hours_T_G": 0,
"annual_hours_T_IH": 0,
"annual_hours_T_ST": 0,
"capital_interest_rate": 0,
"depreciation_life_h": 0,
"energy_eur_per_kwh": 0,
"energy_kw": 0,
"floor_space_m2": 0,
"maintenance_eur_per_year": 0,
"operator_hourly_eur": 0,
"operator_share": 0,
"space_eur_per_m2_y": 0,
"tooling_eur_per_year": 0
},
"workholding": [
"vise.3jaw"
]
},
"valid_from": "2026-06-01"
}'
import requests
resp = requests.post(
"https://api.arcnm.io/api/v1/machine-library",
headers={"X-API-Key": "YOUR_API_KEY"},
json={
"name": "string",
"vendor": "string",
"model_no": "string",
"klass": "milling.3axis_vmc",
"default_capabilities": {
"axes_indexable": 0,
"axes_simultaneous": 0,
"certifications": [
"string"
],
"chatter_stability_lobe": {
"rpm_to_max_axial_depth_mm": [
{
"max_axial_depth_mm": 0,
"rpm": 0
}
]
},
"coolant": [
"flood"
],
"iso_286_achievable_grade": "IT01",
"klass": "milling.3axis_vmc",
"max_material_thickness_mm": 0,
"max_part_envelope_mm": [
None
],
"max_setups_per_part": 6,
"max_spindle_rpm": 0,
"max_table_load_kg": 0,
"max_tool_diameter_mm": 0,
"max_tool_length_mm": 0,
"min_material_thickness_mm": 0,
"nominal_tool_change_time_s_by_class": {},
"pallet_change_time_s": 0,
"positioning_accuracy_mm": 0.01,
"rapid_traverse_m_per_min": 24,
"repeatability_mm": 0.005,
"saw_blade_cost_eur": 0,
"saw_blade_life_mm2": 0,
"saw_blade_type": "bimetal",
"saw_kerf_mm": 0,
"schema_version": "1.0.0",
"spindle_power_kw": 0,
"subclass": "small",
"vdi_3258": {
"acquisition_cost_eur": 0,
"annual_hours_T_G": 0,
"annual_hours_T_IH": 0,
"annual_hours_T_ST": 0,
"capital_interest_rate": 0,
"depreciation_life_h": 0,
"energy_eur_per_kwh": 0,
"energy_kw": 0,
"floor_space_m2": 0,
"maintenance_eur_per_year": 0,
"operator_hourly_eur": 0,
"operator_share": 0,
"space_eur_per_m2_y": 0,
"tooling_eur_per_year": 0
},
"workholding": [
"vise.3jaw"
]
},
"valid_from": "2026-06-01"
},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/machine-library", {
method: "POST",
headers: {
"X-API-Key": process.env.ARCNM_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "string",
"vendor": "string",
"model_no": "string",
"klass": "milling.3axis_vmc",
"default_capabilities": {
"axes_indexable": 0,
"axes_simultaneous": 0,
"certifications": [
"string"
],
"chatter_stability_lobe": {
"rpm_to_max_axial_depth_mm": [
{
"max_axial_depth_mm": 0,
"rpm": 0
}
]
},
"coolant": [
"flood"
],
"iso_286_achievable_grade": "IT01",
"klass": "milling.3axis_vmc",
"max_material_thickness_mm": 0,
"max_part_envelope_mm": [
null
],
"max_setups_per_part": 6,
"max_spindle_rpm": 0,
"max_table_load_kg": 0,
"max_tool_diameter_mm": 0,
"max_tool_length_mm": 0,
"min_material_thickness_mm": 0,
"nominal_tool_change_time_s_by_class": {},
"pallet_change_time_s": 0,
"positioning_accuracy_mm": 0.01,
"rapid_traverse_m_per_min": 24,
"repeatability_mm": 0.005,
"saw_blade_cost_eur": 0,
"saw_blade_life_mm2": 0,
"saw_blade_type": "bimetal",
"saw_kerf_mm": 0,
"schema_version": "1.0.0",
"spindle_power_kw": 0,
"subclass": "small",
"vdi_3258": {
"acquisition_cost_eur": 0,
"annual_hours_T_G": 0,
"annual_hours_T_IH": 0,
"annual_hours_T_ST": 0,
"capital_interest_rate": 0,
"depreciation_life_h": 0,
"energy_eur_per_kwh": 0,
"energy_kw": 0,
"floor_space_m2": 0,
"maintenance_eur_per_year": 0,
"operator_hourly_eur": 0,
"operator_share": 0,
"space_eur_per_m2_y": 0,
"tooling_eur_per_year": 0
},
"workholding": [
"vise.3jaw"
]
},
"valid_from": "2026-06-01"
}),
})
const data = await resp.json()
Responses
| Status | Description |
|---|---|
201 |
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. |
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 201
| Field | Type | Description |
|---|---|---|
default_capabilities |
object | Default capability matrix (axes, envelope, spindle, tolerances). Null on the shared platform catalog for integration callers; populated for your own catalog entries. |
default_vdi_3258 |
object | Optional VDI 3258 cost structure for (machine, region) rate resolution. |
id |
string | Unique identifier of the library entry. |
is_generic |
boolean | True for a class-default type; False for a representative named machine. |
klass |
string | Machine class (process family). |
model_no |
string | Vendor model number, or generic-type slug. |
name |
string | Human-readable catalog name. |
nominal_hourly_rate_eur |
number | Type-default machine-hour rate in EUR/h. Null on the shared platform catalog for integration callers; populated for your own catalog entries. |
nominal_rate_operator_eur_per_h |
number | Operator wage already contained in nominal_hourly_rate_eur, in EUR/h. 0 means the rate is machine-only and operator labour is billed separately. Null on the shared platform catalog for integration callers, alongside the rate it qualifies. |
nominal_rate_operator_share |
number | Operator attendance the nominal rate was built at (0-1), and the type's run-attendance default. Null when not declared. |
org_id |
string | Owning organisation; null for a platform-shared catalog entry. |
owner_scope |
string | 'platform' for the shared catalog, 'tenant' for a private addition. |
subclass |
string | Size tier within the class. |
valid_from |
string | ISO date this entry becomes effective. |
valid_to |
string | ISO date this entry is superseded; null = open-ended. |
vendor |
string | Machine manufacturer / vendor. |
Example response
{
"default_capabilities": {},
"default_vdi_3258": {},
"id": "string",
"is_generic": true,
"klass": "string",
"model_no": "string",
"name": "string",
"nominal_hourly_rate_eur": 0,
"nominal_rate_operator_eur_per_h": 0,
"nominal_rate_operator_share": 0,
"org_id": "string",
"owner_scope": "string",
"subclass": "string",
"valid_from": "string",
"valid_to": "string",
"vendor": "string"
}
Delete Library Entry
DELETE /api/v1/machine-library/{entry_id}
Delete a tenant-private entry. Refused (409) while any environment machine still references it — a library-derived instance resolves its capabilities from the entry, so detach those machines first.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
entry_id |
path | string | yes | Identifier of the entry. |
Request
curl -X DELETE https://api.arcnm.io/api/v1/machine-library/{entry_id} \
-H "X-API-Key: $ARCNM_API_KEY"
import requests
resp = requests.delete(
"https://api.arcnm.io/api/v1/machine-library/{entry_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/machine-library/{entry_id}", {
method: "DELETE",
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. |
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 |
|---|---|---|
message |
string | Human-readable result of the operation. |
Example response
{
"message": "string"
}
Get Library Entry
GET /api/v1/machine-library/{entry_id}
Fetch one machine-library entry.
Environments instantiate machines by library_entry_id, so a caller
holding one previously had to page the whole catalog to resolve it.
Redaction is identical to the list: platform-catalog rows lose our cost structure for integration / MCP callers, tenant-private rows pass through.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
entry_id |
path | string | yes | Identifier of the entry. |
Request
curl -X GET https://api.arcnm.io/api/v1/machine-library/{entry_id} \
-H "X-API-Key: $ARCNM_API_KEY"
import requests
resp = requests.get(
"https://api.arcnm.io/api/v1/machine-library/{entry_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/machine-library/{entry_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 |
|---|---|---|
default_capabilities |
object | Default capability matrix (axes, envelope, spindle, tolerances). Null on the shared platform catalog for integration callers; populated for your own catalog entries. |
default_vdi_3258 |
object | Optional VDI 3258 cost structure for (machine, region) rate resolution. |
id |
string | Unique identifier of the library entry. |
is_generic |
boolean | True for a class-default type; False for a representative named machine. |
klass |
string | Machine class (process family). |
model_no |
string | Vendor model number, or generic-type slug. |
name |
string | Human-readable catalog name. |
nominal_hourly_rate_eur |
number | Type-default machine-hour rate in EUR/h. Null on the shared platform catalog for integration callers; populated for your own catalog entries. |
nominal_rate_operator_eur_per_h |
number | Operator wage already contained in nominal_hourly_rate_eur, in EUR/h. 0 means the rate is machine-only and operator labour is billed separately. Null on the shared platform catalog for integration callers, alongside the rate it qualifies. |
nominal_rate_operator_share |
number | Operator attendance the nominal rate was built at (0-1), and the type's run-attendance default. Null when not declared. |
org_id |
string | Owning organisation; null for a platform-shared catalog entry. |
owner_scope |
string | 'platform' for the shared catalog, 'tenant' for a private addition. |
subclass |
string | Size tier within the class. |
valid_from |
string | ISO date this entry becomes effective. |
valid_to |
string | ISO date this entry is superseded; null = open-ended. |
vendor |
string | Machine manufacturer / vendor. |
Example response
{
"default_capabilities": {},
"default_vdi_3258": {},
"id": "string",
"is_generic": true,
"klass": "string",
"model_no": "string",
"name": "string",
"nominal_hourly_rate_eur": 0,
"nominal_rate_operator_eur_per_h": 0,
"nominal_rate_operator_share": 0,
"org_id": "string",
"owner_scope": "string",
"subclass": "string",
"valid_from": "string",
"valid_to": "string",
"vendor": "string"
}
Update Library Entry
PATCH /api/v1/machine-library/{entry_id}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
entry_id |
path | string | yes | Identifier of the entry. |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
default_capabilities |
object | no | |
default_vdi_3258 |
object | no | |
model_no |
string | no | |
name |
string | no | |
nominal_hourly_rate_eur |
number | no | |
nominal_rate_operator_eur_per_h |
number | no | |
nominal_rate_operator_share |
number | no | |
valid_to |
string | no | |
vendor |
string | no |
Request
curl -X PATCH https://api.arcnm.io/api/v1/machine-library/{entry_id} \
-H "X-API-Key: $ARCNM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"default_capabilities": {},
"default_vdi_3258": {},
"model_no": "string",
"name": "string",
"nominal_hourly_rate_eur": 0,
"nominal_rate_operator_eur_per_h": 0,
"nominal_rate_operator_share": 0,
"valid_to": "2026-06-01",
"vendor": "string"
}'
import requests
resp = requests.patch(
"https://api.arcnm.io/api/v1/machine-library/{entry_id}",
headers={"X-API-Key": "YOUR_API_KEY"},
json={
"default_capabilities": {},
"default_vdi_3258": {},
"model_no": "string",
"name": "string",
"nominal_hourly_rate_eur": 0,
"nominal_rate_operator_eur_per_h": 0,
"nominal_rate_operator_share": 0,
"valid_to": "2026-06-01",
"vendor": "string"
},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/machine-library/{entry_id}", {
method: "PATCH",
headers: {
"X-API-Key": process.env.ARCNM_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
"default_capabilities": {},
"default_vdi_3258": {},
"model_no": "string",
"name": "string",
"nominal_hourly_rate_eur": 0,
"nominal_rate_operator_eur_per_h": 0,
"nominal_rate_operator_share": 0,
"valid_to": "2026-06-01",
"vendor": "string"
}),
})
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 |
|---|---|---|
default_capabilities |
object | Default capability matrix (axes, envelope, spindle, tolerances). Null on the shared platform catalog for integration callers; populated for your own catalog entries. |
default_vdi_3258 |
object | Optional VDI 3258 cost structure for (machine, region) rate resolution. |
id |
string | Unique identifier of the library entry. |
is_generic |
boolean | True for a class-default type; False for a representative named machine. |
klass |
string | Machine class (process family). |
model_no |
string | Vendor model number, or generic-type slug. |
name |
string | Human-readable catalog name. |
nominal_hourly_rate_eur |
number | Type-default machine-hour rate in EUR/h. Null on the shared platform catalog for integration callers; populated for your own catalog entries. |
nominal_rate_operator_eur_per_h |
number | Operator wage already contained in nominal_hourly_rate_eur, in EUR/h. 0 means the rate is machine-only and operator labour is billed separately. Null on the shared platform catalog for integration callers, alongside the rate it qualifies. |
nominal_rate_operator_share |
number | Operator attendance the nominal rate was built at (0-1), and the type's run-attendance default. Null when not declared. |
org_id |
string | Owning organisation; null for a platform-shared catalog entry. |
owner_scope |
string | 'platform' for the shared catalog, 'tenant' for a private addition. |
subclass |
string | Size tier within the class. |
valid_from |
string | ISO date this entry becomes effective. |
valid_to |
string | ISO date this entry is superseded; null = open-ended. |
vendor |
string | Machine manufacturer / vendor. |
Example response
{
"default_capabilities": {},
"default_vdi_3258": {},
"id": "string",
"is_generic": true,
"klass": "string",
"model_no": "string",
"name": "string",
"nominal_hourly_rate_eur": 0,
"nominal_rate_operator_eur_per_h": 0,
"nominal_rate_operator_share": 0,
"org_id": "string",
"owner_scope": "string",
"subclass": "string",
"valid_from": "string",
"valid_to": "string",
"vendor": "string"
}
Rate Calculator
POST /api/v1/machine-library/rate-calculator
Compute a VDI 3258 machine-hour rate from cost-structure inputs.
Pure computation — nothing is persisted. Use the returned
total_per_h as a library entry's nominal rate, or store the
inputs as default_vdi_3258 for region-aware resolution.
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
acquisition_cost_eur |
number | yes | Machine acquisition (replacement) cost, in EUR. |
annual_hours_T_G |
number | yes | VDI 3258 total annual attendance hours (T_G), in hours per year. |
annual_hours_T_IH |
number | yes | VDI 3258 annual maintenance/repair hours (T_IH), in hours per year. |
annual_hours_T_ST |
number | yes | VDI 3258 annual standstill (idle) hours (T_ST), in hours per year. |
capital_interest_rate |
number | yes | Imputed annual interest rate on tied-up capital (0–1, e.g. 0.06 = 6%). |
depreciation_life_h |
number | yes | Depreciation life of the machine, in operating hours. |
energy_eur_per_kwh |
number | yes | Electricity price, in EUR per kilowatt-hour. |
energy_kw |
number | yes | Average electrical power draw while running, in kilowatts. |
floor_space_m2 |
number | yes | Floor space occupied by the machine, in square metres. |
maintenance_eur_per_year |
number | yes | Annual maintenance spend for the machine, in EUR per year. |
operator_hourly_eur |
number | yes | Fully-loaded operator labour cost, in EUR per hour. |
operator_share |
number | yes | Fraction of an operator's time allocated to this machine (0–1). |
space_eur_per_m2_y |
number | yes | Annual floor-space cost rate, in EUR per square metre per year. |
tooling_eur_per_year |
number | yes | Annual perishable-tooling spend for the machine, in EUR per year. |
Request
curl -X POST https://api.arcnm.io/api/v1/machine-library/rate-calculator \
-H "X-API-Key: $ARCNM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"acquisition_cost_eur": 0,
"depreciation_life_h": 0,
"annual_hours_T_G": 0,
"annual_hours_T_ST": 0,
"annual_hours_T_IH": 0,
"capital_interest_rate": 0,
"space_eur_per_m2_y": 0,
"floor_space_m2": 0,
"energy_kw": 0,
"energy_eur_per_kwh": 0,
"operator_hourly_eur": 0,
"operator_share": 0,
"maintenance_eur_per_year": 0,
"tooling_eur_per_year": 0
}'
import requests
resp = requests.post(
"https://api.arcnm.io/api/v1/machine-library/rate-calculator",
headers={"X-API-Key": "YOUR_API_KEY"},
json={
"acquisition_cost_eur": 0,
"depreciation_life_h": 0,
"annual_hours_T_G": 0,
"annual_hours_T_ST": 0,
"annual_hours_T_IH": 0,
"capital_interest_rate": 0,
"space_eur_per_m2_y": 0,
"floor_space_m2": 0,
"energy_kw": 0,
"energy_eur_per_kwh": 0,
"operator_hourly_eur": 0,
"operator_share": 0,
"maintenance_eur_per_year": 0,
"tooling_eur_per_year": 0
},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/machine-library/rate-calculator", {
method: "POST",
headers: {
"X-API-Key": process.env.ARCNM_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
"acquisition_cost_eur": 0,
"depreciation_life_h": 0,
"annual_hours_T_G": 0,
"annual_hours_T_ST": 0,
"annual_hours_T_IH": 0,
"capital_interest_rate": 0,
"space_eur_per_m2_y": 0,
"floor_space_m2": 0,
"energy_kw": 0,
"energy_eur_per_kwh": 0,
"operator_hourly_eur": 0,
"operator_share": 0,
"maintenance_eur_per_year": 0,
"tooling_eur_per_year": 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. |
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 |
|---|---|---|
annual_hours_T_G |
number | |
annual_hours_T_L |
number | |
capital_cost_per_h |
number | |
depreciation_per_h |
number | |
energy_per_h |
number | |
maintenance_per_h |
number | |
operator_share_per_h |
number | |
space_per_h |
number | |
tooling_allocation_per_h |
number | |
total_per_h |
number |
Example response
{
"annual_hours_T_G": 0,
"annual_hours_T_L": 0,
"capital_cost_per_h": 0,
"depreciation_per_h": 0,
"energy_per_h": 0,
"maintenance_per_h": 0,
"operator_share_per_h": 0,
"space_per_h": 0,
"tooling_allocation_per_h": 0,
"total_per_h": 0
}
Library Usage
GET /api/v1/machine-library/usage
Which environment fleets actually use each machine-library entry.
A library entry is a type — a template. It takes part in calculations only after a machine has been instantiated from it into an environment's fleet. This endpoint reports, per entry, the environments of YOUR organization whose active fleet contains such a machine, so a type that no calculation will ever use is visible as exactly that.
Entries with no usage are omitted — treat absence as "not in any fleet".
Request
curl -X GET https://api.arcnm.io/api/v1/machine-library/usage \
-H "X-API-Key: $ARCNM_API_KEY"
import requests
resp = requests.get(
"https://api.arcnm.io/api/v1/machine-library/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/machine-library/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. |
429 |
rate_limited |
Per-key or per-org rate limit exceeded — back off with jitter and retry. |