API reference
Every setting on the v3 request's saw object — what it accepts, what it defaults to, which saws it applies to, and what the platform does when two settings disagree.
A SmartCut optimisation request describes the machine in one
object: saw. It carries the stock type being cut, the cutting
method, the blade width, the stacking and packing options, and, optionally, the
saw's identity (vendor + model) so the platform can
apply that saw's own constraints.
A request can carry one saw (saw as an object,
applied to the whole job), several (saw as an array
of objects that each carry an id, referenced by
materials[].sawId), or a saw per material
(materials[].saw). The rules below apply to each saw independently.
Settings that contradict each other are resolved, not rejected.
A cut type the stock cannot take is clamped, a spacing value on a saw that has no
spacing is zeroed, and the response's warnings name the rule that
fired. Only a value outside the schema is a 400. 12 rules do
that resolving. All of them are listed below, and you can run your own saw
through them.
Interactive
Build a saw with the controls, or paste one — a bare saw object, an array of identified saws, or a whole v3 request. Everything runs in your browser against the same schema and the same rule registry the API uses; nothing is sent anywhere.
stockTypeType of stock material
cutTypeType of cutting algorithm. `guillotine` and `beam` produce edge-to-edge saw cuts; `efficiency` packs without the guillotine constraint; `nesting` is IRREGULAR nesting for CNC routers and similar — give each part an `outline` (and optional `holes`) and it is packed as its true shape rather than its bounding rectangle.
cutPreferencePreferred cutting direction. Only applicable when cutType is 'guillotine' or 'beam'. Set to 'flex' to try both 'l' and 'w' on a per-sheet basis and keep the better orientation per sheet — charged at 2× the standard credit rate.
bladeWidthWidth of the saw blade
stackHeightNot applicable to this saw — it is accepted, but has no effect.
options.stackingModeWhether sheets that share a cutting pattern are cut together as a **stack**: several sheets laid on top of each other and cut once. In the result, a stack is one `stock` entry whose `stack` is the number of sheets, and each part cut from it carries `stacked: { sheet, of }`. - `identical`: stack only when every position holds the same part (same size and material) on every sheet. - `dimensions`: stack when every position holds a part of the same size. The parts may be different parts, so each sheet of the stack can yield different parts. - `none`: never stack. Every sheet is cut individually. Stack depth is capped at `⌊saw.stackHeight ÷ thickness⌋`. Thickness is the stock's `t`, or else the thickest part on the sheet. When neither is known, nothing is stacked. Stacking is also off when `guillotineOptions.strategy` is `time`.
guillotineOptions.strategyCutting strategy
guillotineOptions.maxPhaseMaximum cutting phase — the number of turns a board may take: 0 = unlimited, 1 = two-stage cutting (rips, one turn, crosscuts — every strip takes only parts whose cross dimension matches the strip), 2 = three-stage, … Enforced exactly as sent for every cut type, except where a saw profile (sawProfileId) states the saw's own limit: then 0 takes the profile's default, and on a saw whose control counts its own turns a higher value is lowered to the saw's ceiling. Mayer (mayer-may, PC7000 control): default 3, maximum 4 — 4 is opt-in, because the PC7000 has no automatic turn table and each extra turn is one more piece the operator turns and feeds by hand; it saves stock on some jobs (7 of 713 in our Mayer test set, one sheet each). A Max `model` runs only when the resulting cap is 0 (the Mayer and Biesse profiles default to 3, so 0 there still means 3) — any cap runs the Fast model; on a beam saw it also needs a recognised saw profile.
guillotineOptions.headCutsEnable head cuts
guillotineOptions.limitStripDimensionsPrefer narrower strips, derived from the job's own parts (mean part depth, floored at a fifth of the board). Carries no dimension of its own — use maxStripWidth to state an operator limit. With both set the TIGHTER of the two wins: on a job of small parts the derived cap is usually well below any operator limit, and maxStripWidth then has no effect at all. To make your own number the cap, send it with this flag off.
guillotineOptions.verticalPanelSawArrange the layout for a vertical panel saw: narrowest strips at the top, residual waste at the bottom, cut from the top down. Works on any saw; no profile required.
guillotineOptions.maxStripWidthWidest assembled strip an operator can safely handle, in the same units as every other dimension you send. The optimiser steers away from strips wider than this — it opens strips on parts within the limit wherever it can. Set this alone (limitStripDimensions off) and your number IS the cap. With limitStripDimensions also on, the tighter of the two wins — the parts-derived cap is often tighter, and then this value has no effect. It is a STRONG PREFERENCE, not a guarantee — a part whose own smaller side exceeds the limit cannot be made to fit one, and layouts are never left unplaced to satisfy it. Hard rejection of an over-wide strip requires a saw profile (sawProfileId), whose oracle reports strip-width-exceeded. Null = no limit.
efficiencyOptions.primaryCompressionNot applicable to this saw — it is accepted, but has no effect.
options.minSpacingNot applicable to this saw — it is accepted, but has no effect.
options.minSpacingDimension.dimensionNot applicable to this saw — it is accepted, but has no effect.
options.minSpacingDimension.minSpacingNot applicable to this saw — it is accepted, but has no effect.
minOffcut.lMinimum long side of a reusable offcut
minOffcut.wMinimum short side of a reusable offcut
minOffcut.areaMinimum area of a reusable offcut, independent of side length
options.stockSelectionHow the optimiser chooses between the stock sizes you send. - `efficiency`: pick the stock that gives the best material utilisation. - `smallest`: use the smallest stock (by area) that the parts fit on first.
options.offcutPriorityOffcut priority: 0 = never use offcut stock, 0.5 = offcuts compete with full sheets on score (default), 1 = always use offcuts first. Between 0.5 and 1 offcuts are preferred progressively more strongly; values between 0 and 0.5 currently behave as 0.5.
Saw vendor (e.g. Biesse, Mayer, SCM). Part of the identity pair (`vendor` + `model`) used to look up this saw's profile, which supplies its algorithm constraints and preferences. Optional — without an identity (or a `sawProfileId`) no profile is applied.
Saw control software version (e.g. "CADmatic 5") — selects the CADmatic output dialect where recognised (5 → CAD5/PTNR, 3|4 → CAD4/PTN3), otherwise provenance only.
The schema accepts this saw. 3 rules changed or explained something — below.
cut-type.defaultdefaultinfoNo cutType given — sheet stock defaults to 'guillotine'.
cutType→"guillotine"cut-preference.defaultdefaultinfoNo cutPreference given — guillotine on sheet stock defaults to 'l'.
cutPreference→"l"stacking-mode.defaultdefaultinfoNo options.stackingMode given — a guillotine saw stacks by 'identical'.
options.stackingMode→"identical"saw to send{}Every default filled in and every rule applied — the saw the optimiser sees, and the one the response echoes back.
{
"stockType": "sheet",
"bladeWidth": 0,
"stackHeight": 100,
"guillotineOptions": {
"strategy": "efficiency",
"maxPhase": 0,
"headCuts": false,
"limitStripDimensions": false,
"verticalPanelSaw": false,
"maxStripWidth": null
},
"efficiencyOptions": {
"primaryCompression": "w"
},
"options": {
"stockSelection": "efficiency",
"offcutPriority": 0.5,
"minSpacing": 0,
"stackingMode": "identical"
},
"cutType": "guillotine",
"cutPreference": "l"
}linear.no-cut-type-or-preferencecoercecut-type.defaultdefaultcut-type.valid-for-stockclampcut-preference.valid-for-stock-cut-typeclampcut-preference.defaultdefaultstacking-mode.defaultdefaultstacking-mode.none-for-rollcoercemin-spacing.efficiency-onlycoercestrategy.time-ignored-for-beamcoercealgorithm.ineligibleignoreprofile.max-nested-cut-depth-sets-max-phasederiveprofile.cut-preference-clampedderiveReference
Every public field of the saw object, read from the schema the API validates against. Omit a field and the default applies. Send a field that does not apply to your saw and it is accepted but has no effect — the explorer above lists those explicitly.
| Setting | Type | Accepts | Default | Applies to | Description |
|---|---|---|---|---|---|
| General | |||||
stockType stock type | enum | sheet, linear, roll | "sheet" | Always | Type of stock material |
| Cutting | |||||
cutType cut type | enum | efficiency, guillotine, beam, nesting | — | Always | Type of cutting algorithm. `guillotine` and `beam` produce edge-to-edge saw cuts; `efficiency` packs without the guillotine constraint; `nesting` is IRREGULAR nesting for CNC routers and similar — give each part an `outline` (and optional `holes`) and it is packed as its true shape rather than its bounding rectangle. |
cutPreference cut preference | enum | l, w, flex | — | sheet or linear stock · guillotine or beam cutting | Preferred cutting direction. Only applicable when cutType is 'guillotine' or 'beam'. Set to 'flex' to try both 'l' and 'w' on a per-sheet basis and keep the better orientation per sheet — charged at 2× the standard credit rate. |
| Blade | |||||
bladeWidth blade width | number | number, ≥ 0 | 0 | Always | Width of the saw blade |
bladeWidthCross | number | number, ≥ 0 | — | Always | |
| Stacking | |||||
stackHeight stack height | number | integer, ≥ 0 | 100 | beam cutting | The saw's maximum cutting height, in the same units as every other dimension you send. Sets how many sheets one pattern may be cut through at once: `⌊stackHeight ÷ sheet thickness⌋`. Applies to any saw, not only beam saws. Only read when `options.stackingMode` is not `none`. |
options.stackingMode stacking mode | enum | dimensions, identical | — | sheet or linear stock | Whether sheets that share a cutting pattern are cut together as a **stack**: several sheets laid on top of each other and cut once. In the result, a stack is one `stock` entry whose `stack` is the number of sheets, and each part cut from it carries `stacked: { sheet, of }`. - `identical`: stack only when every position holds the same part (same size and material) on every sheet. - `dimensions`: stack when every position holds a part of the same size. The parts may be different parts, so each sheet of the stack can yield different parts. - `none`: never stack. Every sheet is cut individually. Stack depth is capped at `⌊saw.stackHeight ÷ thickness⌋`. Thickness is the stock's `t`, or else the thickest part on the sheet. When neither is known, nothing is stacked. Stacking is also off when `guillotineOptions.strategy` is `time`. |
| Guillotine options | |||||
guillotineOptions.strategy guillotine strategy | enum | efficiency, time | "efficiency" | sheet stock · guillotine cutting | Cutting strategy |
guillotineOptions.maxPhase maximum phase | number | integer, ≥ 0, ≤ 10 | 0 | guillotine or beam cutting | Maximum cutting phase — the number of turns a board may take: 0 = unlimited, 1 = two-stage cutting (rips, one turn, crosscuts — every strip takes only parts whose cross dimension matches the strip), 2 = three-stage, … Enforced exactly as sent for every cut type, except where a saw profile (sawProfileId) states the saw's own limit: then 0 takes the profile's default, and on a saw whose control counts its own turns a higher value is lowered to the saw's ceiling. Mayer (mayer-may, PC7000 control): default 3, maximum 4 — 4 is opt-in, because the PC7000 has no automatic turn table and each extra turn is one more piece the operator turns and feeds by hand; it saves stock on some jobs (7 of 713 in our Mayer test set, one sheet each). A Max `model` runs only when the resulting cap is 0 (the Mayer and Biesse profiles default to 3, so 0 there still means 3) — any cap runs the Fast model; on a beam saw it also needs a recognised saw profile. |
guillotineOptions.headCuts head cuts | boolean | true, false | false | guillotine or beam cutting | Enable head cuts |
guillotineOptions.limitStripDimensions limit strip dimensions | boolean | true, false | false | guillotine or beam cutting | Prefer narrower strips, derived from the job's own parts (mean part depth, floored at a fifth of the board). Carries no dimension of its own — use maxStripWidth to state an operator limit. With both set the TIGHTER of the two wins: on a job of small parts the derived cap is usually well below any operator limit, and maxStripWidth then has no effect at all. To make your own number the cap, send it with this flag off. |
guillotineOptions.verticalPanelSaw vertical panel saw | boolean | true, false | false | guillotine or beam cutting | Arrange the layout for a vertical panel saw: narrowest strips at the top, residual waste at the bottom, cut from the top down. Works on any saw; no profile required. |
guillotineOptions.maxStripWidth max strip width | number | number, ≥ 0 | null | guillotine or beam cutting | Widest assembled strip an operator can safely handle, in the same units as every other dimension you send. The optimiser steers away from strips wider than this — it opens strips on parts within the limit wherever it can. Set this alone (limitStripDimensions off) and your number IS the cap. With limitStripDimensions also on, the tighter of the two wins — the parts-derived cap is often tighter, and then this value has no effect. It is a STRONG PREFERENCE, not a guarantee — a part whose own smaller side exceeds the limit cannot be made to fit one, and layouts are never left unplaced to satisfy it. Hard rejection of an over-wide strip requires a saw profile (sawProfileId), whose oracle reports strip-width-exceeded. Null = no limit. |
| Efficiency options | |||||
efficiencyOptions.primaryCompression primary compression | enum | l, w | "w" | sheet stock · efficiency cutting | Primary compression direction (l=length/horizontal, w=width/vertical) |
| Spacing | |||||
options.minSpacing minimum spacing | number | number, ≥ 0 | 0 | efficiency cutting | Minimum gap between parts (not between a part and the stock edge), in the same units as every other dimension you send. The blade width is the floor: the gap used is the larger of `bladeWidth` and this value, not their sum. Only applies when `cutType` is `efficiency`. Other cut types space parts by the blade width, so the value is set to 0 and a warning is returned. |
options.minSpacingDimension.dimension minimum dimension | number | number, ≥ 0 | — | efficiency cutting | Parts with length or width equal to or smaller than this value will use the spacing below |
options.minSpacingDimension.minSpacing dimension specific minimum spacing | number | number, ≥ 0 | — | efficiency cutting | Minimum spacing for parts meeting the dimension threshold |
| MinOffcut | |||||
minOffcut.l minOffcutL | number | number, ≥ 0 | — | Always | Minimum long side of a reusable offcut |
minOffcut.w minOffcutW | number | number, ≥ 0 | — | Always | Minimum short side of a reusable offcut |
minOffcut.area minOffcutArea | number | number, ≥ 0 | — | Always | Minimum area of a reusable offcut, independent of side length |
| Optimization | |||||
options.stockSelection stock selection | enum | efficiency, smallest | "efficiency" | Always | How the optimiser chooses between the stock sizes you send. - `efficiency`: pick the stock that gives the best material utilisation. - `smallest`: use the smallest stock (by area) that the parts fit on first. |
options.offcutPriority offcut priority | number | number, ≥ 0, ≤ 1 | 0.5 | Always | Offcut priority: 0 = never use offcut stock, 0.5 = offcuts compete with full sheets on score (default), 1 = always use offcuts first. Between 0.5 and 1 offcuts are preferred progressively more strongly; values between 0 and 0.5 currently behave as 0.5. |
| Identity | |||||
vendor | string | string | — | Always | Saw vendor (e.g. Biesse, Mayer, SCM). Part of the identity pair (`vendor` + `model`) used to look up this saw's profile, which supplies its algorithm constraints and preferences. Optional — without an identity (or a `sawProfileId`) no profile is applied. |
softwareVersion | string | string | — | Always | Saw control software version (e.g. "CADmatic 5") — selects the CADmatic output dialect where recognised (5 → CAD5/PTNR, 3|4 → CAD4/PTN3), otherwise provenance only. |
Reference
Which cutting method each stock type accepts, and the cut directions that pair allows. A cut type outside the row is clamped to the row's first entry; a cut direction outside the cell is cleared.
| Stock type | efficiency | guillotine | beam | nesting |
|---|---|---|---|---|
| sheet | accepted no cut direction | acceptedl, w, flex | acceptedl, w, flex | accepted no cut direction |
| roll | accepted no cut direction | acceptedw | not accepted | accepted no cut direction |
| linear | not accepted | not accepted | not accepted | not accepted |
Linear stock is cut to length, so there is no layout to arrange and it takes no cut
type and no cut direction at all. Roll stock rips one way, across the roll
(w).
Reference
Applied in this order, each one seeing the result of the ones before it. Every rule has a stable id that appears in the response warnings, so a warning can be looked up here.
linear.no-cut-type-or-preference coerce info Linear stock (bars, profiles, lengths) is cut to length; the optimiser arranges nothing on it, so a cut type or cut preference sent with linear stock is dropped rather than applied.
reads stockType → writes cutTypecutPreference
cut-type.default default info cutType is optional. When omitted, the stock type's first accepted cut type is used (sheet and roll: guillotine; linear stock takes none).
reads stockTypecutType → writes cutType
cut-type.valid-for-stock clamp warning Each stock type accepts a fixed set of cut types (sheet: guillotine, efficiency, beam, nesting; roll: guillotine, efficiency, nesting; linear: none). A cutType outside that set resolves to the first accepted one.
reads stockTypecutType → writes cutType
cut-preference.valid-for-stock-cut-type clamp warning Only the guillotine family (guillotine, beam) has a cut direction: sheet stock accepts l, w or flex; roll stock rips one way (w). Efficiency, nesting and linear have no direction, so a value sent for them is cleared.
reads stockTypecutTypecutPreference → writes cutPreference
cut-preference.default default info A guillotine-family saw with no cut preference cuts length-first (l), or the only direction the stock allows (roll: w).
reads stockTypecutTypecutPreference → writes cutPreference
stacking-mode.default default info Jon, 2026-10-01: now that a stack returns every part with its own identity and label per sheet, a BEAM saw stacks identical patterns by footprint ('dimensions') unless the request says otherwise; every other saw keeps 'identical' (the same part on every sheet). An explicit mode always wins.
reads cutTypeoptions.stackingMode → writes options.stackingMode
stacking-mode.none-for-roll coerce warning Roll stock is a single continuous length; there are no sheets to stack, so any stacking mode is forced to none.
reads stockTypeoptions.stackingMode → writes options.stackingMode
min-spacing.efficiency-only coerce warning Part-to-part spacing is an efficiency-packing concept. The guillotine family and nesting derive their gaps from the blade width (kerf), so a spacing value sent for them is zeroed rather than carried as a setting the layout never honours.
reads cutTypeoptions.minSpacingoptions.minSpacingDimension.dimensionoptions.minSpacingDimension.minSpacing → writes options.minSpacingoptions.minSpacingDimension.dimensionoptions.minSpacingDimension.minSpacing
strategy.time-ignored-for-beam coerce warning 'time' trades material efficiency for layouts whose strips share cut positions, so a manual operator moves the fence fewer times. A beam saw positions its fence automatically for every cut, so the trade costs material and buys nothing — the setting is resolved to 'efficiency' rather than rejected, and the job runs.
reads cutTypeguillotineOptions.strategy → writes guillotineOptions.strategy
algorithm.ineligible ignore info The Max tiers are gated per family (rectangle-guillotine-max-* need a beam or guillotine saw, an UNCAPPED job — no maxPhase from the saw or its profile, RM-458 — and a part cap; irregular-nesting-max-* need a nesting saw). A model that does not fit the job safely falls back to the default — it never errors.
reads algorithmcutType → writes nothing (the value is accepted, it just has no effect)
profile.max-nested-cut-depth-sets-max-phase derive info When a recognised saw (vendor + model) declares a maximum nested cut depth and the request leaves maxPhase at 0 (no limit), the profile's depth is applied so the optimiser never plans a pattern the saw's controller rejects.
reads guillotineOptions.maxPhase → writes guillotineOptions.maxPhase
profile.cut-preference-clamped derive warning A saw that physically cannot rip short-side-first must not be handed a 'w' job. When a recognised profile declares supportedCutPreferences, a direction outside the set is steered to 'flex' if allowed (the optimiser then chooses per board within the set), else the first allowed direction.
reads cutPreference → writes cutPreference
Kinds: default fills an unset value · clamp replaces a value the matrix does not allow · coerce rewrites a value another setting makes meaningless · ignore changes nothing and explains why the value will not take effect · derive means a recognised saw profile supplied or narrowed the value.
Reference
Send vendor and model and the platform resolves the saw's own profile: the settings it applies, the constraints the optimiser plans within so it never produces a pattern the saw's controller rejects, and the tuning it brings with it. Any model name in the aliases column resolves.
| Vendor | Saw | Export formats | Production | model values that resolve | Saw settings it applies | Limits it plans within | Export file |
|---|---|---|---|---|---|---|---|
| Biesse | Biesse (Optiplanner XML) | biesse-xml | Validated | optiplannerWN6XX_3200Selco WN6XX, 3200mm bedWN6XX_3800X3200Selco WN6XX, 3800×3200mm bedWN6XX_3800X3800Selco WN6XX, 3800×3800mm bedWN6XX_4500Selco WN6XX, 4500mm bedWN6XX_5900Selco WN6XX, 5900mm bedWN6XX7XX_3800Selco WN6XX/WN7XX, 3800mm bedWN6XX7XX_4500Selco WN6XX/WN7XX, 4500mm bedWN6XX7XX_5900Selco WN6XX/WN7XX, 5900mm bedWN6XXTP_3200Selco WN6XX TP, 3200mm bedWN6XXTP_3800X3200Selco WN6XX TP, 3800×3200mm bedWN6XXTP_3800X3800Selco WN6XX TP, 3800×3800mm bedWN6XXTP_4500Selco WN6XX TP, 4500mm bedWN7XX_3800Selco WN7XX, 3800mm bedWN7XX_4500Selco WN7XX, 4500mm bedWN7XX_5900Selco WN7XX, 5900mm bed |
|
|
|
| Biesse | Biesse Selco (Beam) | biesse-xml | Provisional | None |
|
| defaults |
| Giben | Giben (.ac) | giben-link | Provisional | link |
| none declared | defaults |
| Homag | Homag (PTX) | ptx | Validated | ptx |
|
|
|
| Homag | Homag CADmatic | homag-cadmatic | Validated | cadmatic |
|
| defaults |
| Homag | MagiCut (CPOUT) | homag-cpout | Provisional | magicut |
| none declared | defaults |
| Jingwei | Jingwei (CNC XML) | jingwei-xml | Provisional | None |
| none declared | defaults |
| Mayer | Mayer (.may) | mayer-may | Validated | mayPC7000Otto Mayer beam saw, PC7000 control (Erler) |
|
|
|
| Schelling | Schelling Commander 2 | schelling-commander-2 | Provisional | commander-2 |
| none declared | defaults |
| Schelling | Schelling Commander 4 | schelling-commander-4 | Provisional | commander-4 |
| none declared | defaults |
| SCM | SCM (Pratika) | biesse-xml | Provisional | pratika |
|
| defaults |
| SCM | SCM Link (.900) | scm-link | Provisional | link |
| none declared | defaults |
| Striebig | Striebig (vertical panel saw / IST PIOS) | striebig-csv | Provisional | None |
| none declared | defaults |
Saw settings it applies are saw fields filled in when you
leave them out, so send your own and yours stands. Limits it plans within
are enforced whatever you send, so the pattern is one this saw can cut.
Export file affects only the file written for the saw, never the layout.
"Validated" means output for that saw has been checked against the saw's own control
software.
The full request reference is in the v3 API reference, covering every endpoint, every field and runnable samples, and the narrative walkthrough is in the API guide.