---
title: Recipe — cut a job nest
description: Take a job nest's sheets to the cutting machine over the API: DXF or SVG per sheet, a zip of them all, and the JSON nest plan an integration reads sheets from.
---

# Recipe: cut a job nest

A [job nest](../api/nest-runs.md) lays a backlog of sheet-metal parts out on
shared sheets. This recipe takes those sheets to the machine **over the
API** — and the sheet a single calculation's own price laid its part out
on the same way — so a CAM system, an MES or an agent can do it without the
dashboard.

Every export reads `parts:read`. Nothing here changes a calculation's
price or a job nest's result: an export is a read of what was stored.

---

## 1. Export a job nest's sheets

`GET /nest-runs/{run_id}/export` writes the sheets of every solved material
and thickness of the job nest. Each distinct layout is one sheet; the
manifest and the plan say how many identical sheets it stands for.

| Query | Values | What you get |
| --- | --- | --- |
| `format` | `dxf` (default), `svg`, `json` | DXF or SVG per sheet, or the JSON nest plan |
| `sheet` | `all` (default), or one key `<group>:<index>` | every sheet — a zip (DXF/SVG) or the whole plan (JSON) — or that one sheet's file |
| `exploded` | `false` (default), `true` | DXF only: plain closed polylines in place, no block references |
| `revision` | omitted (the active revision), or a number | the sheets as laid out in that revision of every material and thickness — `1` is the job nest's own layout; every adjustment posted through `POST /nest-runs/{run_id}/groups/{group_id}/revisions` is the next |

<CodeTabs>

```bash title="cURL"
# every sheet as DXF: a zip with plan.json and manifest.csv
curl -o nest.zip \
  "https://api.arcnm.io/api/v1/nest-runs/$RUN_ID/export?format=dxf" \
  -H "X-API-Key: $ARCNM_API_KEY"

# one sheet, for a machine that reads no blocks
curl -o sheet-0-0.dxf \
  "https://api.arcnm.io/api/v1/nest-runs/$RUN_ID/export?format=dxf&sheet=0:0&exploded=true" \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.get(
    f"https://api.arcnm.io/api/v1/nest-runs/{run_id}/export",
    params={"format": "json"},
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
plan = resp.json()
for sheet in plan["sheets"]:
    print(sheet["key"], sheet["repeat"], "x", sheet["container"]["key"], sheet["count"], "parts")
```

