ARCNM

API reference

Folders

The Folders API lets you create, list, retrieve, update, and delete folders.

The Folders API lets you create, list, retrieve, update, and delete folders.

Auto-generated from the public OpenAPI spec — this page never drifts from the running API. Base URL https://api.arcnm.io. Authenticate with the X-API-Key header (see Authentication).

List folders

GET /api/v1/folders

All folders for the org, each with its direct (non-recursive) part count.

The tree is small enough to ship flat — the client assembles parent/child structure from parent_id.

Request

curl -X GET https://api.arcnm.io/api/v1/folders \
  -H "X-API-Key: $ARCNM_API_KEY"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/folders",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/folders", {
  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.

Response body 200

Field Type Description
count integer Total number of folders.
data PartFolderPublic[] All folders for the org.

Example response

{
  "count": 0,
  "data": [
    {
      "created_at": "2026-06-01T12:00:00Z",
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name": "string",
      "parent_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "part_count": 0,
      "updated_at": "2026-06-01T12:00:00Z"
    }
  ]
}

Create a folder

POST /api/v1/folders

Request body (application/json)

Field Type Required Description
name string yes Folder name, shown in the workspace tree. Unique among its siblings.
parent_id string no ID of the parent folder; null creates a top-level folder.

Request

curl -X POST https://api.arcnm.io/api/v1/folders \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string"
  }'
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/folders",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "name": "string"
    },
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/folders", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "name": "string"
  }),
})
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
created_at string Timestamp when the folder was created (UTC, ISO 8601).
id string Unique identifier of the folder.
name string Folder name, shown in the workspace tree. Unique among its siblings.
parent_id string ID of the parent folder; null for a top-level folder.
part_count integer Number of parts filed directly in this folder (excludes subfolders).
updated_at string Timestamp when the folder was last updated (UTC, ISO 8601).

Example response

{
  "created_at": "2026-06-01T12:00:00Z",
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "string",
  "parent_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "part_count": 0,
  "updated_at": "2026-06-01T12:00:00Z"
}

Delete a folder

DELETE /api/v1/folders/{folder_id}

Parameters

Name In Type Required Description
folder_id path string yes Identifier of the folder.

Request

curl -X DELETE https://api.arcnm.io/api/v1/folders/{folder_id} \
  -H "X-API-Key: $ARCNM_API_KEY"
import requests

