ARCNM

API reference

Job Nests

The Job Nests API nests a backlog of sheet-metal parts together on shared sheets: preview what a job nest would take, start one, read each order's and each…

The Job Nests API nests a backlog of sheet-metal parts together on shared sheets: preview what a job nest would take, start one, read each order's and each part's share of the sheets, export its sheets as cutting files (DXF, SVG or the JSON nest plan), and cancel it.

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 job nests

GET /api/v1/nest-runs

The job nests your organization started, newest first. The nest an assembly calculation runs for its own sheet components belongs to that calculation and is not listed.

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 job nests. A filter narrows the list: an id that matches no environment of your organization lists nothing.
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/nest-runs \
  -H "X-API-Key: $ARCNM_API_KEY"
import requests

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

Start a job nest

POST /api/v1/nest-runs

Nest a backlog selection together, sheet by sheet.

Every line is read off its calculation: the part's shape as its single-part price nested it, the thickness it is bought in, the margin and spacing, the material and its price. Lines are grouped by material, thickness and allowances — one nest never mixes them — and the job nest is queued: poll GET /nest-runs/{run_id} until it ends. It cuts from the environment's remnants of each material and thickness before it buys a sheet — a remnant it cuts from leaves stock, and the reusable rests its sheets leave go in. Nothing here changes a calculation's price.

One job nest at a time: while one of your organization's is queued or running, a second is refused — wait until it ends, or cancel it.

When the month's runs are already used, the job nest is kept as a draft: stored, not queued, spending no run. Start it with POST /nest-runs/{run_id}/start once the allowance has a run for it, or cancel it. Your organization keeps at most 20 drafts.

Request body (application/json)

Field Type Required Description
allocation_rule area_proportional | equal_per_sheet no How a sheet's cost is shared by the parts on it: by their area, or equally.
batch_id string no Nest every calculation of this batch priced in the environment, each at its lot size.
env_id string yes The costing environment the run nests in: its stock and remnants.
folder_id string no Nest the newest calculation priced in the environment of every part filed in this folder or below it, each at its lot size.
group_budget_s number no The longest each material and thickness may be nested for, in seconds of computing time: longer can use less sheet.
items NestRunItemIn[] no

Request

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

resp = requests.post(
    "https://api.arcnm.io/api/v1/nest-runs",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "env_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    },
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/nest-runs", {
  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"
  }),
})
const data = await resp.json()

Responses

Status Description
201 Successful Response
404 The environment, batch or folder is not your organization's (nest_run_selection_not_found).
409 A job nest of your organization is still queued or running (nest_run_in_flight): wait until it ends, or cancel it. Or the month's runs are used and your organization keeps the most drafts it may (nest_run_too_many_drafts): start one or cancel one.
422 An item can't be nested — details.items names each with its reason (nest_run_items_unusable) — or the batch or folder holds nothing that can (nest_run_nothing_to_nest), or more calculations than one run takes (nest_run_selection_too_large), or a line asks for more copies than one line takes (nest_run_line_too_large), or the lines together more than one run takes (nest_run_too_many_copies), or group_budget_s is past what your organization may ask for (nest_run_budget_too_long).

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
allocation_rule area_proportional | equal_per_sheet How each sheet's cost is shared by the parts on it.
as_of string The day its stock and prices are read at.
copies integer Copies it nests, over all its lines.
counted_at string When it was released; null while a simulation.
counts_toward_savings boolean True once the job nest was released: its stock is booked and what it saves adds to the total saved by nesting. False: a simulation, whose saving is potential only.
created_at string
created_by_user_id string
env_id string The costing environment it nests in.
error string Why it stopped, when it did not finish.
finished_at string
group_budget_s number The longest each material and thickness may be nested for, in seconds of computing time.
groups_done integer Of those, the ones finished so far: nested, or not nestable.
groups_total integer Materials and thicknesses it nests — each is nested on its own.
id string
lines integer Lines it nests.
savings NestRunSavings What it saves, once it ends; null before, or where no line compares.
sheets integer Sheets and remnants the nested materials and thicknesses are cut from; set once the job nest ends.
started_at string
status draft | queued | running | solved | failed | cancelled draft: kept, not queued — it was started while the month's runs were used, so it spends no run until POST /nest-runs/{run_id}/start starts it. queued: waiting to start. running: nesting, several materials and thicknesses at a time. solved: every material and thickness is nested. failed: it stopped, error says why; what it nested before stands. cancelled: stopped on request; what it nested before stands.

Example response

{
  "allocation_rule": "area_proportional",
  "as_of": "2026-06-01",
  "copies": 0,
  "counted_at": "2026-06-01T12:00:00Z",
  "counts_toward_savings": false,
  "created_at": "2026-06-01T12:00:00Z",
  "created_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "env_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "error": "string",
  "finished_at": "2026-06-01T12:00:00Z",
  "group_budget_s": 184,
  "groups_done": 0,
  "groups_total": 0,
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "lines": 0,
  "savings": {
    "alone": 0,
    "alone_kg": 0,
    "alone_sheets": 0,
    "by_order": [
      {
        "alone": 0,
        "alone_kg": 0,
        "alone_sheets": 0,
        "copies": 0,
        "currency": "EUR",
        "lines": 0,
        "lines_compared": 0,
        "nested": 0,
        "nested_kg": 0,
        "nested_sheets": 0,
        "order_ref": "string",
        "rectangular": 0,
        "rectangular_kg": 0,
        "rectangular_sheets": 0,
        "saved": 0,
        "saved_combining": 0,
        "saved_combining_kg": 0,
        "saved_kg": 0,
        "saved_true_shape": 0,
        "saved_true_shape_kg": 0,
        "split_lines": 0
      }
    ],
    "copies": 0,
    "currency": "EUR",
    "lines": 0,
    "lines_compared": 0,
    "nested": 0,
    "nested_kg": 0,
    "nested_sheets": 0,
    "rectangular": 0,
    "rectangular_kg": 0,
    "rectangular_sheets": 0,
    "saved": 0,
    "saved_combining": 0,
    "saved_combining_kg": 0,
    "saved_kg": 0,
    "saved_true_shape": 0,
    "saved_true_shape_kg": 0,
    "split_lines": 0
  },
  "sheets": 0,
  "started_at": "2026-06-01T12:00:00Z",
  "status": "draft"
}