```typescript title="TypeScript"
const resp = await fetch(
  `https://api.arcnm.io/api/v1/nest-runs/${runId}/export?format=svg&sheet=0:0`,
  { headers: { "X-API-Key": process.env.ARCNM_API_KEY! } },
)
const svg = await resp.text()
```

</CodeTabs>

The file name travels in `Content-Disposition`
(`nest-run-<run id>-sheet-<group>-<index>.dxf`, `nest-run-<run id>-dxf.zip`,
an exploded DXF `nest-run-<run id>-dxf-exploded.zip`,
`nest-run-<run id>-plan.json`). A job nest that is still running exports
what is solved so far; one with nothing solved yet answers
`nest_run_nothing_to_export` (409), a sheet key it has not
`nest_run_sheet_not_found` (404) — see [Errors](../errors.md).

## 2. Export a calculation's own sheet

`GET /calculations/{calculation_id}/sheet-nest/export` writes the sheet the
calculation's own price laid its part out on — the part alone, as many
copies as its price put on one sheet. It takes `format` and `exploded` as
above; there is one sheet, so no `sheet` and no zip. A calculation that
stored no sheet layout answers `sheet_layout_not_found` (404).

## 3. The DXF

- **R2010**, `$INSUNITS` 4: every coordinate is a millimetre. The sheet's
  origin is a corner, x along the sheet's length, y across its width.
- **Layers**: `SHEET` (the sheet's rectangle), `MARGIN` (the usable area,
  dashed), `REMNANT` (the reusable rest the sheet leaves, when it does),
  `CUT_OUTER` (outer contours), `CUT_INNER` (holes), `LABEL` (the part
  reference and order reference at each copy, and the sheet's title).
- **One block per part, one insert per copy.** The block `PART_P1` holds
  the part's contour and holes as closed lightweight polylines in the part's
  own frame. Each `INSERT` places one copy: a mirrored copy is reflected
  across the part's own x axis (`yscale` −1), then turned counter-clockwise
  by `rotation`, then set at `insert`.
- **`exploded=true`** writes each copy's contours as closed polylines in
  place, all in the world coordinate system, and no blocks — for a cutting
  system that does not read block references, or reads a reflected one in
  its own coordinate system.
- **What the drawing says about itself**: the header's custom properties
  (`NEST_RUN_ID` or `NEST_CALCULATION_ID`, `NEST_SHEET`,
  `NEST_SHEETS_TO_CUT`, `NEST_MATERIAL`, `NEST_GAUGE_MM`, `NEST_CONTAINER`,
  `NEST_SHEET_MM`, `NEST_PARTS`, `NEST_UTILISATION`, `NEST_TOLERANCE`) and
  a title above the sheet state the same.
- **Tolerance**: contours are within 0.2 mm of the unfolded flat pattern;
  arcs are polylines. Check a contour against the part's drawing before the
  first cut, as you would any nest.

## 4. The SVG

The same geometry, `viewBox` in millimetres, y up inside the `sheet` group
(a `translate` and `scale(1 -1)`), each DXF layer a `<g>` of that class.
Every outer contour carries `data-part`, `data-line` and `data-order`, so a
viewer can name what it shows.

## 5. The JSON nest plan (schema v1)

The plan is the export as data: what the DXF draws, readable by an
integration that lays the parts out itself or checks a file.

```json
{
  "v": 1,
  "units": "mm",
  "source": {"kind": "run", "run_id": "…", "environment_id": "…", "created_at": "…", "finished_at": "…"},
  "tolerance": {"contour_mm": 0.2, "arcs": "polylines", "note": "Contours within 0.2 mm of the unfolded flat pattern; arcs as polylines."},
  "parts": [
    {
      "ref": "P1",
      "name": "bracket",
      "line_id": "…",
      "calculation_id": "…",
      "order_ref": "4711",
      "quantity": 12,
      "placed": 12,
      "net_area_mm2": 21840.5,
      "outline": [[0, 0], [300, 0], [300, 120], [0, 120]],
      "holes": [[[40, 40], [80, 40], [80, 80], [40, 80]]]
    }
  ],
  "sheets": [
    {
      "key": "0:0",
      "index": 0,
      "group": 0,
      "repeat": 2,
      "container": {"kind": "format", "key": "3000 x 1500", "length_mm": 3000, "width_mm": 1500},
      "material": "S235JR",
      "gauge_mm": 3,
      "margin_mm": 10,
      "spacing_mm": 5,
      "count": 17,
      "utilisation": 0.71,
      "remnant": {"x_mm": 2100, "y_mm": 0, "length_mm": 900, "width_mm": 1500},
      "placements": [
        {"part": "P1", "line_id": "…", "order_ref": "4711", "x": 10, "y": 10, "rot_deg": 90, "mirrored": false}
      ]
    }
  ]
}
```

| Field | Meaning |
| --- | --- |
| `v`, `units` | The schema version (1) and the unit of every length (mm). |
| `source` | What the plan is of: `kind` `run` (with `run_id`, `environment_id`, `created_at`, `finished_at`) or `calculation` (with `calculation_id`). |
| `tolerance` | What the contours are good to. |
| `parts[]` | One per job-nest line (or the one part): `ref` names it in placements and in the DXF block `PART_<ref>`; `outline` runs counter-clockwise, each ring of `holes` clockwise, in the part's own frame; `quantity` copies ordered, `placed` on the sheets; `line_id` re-enters a quote as `nest_item_id`. |
| `sheets[]` | `key` names the sheet in `sheet=` and in file names (`<group>:<index>`; `0` for a calculation's sheet); `group` the material and thickness it belongs to; `repeat` identical sheets it stands for; `container` what it is cut from (`format` or `remnant`, the key you stated, its size); `material`, `gauge_mm`; `margin_mm` and `spacing_mm` every copy keeps; `count` copies on the sheet; `utilisation` their net area over the sheet's; `remnant` the reusable rest, when one is left. |
| `placements[]` | One per copy: `part`, and where it sits — mirrored across its own x axis first when `mirrored`, then turned `rot_deg` counter-clockwise about its origin, then set at (`x`, `y`). |

A placement's contour on the sheet is therefore, for each point (px, py) of
the part's outline: flip py when mirrored, rotate by `rot_deg`, add
(`x`, `y`). That is exactly the DXF insert's transform.

## 6. Labels for the rests

Once the job nest is released (`PATCH /nest-runs/{run_id}` with
`counts_toward_savings: true`), the reusable rests its sheets leave are
remnants of the environment. Print their rack labels in one go:

```bash
curl -o rests.svg \
  "https://api.arcnm.io/api/v1/nest-runs/$RUN_ID/remnant-labels?lang=de" \
  -H "X-API-Key: $ARCNM_API_KEY"
```

One SVG, one label per rest, sized in millimetres (100 × 50 mm each) —
print at 100 %. Each label carries the size, thickness, material, pieces,
origin and date, and a Code 128 barcode of the piece's **code**, the first
12 hex digits of its id. A single piece's label is
`GET /remnants/{remnant_id}/label`. When the piece comes off the rack, the
scanner's reading finds it again in any state:

```bash
curl "https://api.arcnm.io/api/v1/remnants/by-code/3F9A0C12B7D4" \
  -H "X-API-Key: $ARCNM_API_KEY"
```

`404 nest_run_no_rests` says the job nest put nothing into stock — not
released yet, no reusable rest, or an environment that does not credit
remnants (then a release books no stock at all).

## 7. From an agent

The MCP tools `arcnm_nest_run_export` and `arcnm_sheet_nest_export` answer
the plan inline for `format="json"` (past 256 KB, without the contours) and,
for DXF and SVG, each sheet's download link — the same routes as above, to
fetch with the API key. See [MCP for agents](../mcp.md).