resp = requests.delete(
    "https://api.arcnm.io/api/v1/folders/{folder_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/folders/{folder_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

Example response

{
  "message": "string"
}

Get a folder

GET /api/v1/folders/{folder_id}

Fetch a single folder.

Parts carry a folder_id, so a client holding one previously had to list the whole tree to resolve it to a name.

Parameters

Name In Type Required Description
folder_id path string yes Identifier of the folder.

Request

curl -X GET https://api.arcnm.io/api/v1/folders/{folder_id} \
  -H "X-API-Key: $ARCNM_API_KEY"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/folders/{folder_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/folders/{folder_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
created_at string Timestamp when the folder was created (UTC, ISO 8601).
id string Unique identifier of the folder.
name string Folder name, shown in the workspace tree. Unique among its siblings.
parent_id string ID of the parent folder; null for a top-level folder.
part_count integer Number of parts filed directly in this folder (excludes subfolders).
updated_at string Timestamp when the folder was last updated (UTC, ISO 8601).

Example response

{
  "created_at": "2026-06-01T12:00:00Z",
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "string",
  "parent_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "part_count": 0,
  "updated_at": "2026-06-01T12:00:00Z"
}

Rename or move a folder

PATCH /api/v1/folders/{folder_id}

Parameters

Name In Type Required Description
folder_id path string yes Identifier of the folder.

Request body (application/json)

Field Type Required Description
name string no New folder name.
parent_id string no New parent folder; null moves the folder to the workspace root.

Request

curl -X PATCH https://api.arcnm.io/api/v1/folders/{folder_id} \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string",
    "parent_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  }'
import requests

resp = requests.patch(
    "https://api.arcnm.io/api/v1/folders/{folder_id}",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "name": "string",
        "parent_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    },
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/folders/{folder_id}", {
  method: "PATCH",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "name": "string",
    "parent_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  }),
})
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
created_at string Timestamp when the folder was created (UTC, ISO 8601).
id string Unique identifier of the folder.
name string Folder name, shown in the workspace tree. Unique among its siblings.
parent_id string ID of the parent folder; null for a top-level folder.
part_count integer Number of parts filed directly in this folder (excludes subfolders).
updated_at string Timestamp when the folder was last updated (UTC, ISO 8601).

Example response

{
  "created_at": "2026-06-01T12:00:00Z",
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "string",
  "parent_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "part_count": 0,
  "updated_at": "2026-06-01T12:00:00Z"
}

Folder spend rollup

GET /api/v1/folders/{folder_id}/summary

Rollup scoped to a folder and all of its subfolders.

Parameters

Name In Type Required Description
folder_id path string yes Identifier of the folder.

Request

curl -X GET https://api.arcnm.io/api/v1/folders/{folder_id}/summary \
  -H "X-API-Key: $ARCNM_API_KEY"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/folders/{folder_id}/summary",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/folders/{folder_id}/summary", {
  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
calculation_count integer Succeeded calculations counted in this rollup.
currency string Currency of the money figures.
effective_annual_cost_eur number Σ over scoped parts of the current TOTAL annual cost — production plus inventory holding at the current lot where known, else the production spend. The honest denominator for a savings percentage: savings include holding relief, so dividing by production spend alone can overstate the fraction.
folder_id string The folder this rollup is scoped to; null means the whole workspace.
part_count integer Parts in this folder and all its subfolders.
potential_savings_eur number Σ over scoped parts of the net annual saving of moving to the recommended (holding-aware) lot size, EUR — production plus inventory holding.
quoted_part_count integer Parts in scope that have at least one succeeded calculation.
total_annual_spend_eur number Σ over scoped parts of (latest should-cost unit price × annual volume), EUR.

Example response

{
  "calculation_count": 0,
  "currency": "EUR",
  "effective_annual_cost_eur": 0,
  "folder_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "part_count": 0,
  "potential_savings_eur": 0,
  "quoted_part_count": 0,
  "total_annual_spend_eur": 0
}

Move parts into a folder

POST /api/v1/folders/move-parts

Request body (application/json)

Field Type Required Description
folder_id string no Destination folder; null unfiles the parts (moves them to the root).
part_ids string[] yes Parts to (re-)file.

Request

curl -X POST https://api.arcnm.io/api/v1/folders/move-parts \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "part_ids": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    ]
  }'
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/folders/move-parts",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "part_ids": [
            "3fa85f64-5717-4562-b3fc-2c963f66afa6"
        ]
    },
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/folders/move-parts", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "part_ids": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    ]
  }),
})
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
moved integer Number of parts actually re-filed.
not_found string[] Ids that were skipped because no such part exists in this workspace, capped at 100 entries. Empty on a fully successful move. Compare moved against requested for the true count — that pair is never truncated.
requested integer Number of distinct part ids you asked about.

Example response

{
  "moved": 0,
  "not_found": [
    "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  ],
  "requested": 0
}

Workspace spend rollup

GET /api/v1/folders/summary

Rollup over the entire workspace (all parts, filed or not).

Request

curl -X GET https://api.arcnm.io/api/v1/folders/summary \
  -H "X-API-Key: $ARCNM_API_KEY"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/folders/summary",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/folders/summary", {
  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.

Response body 200

Field Type Description
calculation_count integer Succeeded calculations counted in this rollup.
currency string Currency of the money figures.
effective_annual_cost_eur number Σ over scoped parts of the current TOTAL annual cost — production plus inventory holding at the current lot where known, else the production spend. The honest denominator for a savings percentage: savings include holding relief, so dividing by production spend alone can overstate the fraction.
folder_id string The folder this rollup is scoped to; null means the whole workspace.
part_count integer Parts in this folder and all its subfolders.
potential_savings_eur number Σ over scoped parts of the net annual saving of moving to the recommended (holding-aware) lot size, EUR — production plus inventory holding.
quoted_part_count integer Parts in scope that have at least one succeeded calculation.
total_annual_spend_eur number Σ over scoped parts of (latest should-cost unit price × annual volume), EUR.

Example response

{
  "calculation_count": 0,
  "currency": "EUR",
  "effective_annual_cost_eur": 0,
  "folder_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "part_count": 0,
  "potential_savings_eur": 0,
  "quoted_part_count": 0,
  "total_annual_spend_eur": 0
}