Read a job nest

GET /api/v1/nest-runs/{run_id}

One job nest: each material and thickness with its sheets and utilisation, each line's and each order's share of the sheets, and the remnants it used, holds and created.

Parameters

Name In Type Required Description
run_id path string yes Identifier of the run.

Request

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

resp = requests.get(
    "https://api.arcnm.io/api/v1/nest-runs/{run_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/nest-runs/{run_id}", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()

Responses

Status Description
200 Successful Response
402 An assembly calculation ran this job nest for its own sheet components, and your organization has no active Nesting add-on (addon_required).
404 No run with this id in your organization (nest_run_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.

Response body 200

Field Type Description
allocation_rule area_proportional | equal_per_sheet How each sheet's cost is shared by the parts on it.
as_of string The day its stock and prices are read at.
copies integer Copies it nests, over all its lines.
counted_at string When it was released; null while a simulation.
counts_toward_savings boolean True once the job nest was released: its stock is booked and what it saves adds to the total saved by nesting. False: a simulation, whose saving is potential only.
created_at string
created_by_user_id string
env_id string The costing environment it nests in.
error string Why it stopped, when it did not finish.
finished_at string
group_budget_s number The longest each material and thickness may be nested for, in seconds of computing time.
groups NestRunGroup[]
groups_done integer Of those, the ones finished so far: nested, or not nestable.
groups_total integer Materials and thicknesses it nests — each is nested on its own.
id string
items NestRunLine[]
left_out LeftOutLine[] Calculations of the batch or folder it does not take, each with why.
lines integer Lines it nests.
orders OrderTotal[] Each order's lines totalled, once the job nest ends.
remnants_created RemnantPublic[] The reusable rests its sheets left, now in stock.
remnants_held RemnantPublic[] Remnants it holds while it runs, kept from other job nests.
remnants_used RemnantPublic[] Remnants from stock its sheets were cut from.
savings NestRunSavings What it saves, once it ends; null before, or where no line compares.
sheets integer Sheets and remnants the nested materials and thicknesses are cut from; set once the job nest ends.
started_at string
status draft | queued | running | solved | failed | cancelled draft: kept, not queued — it was started while the month's runs were used, so it spends no run until POST /nest-runs/{run_id}/start starts it. queued: waiting to start. running: nesting, several materials and thicknesses at a time. solved: every material and thickness is nested. failed: it stopped, error says why; what it nested before stands. cancelled: stopped on request; what it nested before stands.

Example response

{
  "allocation_rule": "area_proportional",
  "as_of": "2026-06-01",
  "copies": 0,
  "counted_at": "2026-06-01T12:00:00Z",
  "counts_toward_savings": false,
  "created_at": "2026-06-01T12:00:00Z",
  "created_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "env_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "error": "string",
  "finished_at": "2026-06-01T12:00:00Z",
  "group_budget_s": 184,
  "groups": [
    {
      "active_revision": 0,
      "error": "string",
      "finished_at": "2026-06-01T12:00:00Z",
      "gauge_mm": 0,
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "material_category": "string",
      "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "position": 0,
      "revisions": 0,
      "sheets": 0,
      "started_at": "2026-06-01T12:00:00Z",
      "status": "pending",
      "utilisation_net": 0
    }
  ],
  "groups_done": 0,
  "groups_total": 0,
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "items": [
    {
      "allocation": {
        "copies": 0,
        "currency": "EUR",
        "net": 0,
        "net_per_copy": 0,
        "purchased": 0,
        "remnant_credit": 0,
        "scrap_credit": 0
      },
      "calculation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "due": "2026-06-01",
      "group_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "order_ref": "string",
      "position": 0,
      "priority": 0,
      "quantity": 0
    }
  ],
  "left_out": [
    {
      "calculation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "reason": "string"
    }
  ],
  "lines": 0,
  "orders": [
    {
      "copies": 0,
      "currency": "EUR",
      "net": 0,
      "net_per_copy": 0,
      "order_ref": "string",
      "purchased": 0,
      "remnant_credit": 0,
      "scrap_credit": 0
    }
  ],
  "remnants_created": [
    {
      "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
    }
  ],
  "remnants_held": [
    {
      "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
    }
  ],
  "remnants_used": [
    {
      "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
    }
  ],
  "savings": {
    "alone": 0,
    "alone_kg": 0,
    "alone_sheets": 0,
    "by_order": [
      {
        "alone": 0,
        "alone_kg": 0,
        "alone_sheets": 0,
        "copies": 0,
        "currency": "EUR",
        "lines": 0,
        "lines_compared": 0,
        "nested": 0,
        "nested_kg": 0,
        "nested_sheets": 0,
        "order_ref": "string",
        "rectangular": 0,
        "rectangular_kg": 0,
        "rectangular_sheets": 0,
        "saved": 0,
        "saved_combining": 0,
        "saved_combining_kg": 0,
        "saved_kg": 0,
        "saved_true_shape": 0,
        "saved_true_shape_kg": 0,
        "split_lines": 0
      }
    ],
    "copies": 0,
    "currency": "EUR",
    "lines": 0,
    "lines_compared": 0,
    "nested": 0,
    "nested_kg": 0,
    "nested_sheets": 0,
    "rectangular": 0,
    "rectangular_kg": 0,
    "rectangular_sheets": 0,
    "saved": 0,
    "saved_combining": 0,
    "saved_combining_kg": 0,
    "saved_kg": 0,
    "saved_true_shape": 0,
    "saved_true_shape_kg": 0,
    "split_lines": 0
  },
  "sheets": 0,
  "started_at": "2026-06-01T12:00:00Z",
  "status": "draft"
}

Cancel a job nest

POST /api/v1/nest-runs/{run_id}/cancel

Stop a job nest that has not ended.

The materials and thicknesses already nested keep their result; the others are cancelled, and every remnant the job nest holds goes back to stock. A job nest cancelled before any material and thickness was nested gives its run back to the month's allowance; once one is nested, it counts as a run, as a job nest that stops on an error does. A draft is discarded the same way.

Parameters

Name In Type Required Description
run_id path string yes Identifier of the run.

Request

curl -X POST https://api.arcnm.io/api/v1/nest-runs/{run_id}/cancel \
  -H "X-API-Key: $ARCNM_API_KEY"
import requests

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

Responses

Status Description
200 Successful Response
402 An assembly calculation ran this job nest for its own sheet components, and your organization has no active Nesting add-on (addon_required).
404 No run with this id in your organization (nest_run_not_found).
409 The run has already ended (nest_run_not_cancellable), or it is an assembly calculation's own nest, which only that assembly changes (nest_run_internal).
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
allocation_rule area_proportional | equal_per_sheet How each sheet's cost is shared by the parts on it.
as_of string The day its stock and prices are read at.
copies integer Copies it nests, over all its lines.
counted_at string When it was released; null while a simulation.
counts_toward_savings boolean True once the job nest was released: its stock is booked and what it saves adds to the total saved by nesting. False: a simulation, whose saving is potential only.
created_at string
created_by_user_id string
env_id string The costing environment it nests in.
error string Why it stopped, when it did not finish.
finished_at string
group_budget_s number The longest each material and thickness may be nested for, in seconds of computing time.
groups_done integer Of those, the ones finished so far: nested, or not nestable.
groups_total integer Materials and thicknesses it nests — each is nested on its own.
id string
lines integer Lines it nests.
savings NestRunSavings What it saves, once it ends; null before, or where no line compares.
sheets integer Sheets and remnants the nested materials and thicknesses are cut from; set once the job nest ends.
started_at string
status draft | queued | running | solved | failed | cancelled draft: kept, not queued — it was started while the month's runs were used, so it spends no run until POST /nest-runs/{run_id}/start starts it. queued: waiting to start. running: nesting, several materials and thicknesses at a time. solved: every material and thickness is nested. failed: it stopped, error says why; what it nested before stands. cancelled: stopped on request; what it nested before stands.

Example response

{
  "allocation_rule": "area_proportional",
  "as_of": "2026-06-01",
  "copies": 0,
  "counted_at": "2026-06-01T12:00:00Z",
  "counts_toward_savings": false,
  "created_at": "2026-06-01T12:00:00Z",
  "created_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "env_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "error": "string",
  "finished_at": "2026-06-01T12:00:00Z",
  "group_budget_s": 184,
  "groups_done": 0,
  "groups_total": 0,
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "lines": 0,
  "savings": {
    "alone": 0,
    "alone_kg": 0,
    "alone_sheets": 0,
    "by_order": [
      {
        "alone": 0,
        "alone_kg": 0,
        "alone_sheets": 0,
        "copies": 0,
        "currency": "EUR",
        "lines": 0,
        "lines_compared": 0,
        "nested": 0,
        "nested_kg": 0,
        "nested_sheets": 0,
        "order_ref": "string",
        "rectangular": 0,
        "rectangular_kg": 0,
        "rectangular_sheets": 0,
        "saved": 0,
        "saved_combining": 0,
        "saved_combining_kg": 0,
        "saved_kg": 0,
        "saved_true_shape": 0,
        "saved_true_shape_kg": 0,
        "split_lines": 0
      }
    ],
    "copies": 0,
    "currency": "EUR",
    "lines": 0,
    "lines_compared": 0,
    "nested": 0,
    "nested_kg": 0,
    "nested_sheets": 0,
    "rectangular": 0,
    "rectangular_kg": 0,
    "rectangular_sheets": 0,
    "saved": 0,
    "saved_combining": 0,
    "saved_combining_kg": 0,
    "saved_kg": 0,
    "saved_true_shape": 0,
    "saved_true_shape_kg": 0,
    "split_lines": 0
  },
  "sheets": 0,
  "started_at": "2026-06-01T12:00:00Z",
  "status": "draft"
}

Export a job nest's sheets for cutting

GET /api/v1/nest-runs/{run_id}/export

The sheets of a job nest as cutting files.

Every solved material and thickness contributes its sheets: each distinct layout once, with how many identical sheets it stands for. A sheet's DXF holds the sheet's rectangle, the usable area, the reusable rest it leaves, every copy's outer contour and holes, and a label per copy with its part reference and order; the header and a title state the job nest, the sheet, the material and thickness, the format or remnant, the count and the utilisation. Contours are within 0.2 mm of the unfolded flat pattern; arcs are polylines. The JSON nest plan carries the same geometry as data. A job nest that is still running exports what is solved so far. The sheets are each material and thickness's ACTIVE revision — the layout the job nest reads — unless revision names another; then every exported material and thickness must have that revision. A file still being built after a minute is answered 503 with Retry-After; /export-url never waits.

Parameters

Name In Type Required Description
run_id path string yes Identifier of the run.
format query dxf | svg | json no dxf (R2010, millimetres: one block per part and one insert per copy, on the layers SHEET, MARGIN, REMNANT, CUT_OUTER, CUT_INNER and LABEL), svg (the same geometry, the view box in millimetres) or json (the nest plan: every part's contour and every sheet's placements).
sheet query string no all: every sheet — a zip of one DXF or SVG per sheet with plan.json and manifest.csv, or the whole nest plan as JSON. Or one sheet's key, <group>:<index> as the plan names it, for that sheet's file.
exploded query boolean no DXF only: write each copy's contours as plain closed polylines in place, no blocks — for a cutting system that does not read block references.
revision query integer no Export this revision of every material and thickness's sheets instead of the active one; 1 is the job nest's own layout.

Request

curl -X GET https://api.arcnm.io/api/v1/nest-runs/{run_id}/export \
  -H "X-API-Key: $ARCNM_API_KEY"
import requests

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

Responses

Status Description
200 The file — Content-Disposition names it — or, for format=json, the nest plan.
402 An assembly calculation ran this job nest for its own sheet components, and your organization has no active Nesting add-on (addon_required).
404 No job nest with this id in your organization (nest_run_not_found), or sheet names no sheet of it (nest_run_sheet_not_found).
409 No material and thickness of the job nest is solved yet (nest_run_nothing_to_export).
422 Validation Error
503 The file is still being built (nest_export_timeout): ask again after Retry-After seconds.

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
parts NestPlanPart[]
sheets NestPlanSheet[]
source NestPlanSource
tolerance NestPlanTolerance
units string
v integer The schema version.

Example response

{
  "parts": [
    {
      "calculation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "holes": [
        []
      ],
      "line_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name": "string",
      "net_area_mm2": 0,
      "order_ref": "string",
      "outline": [
        []
      ],
      "placed": 0,
      "quantity": 0,
      "ref": "string"
    }
  ],
  "sheets": [
    {
      "container": {
        "key": "string",
        "kind": "format",
        "length_mm": 0,
        "width_mm": 0
      },
      "count": 0,
      "gauge_mm": 0,
      "group": 0,
      "index": 0,
      "key": "string",
      "margin_mm": 0,
      "material": "string",
      "placements": [
        {}
      ],
      "remnant": {
        "length_mm": 0,
        "width_mm": 0,
        "x_mm": 0,
        "y_mm": 0
      },
      "repeat": 0,
      "spacing_mm": 0,
      "utilisation": 0
    }
  ],
  "source": {
    "calculation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "created_at": "2026-06-01T12:00:00Z",
    "environment_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "finished_at": "2026-06-01T12:00:00Z",
    "kind": "run",
    "run_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  },
  "tolerance": {
    "arcs": "string",
    "contour_mm": 0,
    "note": "string"
  },
  "units": "string",
  "v": 0
}

GET /api/v1/nest-runs/{run_id}/export-url

The file GET /nest-runs/{run_id}/export answers, as a short-lived download link — without waiting for it to be built.

200: the file is ready; url downloads it (no credentials, until expires_in_s runs out) under file_name. 202: it is being built; ask again after Retry-After seconds. A build that was refused is answered with its own code and status; fresh=true builds it again. Same parameters, scope and refusals as the export.

Parameters

Name In Type Required Description
run_id path string yes Identifier of the run.
format query dxf | svg | json no dxf (R2010, millimetres: one block per part and one insert per copy, on the layers SHEET, MARGIN, REMNANT, CUT_OUTER, CUT_INNER and LABEL), svg (the same geometry, the view box in millimetres) or json (the nest plan: every part's contour and every sheet's placements).
sheet query string no all: every sheet — a zip of one DXF or SVG per sheet with plan.json and manifest.csv, or the whole nest plan as JSON. Or one sheet's key, <group>:<index> as the plan names it, for that sheet's file.
exploded query boolean no DXF only: write each copy's contours as plain closed polylines in place, no blocks — for a cutting system that does not read block references.
revision query integer no Export this revision of every material and thickness's sheets instead of the active one; 1 is the job nest's own layout.
fresh query boolean no Build the file again when its last build was refused and nothing is building it now. Without it, a refusal is answered again for a few minutes.

Request

curl -X GET https://api.arcnm.io/api/v1/nest-runs/{run_id}/export-url \
  -H "X-API-Key: $ARCNM_API_KEY"
import requests

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

Responses

Status Description
200 Successful Response
202 The file is being built: ask again after Retry-After seconds.
402 An assembly calculation ran this job nest for its own sheet components, and your organization has no active Nesting add-on (addon_required).
404 No job nest with this id in your organization (nest_run_not_found), or sheet names no sheet of it (nest_run_sheet_not_found).
409 No material and thickness of the job nest is solved yet (nest_run_nothing_to_export).
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
content_type string
expires_in_s integer Seconds until the link expires.
file_name string
size_bytes integer The file's size in bytes.
status string
url string GET it, without credentials, before it expires; the response names the file.

Example response

{
  "content_type": "string",
  "expires_in_s": 0,
  "file_name": "string",
  "size_bytes": 204800,
  "status": "string",
  "url": "string"
}

Check a layout of a job nest's sheets

POST /api/v1/nest-runs/{run_id}/groups/{group_id}/layout-check

What the cutter would find in this layout, before anything is stored.

Send the whole layout of one material and thickness: every sheet with the stock format or remnant it is cut from and its placements. The answer names every pair of parts closer than the spacing with the gap between them, every part in the margin or off the sheet, every line short or over its quantity, every container the job nest cannot cut from, every copy turned against the environment's grain direction or mirrored where it allows no mirroring (as the job nest read its shop practice), and each sheet's utilisation and rest. ok is what POST …/revisions accepts; complete says every line is placed exactly as often as ordered. Nothing is stored.

Parameters

Name In Type Required Description
run_id path string yes The job nest.
group_id path string yes The material and thickness.

Request body (application/json)

Field Type Required Description
note string no Why this layout (kept with the revision; ignored by the check).
sheets NestSheetIn[] yes

Request

curl -X POST https://api.arcnm.io/api/v1/nest-runs/{run_id}/groups/{group_id}/layout-check \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sheets": [
      {
        "container_id": "string",
        "placements": [
          {
            "line_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "mirrored": false,
            "rot_deg": 0,
            "x": 0,
            "y": 0
          }
        ],
        "repeat": 1
      }
    ]
  }'
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/nest-runs/{run_id}/groups/{group_id}/layout-check",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "sheets": [
            {
                "container_id": "string",
                "placements": [
                    {
                        "line_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                        "mirrored": False,
                        "rot_deg": 0,
                        "x": 0,
                        "y": 0
                    }
                ],
                "repeat": 1
            }
        ]
    },
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/nest-runs/{run_id}/groups/{group_id}/layout-check", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "sheets": [
      {
        "container_id": "string",
        "placements": [
          {
            "line_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "mirrored": false,
            "rot_deg": 0,
            "x": 0,
            "y": 0
          }
        ],
        "repeat": 1
      }
    ]
  }),
})
const data = await resp.json()

