ARCNM

API reference

Remnants

The Remnants API keeps the remnants your shop holds in stock, per costing environment: list them, state the ones in your racks, and scrap one when it leaves.

The Remnants API keeps the remnants your shop holds in stock, per costing environment: list them, state the ones in your racks, and scrap one when it leaves.

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 Remnants

GET /api/v1/remnants

Your organization's remnants, newest first.

A plain array: the page position travels in the Link, X-Next-Cursor and X-Has-More response headers.

Paginated. Pass cursor (from the previous response) to fetch the next page; limit caps the page size.

Parameters

Name In Type Required Description
env_id query string no Only this environment's remnants. A filter narrows the list: an id that matches no environment of your organization lists nothing.
status query available | reserved | consumed | scrapped no Only remnants in this state; every state when omitted.
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.

Request

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

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

POST /api/v1/remnants

State a remnant your shop holds.

A job nest in that environment cuts parts of its material and thickness from it before it buys a sheet.

Request body (application/json)

Field Type Required Description
env_id string yes
gauge_mm number yes
length_mm number yes
material_category carbon_steel | alloy_steel | stainless_steel | tool_steel | cast_iron | aluminium | copper_alloy | nickel_alloy | titanium_alloy | magnesium_alloy | zinc_alloy | thermoplastic | thermoset | elastomer | composite | other no
material_grade_id string no
quantity integer no
width_mm number yes

Request

curl -X POST https://api.arcnm.io/api/v1/remnants \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "env_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "length_mm": 0,
    "width_mm": 0,
    "gauge_mm": 0
  }'
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/remnants",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "env_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "length_mm": 0,
        "width_mm": 0,
        "gauge_mm": 0
    },
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/remnants", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "env_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "length_mm": 0,
    "width_mm": 0,
    "gauge_mm": 0
  }),
})
const data = await resp.json()

Responses

Status Description
201 Successful Response
422 The environment or the material grade is not one of your organization's (remnant_unresolved).

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
consumed_at string When it left stock — consumed or scrapped.
created_at string
env_id string The costing environment that holds it.
gauge_mm number Thickness, in millimetres.
id string
length_mm number Longer edge, in millimetres.
material_category string The material category.
material_grade_id string The material grade; null when the remnant is stated for a whole material category.
origin_group_id string The job nest group whose sheet left it; null for a remnant you stated.
quantity integer Pieces of this size.
reserved_by_run_id string The job nest that holds or consumed it.
status available | reserved | consumed | scrapped available: in stock. reserved: held by a job nest while it runs. consumed: cut into parts by a job nest. scrapped: taken out of stock.
width_mm number Shorter edge, in millimetres.

Example response

{
  "consumed_at": "2026-06-01T12:00:00Z",
  "created_at": "2026-06-01T12:00:00Z",
  "env_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "gauge_mm": 0,
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "length_mm": 0,
  "material_category": "string",
  "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "origin_group_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "quantity": 0,
  "reserved_by_run_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "available",
  "width_mm": 0
}

Remnant Label

GET /api/v1/remnants/{remnant_id}/label

The remnant's rack label: size, thickness, material, pieces, origin and date, with a Code 128 barcode of its code.

Print it at 100 %: the SVG is sized in millimetres. The barcode reads back through GET /remnants/by-code/{code}.

Parameters

Name In Type Required Description
remnant_id path string yes Identifier of the remnant.
lang query de | en no The label's language.

Request

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

resp = requests.get(
    "https://api.arcnm.io/api/v1/remnants/{remnant_id}/label",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/remnants/{remnant_id}/label", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()

Responses

Status Description
200 The rack label, an SVG at true size (100 × 50 mm).
404 No remnant with this id in your organization (remnant_not_found).
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.

Scrap Remnant

POST /api/v1/remnants/{remnant_id}/scrap

Take a remnant out of stock — sold, thrown away, or cut by hand.

It stays on record, so a job nest that used or left it still names it. Scrapping part of a stack of one size takes out that many pieces.

Parameters

Name In Type Required Description
remnant_id path string yes Identifier of the remnant.

Request

curl -X POST https://api.arcnm.io/api/v1/remnants/{remnant_id}/scrap \
  -H "X-API-Key: $ARCNM_API_KEY"
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/remnants/{remnant_id}/scrap",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/remnants/{remnant_id}/scrap", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()

Responses

Status Description
200 Successful Response
404 No remnant with this id in your organization (remnant_not_found).
409 The remnant is not in stock: a job nest holds it while it runs, or it was consumed or scrapped already, or fewer pieces are in stock than you named (remnant_not_in_stock).
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
consumed_at string When it left stock — consumed or scrapped.
created_at string
env_id string The costing environment that holds it.
gauge_mm number Thickness, in millimetres.
id string
length_mm number Longer edge, in millimetres.
material_category string The material category.
material_grade_id string The material grade; null when the remnant is stated for a whole material category.
origin_group_id string The job nest group whose sheet left it; null for a remnant you stated.
quantity integer Pieces of this size.
reserved_by_run_id string The job nest that holds or consumed it.
status available | reserved | consumed | scrapped available: in stock. reserved: held by a job nest while it runs. consumed: cut into parts by a job nest. scrapped: taken out of stock.
width_mm number Shorter edge, in millimetres.

Example response

{
  "consumed_at": "2026-06-01T12:00:00Z",
  "created_at": "2026-06-01T12:00:00Z",
  "env_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "gauge_mm": 0,
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "length_mm": 0,
  "material_category": "string",
  "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "origin_group_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "quantity": 0,
  "reserved_by_run_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "available",
  "width_mm": 0
}

Find Remnant By Code

GET /api/v1/remnants/by-code/{code}

The remnant a scanned or typed label code names.

Any state: a scanned piece that was consumed or scrapped is still found, and its status says so.

Parameters

Name In Type Required Description
code path string yes The code a label carries — the first 12 hexadecimal digits of the remnant's id — or the whole id. Case does not matter.

Request

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

resp = requests.get(
    "https://api.arcnm.io/api/v1/remnants/by-code/{code}",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/remnants/by-code/{code}", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()

Responses

Status Description
200 Successful Response
404 No remnant with this id in your organization (remnant_not_found).
409 More than one remnant of your organization begins with this code — scan or type more of the id (remnant_code_ambiguous).
422 The code is not a remnant code: hexadecimal digits of the id, at least 8 of them, or the whole id (remnant_code_invalid).

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
consumed_at string When it left stock — consumed or scrapped.
created_at string
env_id string The costing environment that holds it.
gauge_mm number Thickness, in millimetres.
id string
length_mm number Longer edge, in millimetres.
material_category string The material category.
material_grade_id string The material grade; null when the remnant is stated for a whole material category.
origin_group_id string The job nest group whose sheet left it; null for a remnant you stated.
quantity integer Pieces of this size.
reserved_by_run_id string The job nest that holds or consumed it.
status available | reserved | consumed | scrapped available: in stock. reserved: held by a job nest while it runs. consumed: cut into parts by a job nest. scrapped: taken out of stock.
width_mm number Shorter edge, in millimetres.

Example response

{
  "consumed_at": "2026-06-01T12:00:00Z",
  "created_at": "2026-06-01T12:00:00Z",
  "env_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "gauge_mm": 0,
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "length_mm": 0,
  "material_category": "string",
  "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "origin_group_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "quantity": 0,
  "reserved_by_run_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "available",
  "width_mm": 0
}