Responses

Status Description
200 Successful Response
404 No job nest with this id in your organization (nest_run_not_found), or no material and thickness with this id in it (nest_run_group_not_found).
409 This material and thickness is not nested yet (nest_run_not_editable).
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
complete boolean Every line is placed exactly as often as its quantity: missing and extra are empty.
containers_unknown string[]
extra NestLineCount[] Lines with more copies placed than demanded (placed = the surplus).
lines NestLineCount[]
missing NestLineCount[] Lines with fewer copies placed than demanded (placed = the shortfall).
ok boolean Every sheet can be cut, every copy keeps the environment's shop practice, and no remnant is over-used: what POST …/revisions accepts. A line short of its quantity or over it does not make a layout unacceptable — missing and extra state it, and a revision is priced on the copies it cuts.
remnants_over NestRemnantOver[]
sheets NestSheetCheck[]
sheets_total integer Sheets, every one as often as it repeats.
utilisation_net number The parts' area over the sheet area used, reusable rests not counted.

Example response

{
  "complete": true,
  "containers_unknown": [
    "string"
  ],
  "extra": [
    {
      "line_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "placed": 0,
      "quantity": 0
    }
  ],
  "lines": [
    {
      "line_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "placed": 0,
      "quantity": 0
    }
  ],
  "missing": [
    {
      "line_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "placed": 0,
      "quantity": 0
    }
  ],
  "ok": true,
  "remnants_over": [
    {
      "available": 0,
      "container_id": "string",
      "pieces": 0
    }
  ],
  "sheets": [
    {
      "against_shop_practice": [
        {}
      ],
      "clashes": [
        {}
      ],
      "clashes_total": 0,
      "container_id": "string",
      "container_kind": "string",
      "container_unknown": true,
      "count": 0,
      "index": 0,
      "length_mm": 0,
      "net_area_mm2": 0,
      "ok": true,
      "outside": [
        0
      ],
      "repeat": 0,
      "rest": {
        "length_mm": 0,
        "reusable": true,
        "width_mm": 0,
        "x_mm": 0,
        "y_mm": 0
      },
      "unknown_lines": [
        "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      ],
      "utilisation": 0,
      "width_mm": 0
    }
  ],
  "sheets_total": 0,
  "utilisation_net": 0
}

List a material and thickness's revisions

GET /api/v1/nest-runs/{run_id}/groups/{group_id}/revisions

Every revision of this material and thickness's sheets, oldest first — the job nest's own result is revision 1 — with what each saves; the active one is marked. Layouts are read per revision.

Parameters

Name In Type Required Description
run_id path string yes The job nest.
group_id path string yes The material and thickness.

Request

curl -X GET https://api.arcnm.io/api/v1/nest-runs/{run_id}/groups/{group_id}/revisions \
  -H "X-API-Key: $ARCNM_API_KEY"
import requests

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

Responses

Status Description
200 Successful Response
402 An assembly calculation ran this job nest for its own sheet components, and your organization has no active Nesting add-on (addon_required).
404 No job nest with this id in your organization (nest_run_not_found), or no material and thickness with this id in it (nest_run_group_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.

Post a layout as the next revision

POST /api/v1/nest-runs/{run_id}/groups/{group_id}/revisions

Store this layout as the material and thickness's next revision and make it the active one.

The body is the one POST …/layout-check takes; a layout the check finds ok — every sheet cuttable, no remnant over-used — is accepted. A line short of its quantity or over it is accepted as posted and priced on the copies the layout cuts. It is priced as the job nest's own result is (the run's allocation rule, the material's price and credits), and the group's sheets, every line's share, the run's order totals and what it saves follow the new revision. Earlier revisions stay as they are: a calculation priced on a line keeps the revision it read. To go back to an earlier layout, post it again. A released job nest is frozen.

Parameters

Name In Type Required Description
run_id path string yes The job nest.
group_id path string yes The material and thickness.

Request body (application/json)

Field Type Required Description
note string no Why this layout (kept with the revision; ignored by the check).
sheets NestSheetIn[] yes

Request

curl -X POST https://api.arcnm.io/api/v1/nest-runs/{run_id}/groups/{group_id}/revisions \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sheets": [
      {
        "container_id": "string",
        "placements": [
          {
            "line_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "mirrored": false,
            "rot_deg": 0,
            "x": 0,
            "y": 0
          }
        ],
        "repeat": 1
      }
    ]
  }'
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/nest-runs/{run_id}/groups/{group_id}/revisions",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "sheets": [
            {
                "container_id": "string",
                "placements": [
                    {
                        "line_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                        "mirrored": False,
                        "rot_deg": 0,
                        "x": 0,
                        "y": 0
                    }
                ],
                "repeat": 1
            }
        ]
    },
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/nest-runs/{run_id}/groups/{group_id}/revisions", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "sheets": [
      {
        "container_id": "string",
        "placements": [
          {
            "line_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "mirrored": false,
            "rot_deg": 0,
            "x": 0,
            "y": 0
          }
        ],
        "repeat": 1
      }
    ]
  }),
})
const data = await resp.json()

Responses

Status Description
201 Successful Response
404 No job nest with this id in your organization (nest_run_not_found), or no material and thickness with this id in it (nest_run_group_not_found).
409 The job nest has not ended yet, or this material and thickness is not nested (nest_run_not_editable, details.reason); the job nest was released and its stock booked, so its sheets are frozen (nest_run_released); or it is an assembly calculation's own nest, whose layout prices that assembly's components and only that assembly changes (nest_run_internal).
422 The layout cannot be cut as posted, or breaks the environment's shop practice (nest_layout_invalid): details is the check POST …/layout-check answers. A line short of its quantity or over it is no refusal.

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 201

Field Type Description
active boolean The one the job nest reads its sheets from.
created_at string
created_by_user_id string
note string
revision integer
savings object What the lines save under this revision: rectangular blanks, each part nested alone, the parts nested together, what nesting saved and its split, summed and per order (by_order), and per line (by_line) — see the job nest's savings.
sheets integer Sheets and remnants it cuts.
source string nest — the job nest's own layout; edit — one posted here.
utilisation_net number

Example response

{
  "active": true,
  "created_at": "2026-06-01T12:00:00Z",
  "created_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "note": "string",
  "revision": 0,
  "savings": {},
  "sheets": 0,
  "source": "string",
  "utilisation_net": 0
}

Read a revision with its sheets

GET /api/v1/nest-runs/{run_id}/groups/{group_id}/revisions/{revision}

One revision with every sheet's placements — the body POST …/revisions takes, as stored, to adjust and post again.

Parameters

Name In Type Required Description
run_id path string yes The job nest.
group_id path string yes The material and thickness.
revision path integer yes The revision number.

Request

curl -X GET https://api.arcnm.io/api/v1/nest-runs/{run_id}/groups/{group_id}/revisions/{revision} \
  -H "X-API-Key: $ARCNM_API_KEY"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/nest-runs/{run_id}/groups/{group_id}/revisions/{revision}",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/nest-runs/{run_id}/groups/{group_id}/revisions/{revision}", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()

Responses

Status Description
200 Successful Response
402 An assembly calculation ran this job nest for its own sheet components, and your organization has no active Nesting add-on (addon_required).
404 No job nest, material and thickness, or revision with this id (nest_run_not_found, nest_run_group_not_found, nest_run_revision_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.

Response body 200

Field Type Description
active boolean The one the job nest reads its sheets from.
created_at string
created_by_user_id string
group_id string
length_width_mm object Each container's length and width, by container id.
note string
revision integer
savings object What the lines save under this revision: rectangular blanks, each part nested alone, the parts nested together, what nesting saved and its split, summed and per order (by_order), and per line (by_line) — see the job nest's savings.
sheets integer Sheets and remnants it cuts.
sheets_laid NestRevisionSheet[]
source string nest — the job nest's own layout; edit — one posted here.
utilisation_net number

Example response

{
  "active": true,
  "created_at": "2026-06-01T12:00:00Z",
  "created_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "group_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "length_width_mm": {},
  "note": "string",
  "revision": 0,
  "savings": {},
  "sheets": 0,
  "sheets_laid": [
    {
      "container_id": "string",
      "container_kind": "string",
      "count": 0,
      "index": 0,
      "net_area_mm2": 0,
      "placements": [
        {}
      ],
      "repeat": 0,
      "rest": {
        "length_mm": 0,
        "reusable": true,
        "width_mm": 0,
        "x_mm": 0,
        "y_mm": 0
      },
      "utilisation": 0
    }
  ],
  "source": "string",
  "utilisation_net": 0
}

Nest Run Remnant Labels

GET /api/v1/nest-runs/{run_id}/remnant-labels

Rack labels for the rests a released job nest put into stock, one per row in one SVG sized in millimetres — print it when the sheets come off the cutter.

Parameters

Name In Type Required Description
run_id path string yes Identifier of the run.
lang query de | en no The labels' language.

Request

curl -X GET https://api.arcnm.io/api/v1/nest-runs/{run_id}/remnant-labels \
  -H "X-API-Key: $ARCNM_API_KEY"
import requests

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

Responses

Status Description
200 One label per rest the released job nest put into stock.
402 An assembly calculation ran this job nest for its own sheet components, and your organization has no active Nesting add-on (addon_required).
404 No job nest with this id in your organization (nest_run_not_found), or it put no rest into stock — not released, or its sheets leave no reusable rest (nest_run_no_rests).
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.

Start a job nest kept as a draft

POST /api/v1/nest-runs/{run_id}/start

Queue a job nest that was kept as a draft.

A start made while the month's runs were used keeps the job nest as a draft. Once the allowance has a run for it, this queues it: it spends one run, is nested at today's stock and prices, and runs in the background — poll GET /nest-runs/{run_id} until it ends. While the month's runs are still used it is refused (402) and stays a draft. Only a draft starts, and only once; one job nest of your organization runs at a time, as for a start.

Parameters

Name In Type Required Description
run_id path string yes Identifier of the run.

Request

curl -X POST https://api.arcnm.io/api/v1/nest-runs/{run_id}/start \
  -H "X-API-Key: $ARCNM_API_KEY"
import requests

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

Responses

Status Description
200 Successful Response
402 The Nesting add-on is not active, or the month's runs are still used (details.feature nesting_runs, with used and limit): the draft stays a draft.
404 No run with this id in your organization (nest_run_not_found).
409 The job nest is not a draft (nest_run_not_draft: it was started already, or cancelled), another job nest of your organization is still queued or running (nest_run_in_flight), or it is an assembly calculation's own nest, which only that assembly changes (nest_run_internal).
422 It has more materials and thicknesses than a run takes (nest_run_too_many_nests).

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
allocation_rule area_proportional | equal_per_sheet How each sheet's cost is shared by the parts on it.
as_of string The day its stock and prices are read at.
copies integer Copies it nests, over all its lines.
counted_at string When it was released; null while a simulation.
counts_toward_savings boolean True once the job nest was released: its stock is booked and what it saves adds to the total saved by nesting. False: a simulation, whose saving is potential only.
created_at string
created_by_user_id string
env_id string The costing environment it nests in.
error string Why it stopped, when it did not finish.
finished_at string
group_budget_s number The longest each material and thickness may be nested for, in seconds of computing time.
groups_done integer Of those, the ones finished so far: nested, or not nestable.
groups_total integer Materials and thicknesses it nests — each is nested on its own.
id string
lines integer Lines it nests.
savings NestRunSavings What it saves, once it ends; null before, or where no line compares.
sheets integer Sheets and remnants the nested materials and thicknesses are cut from; set once the job nest ends.
started_at string
status draft | queued | running | solved | failed | cancelled draft: kept, not queued — it was started while the month's runs were used, so it spends no run until POST /nest-runs/{run_id}/start starts it. queued: waiting to start. running: nesting, several materials and thicknesses at a time. solved: every material and thickness is nested. failed: it stopped, error says why; what it nested before stands. cancelled: stopped on request; what it nested before stands.

Example response

{
  "allocation_rule": "area_proportional",
  "as_of": "2026-06-01",
  "copies": 0,
  "counted_at": "2026-06-01T12:00:00Z",
  "counts_toward_savings": false,
  "created_at": "2026-06-01T12:00:00Z",
  "created_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "env_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "error": "string",
  "finished_at": "2026-06-01T12:00:00Z",
  "group_budget_s": 184,
  "groups_done": 0,
  "groups_total": 0,
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "lines": 0,
  "savings": {
    "alone": 0,
    "alone_kg": 0,
    "alone_sheets": 0,
    "by_order": [
      {
        "alone": 0,
        "alone_kg": 0,
        "alone_sheets": 0,
        "copies": 0,
        "currency": "EUR",
        "lines": 0,
        "lines_compared": 0,
        "nested": 0,
        "nested_kg": 0,
        "nested_sheets": 0,
        "order_ref": "string",
        "rectangular": 0,
        "rectangular_kg": 0,
        "rectangular_sheets": 0,
        "saved": 0,
        "saved_combining": 0,
        "saved_combining_kg": 0,
        "saved_kg": 0,
        "saved_true_shape": 0,
        "saved_true_shape_kg": 0,
        "split_lines": 0
      }
    ],
    "copies": 0,
    "currency": "EUR",
    "lines": 0,
    "lines_compared": 0,
    "nested": 0,
    "nested_kg": 0,
    "nested_sheets": 0,
    "rectangular": 0,
    "rectangular_kg": 0,
    "rectangular_sheets": 0,
    "saved": 0,
    "saved_combining": 0,
    "saved_combining_kg": 0,
    "saved_kg": 0,
    "saved_true_shape": 0,
    "saved_true_shape_kg": 0,
    "split_lines": 0
  },
  "sheets": 0,
  "started_at": "2026-06-01T12:00:00Z",
  "status": "draft"
}

Preview a job nest

POST /api/v1/nest-runs/preview

What a job nest of this selection would take, without starting it.

Takes the body POST /nest-runs takes and reads it the same way: the lines it would nest, each material and thickness they fall into with the remnant pieces of it in stock now, and what a batch or folder leaves out and why. It refuses a missing add-on and a run with too many nests. When the month's runs are already used it still returns the plan, with kept_as_draft set, and nothing is stored.

Request body (application/json)

Field Type Required Description
allocation_rule area_proportional | equal_per_sheet no How a sheet's cost is shared by the parts on it: by their area, or equally.
batch_id string no Nest every calculation of this batch priced in the environment, each at its lot size.
env_id string yes The costing environment the run nests in: its stock and remnants.
folder_id string no Nest the newest calculation priced in the environment of every part filed in this folder or below it, each at its lot size.
group_budget_s number no The longest each material and thickness may be nested for, in seconds of computing time: longer can use less sheet.
items NestRunItemIn[] no

Request

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

resp = requests.post(
    "https://api.arcnm.io/api/v1/nest-runs/preview",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "env_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    },
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/nest-runs/preview", {
  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"
  }),
})
const data = await resp.json()

Responses

Status Description
200 Successful Response
404 The environment, batch or folder is not your organization's (nest_run_selection_not_found).
422 An item can't be nested — details.items names each with its reason (nest_run_items_unusable) — or the batch or folder holds nothing that can (nest_run_nothing_to_nest), or more calculations than one run takes (nest_run_selection_too_large), or a line asks for more copies than one line takes (nest_run_line_too_large), or the lines together more than one run takes (nest_run_too_many_copies), or group_budget_s is past what your organization may ask for (nest_run_budget_too_long).

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
copies integer Copies it would nest, over all its lines.
env_id string
groups NestPlanGroup[]
items NestPlanLine[]
kept_as_draft boolean The month's runs are already used. Starting stores this selection as a draft and does not queue it or spend a run.
left_out LeftOutLine[] Calculations of the batch or folder it would not take, each with why.
lines integer Lines it would nest.

Example response

{
  "copies": 0,
  "env_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "groups": [
    {
      "copies": 0,
      "gauge_mm": 0,
      "lines": 0,
      "material_category": "string",
      "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "remnants_in_stock": 0
    }
  ],
  "items": [
    {
      "calculation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "group": 0,
      "order_ref": "string",
      "position": 0,
      "quantity": 0
    }
  ],
  "kept_as_draft": false,
  "left_out": [
    {
      "calculation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "reason": "string"
    }
  ],
  "lines": 0
}

Read the total saved by nesting

GET /api/v1/nest-runs/savings

What the job nests your organization released have saved together — rectangular blanks cut part by part against the parts nested together, split into each part's true shape and the orders nested together, the money per currency and the sheet metal over all — and, apart from it, the potential of the job nests that are still simulations. A job nest is a simulation, and stays out of the total, until it is released.

Request

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

resp = requests.get(
    "https://api.arcnm.io/api/v1/nest-runs/savings",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://api.arcnm.io/api/v1/nest-runs/savings", {
  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
alone_kg number The same with each part nested alone, in kg, over the lines in split_lines.
lines_compared integer Their lines the figures cover.
money NestSavingsMoney[] The released job nests' savings per currency, in currency order.
nested_kg number The same nested together, in kg.
potential NestSavingsSum The simulations' savings, summed the same way: what releasing them would add. Never part of the total.
rectangular_kg number The sheet the released lines take as rectangular blanks, in kg.
runs_counted integer Released job nests, each with a saving.
runs_simulated integer Job nests with a saving that are not released: simulations.
saved_combining_kg number alone_kg less nested_kg, over the lines in split_lines.
saved_kg number rectangular_kg less nested_kg.
saved_true_shape_kg number rectangular_kg less alone_kg, over the lines in split_lines.
split_lines integer Of those, the lines the split of the saving covers.

Example response

{
  "alone_kg": 0,
  "lines_compared": 0,
  "money": [
    {
      "alone": 0,
      "currency": "EUR",
      "lines_compared": 0,
      "nested": 0,
      "rectangular": 0,
      "runs": 0,
      "saved": 0,
      "saved_combining": 0,
      "saved_true_shape": 0,
      "split_lines": 0
    }
  ],
  "nested_kg": 0,
  "potential": {
    "alone_kg": 0,
    "lines_compared": 0,
    "money": [
      {
        "alone": 0,
        "currency": "EUR",
        "lines_compared": 0,
        "nested": 0,
        "rectangular": 0,
        "runs": 0,
        "saved": 0,
        "saved_combining": 0,
        "saved_true_shape": 0,
        "split_lines": 0
      }
    ],
    "nested_kg": 0,
    "rectangular_kg": 0,
    "runs": 0,
    "saved_combining_kg": 0,
    "saved_kg": 0,
    "saved_true_shape_kg": 0,
    "split_lines": 0
  },
  "rectangular_kg": 0,
  "runs_counted": 0,
  "runs_simulated": 0,
  "saved_combining_kg": 0,
  "saved_kg": 0,
  "saved_true_shape_kg": 0,
  "split_lines": 0
}