Skip to main content
FOR DEVELOPERS

CutOptim Engine API

A deterministic cutting-optimization engine, callable over HTTP: the same request always returns the same cut plan — so you can audit it, quote from it, settle a dispute with it, and re-run last year’s order to get last year’s plan. It is the same engine that powers CutOptim, across the three rectangular modes (2D panels, 1D linear, and timber with cross-section matching), plus true-shape nesting for irregular polygon parts — POST /v1/optimize/nest, for laser, plasma and waterjet work. Send parts and stock, get back the full layout, cut plan and yield — ready to drop into an ERP, a quoting tool, or a machine’s own software.

See the full benchmark → · Measured, not claimed

Read the API reference →

Why build on it

DETERMINISTIC

The same input always returns the same output — no randomness, no clock in the algorithm. You can cache results and diff them in tests.

A REAL CUT PLAN

Not just rectangles: the guillotine cut sequence, cut lines vs. saw passes, sawn length, and a flag telling you whether it is producible on a panel saw.

PANEL-SAW AWARE

Kerf, per-side trim, tolerance, cost mode, grain groups, max cutting stages, rotation minimising — the same options the app exposes.

What the API does

Four cutting modes

One call each for 2D panels, 1D linear stock, timber with cross-section matching, and true-shape nesting of irregular polygons — POST /v1/optimize/2d, /1d, /wood and /nest.

True-shape nesting

POST /v1/optimize/nest packs arbitrary polygons (with holes) onto fixed sheets, interlocking parts into each other’s concave pockets — 6 sheets where the same parts by bounding box need 9. For laser, plasma and waterjet. Per-sheet exclusion zones (a defect, a clamp) come with it.

Material-aware

Tag parts and stock with a material and the optimizer partitions the job: each material is cut only from its own stock. On every mode; a per-material rollup comes back.

Edge banding

Name a banding type per edge (2D) and the response totals the running metres per type — per part and per order. Metadata: it never moves a part.

Inline export (SVG · DXF · CSV)

Ask for include:["svg","csv","dxf"] and the response carries the layout as a ready-made file, inline — a standalone 2D SVG drawing, an R12/AC1009 DXF, or a CSV cut list. No storage, no second call.

Metadata passthrough

Attach a meta object — your ERP article number, order-line id, customer ref — to any part or stock row and it comes back verbatim on every placed piece and every sheet/rod, so the plan reconciles with your system.

Free validation

POST /v1/validate/{2d,1d,wood,nest} schema-validates the same body without solving — no key, no quota. Check a payload will not be rejected and get feasibility warnings before you spend a call.

Cost or waste

minimizeCost ranks by the lowest total bill across priced stock sizes, mixing formats; the default minimizes material. Both run the same guillotine algorithm.

Stock priority & limited stock

Mark stock to use up first, treat quantities as a hard cap with respectStock, and flag must-cut parts that win board space when material is short.

A real cut plan

Not just rectangles: the guillotine cut sequence with per-step stop positions, cut lines vs. saw passes, sawn length, and a producible-on-a-panel-saw flag.

Panel-saw parameters

kerf, per-side trim, tolerance, grain groups, maxCutStages and rotation minimising — the same options the app exposes.

Deterministic & OpenAPI

The same input always returns the same output — cache and diff it. A pinnable engine version and an OpenAPI 3.1 document describe the whole contract.

Parts from CAD files

Send an SVG or DXF instead of coordinates: parts[].source reads the outline and its holes out of the drawing, and POST /v1/import/nest splits a multi-part file first. Nothing is stored — the file is parsed in memory and is gone with the response.

Which engine serves which mode

The endpoint you POST to picks the mode; the engine parameter picks the algorithm. The default heuristic engine serves 2D, 1D and timber; balanced and the asynchronous max engine are 2D only; and true-shape nesting runs on its own lbf engine. Same engine as the app, over HTTP.

Mode · endpointEngine · algorithm2D panels/v1/optimize/2d1D linear/v1/optimize/1dTimber · cross-section/v1/optimize/woodTrue-shape nest/v1/optimize/nestheuristicdefault · synchronousbalancedopt-in · 2D onlymaxasync · 2D onlylbfnesting · sparrow plannedOn 1D and timber, balanced simply aliases the heuristic (the response says so).
  • heuristic — The default — a guillotine multi-strategy packer. Highest yield, every layout is saw-cuttable, and it always returns a cut plan. It serves 2D, 1D and timber.
  • balanced — An opt-in MaxRects free-nester for 2D. Much faster on very large jobs for slightly less yield, but its layouts often cannot be sawn edge-to-edge, so they carry no cut plan.
  • max — An asynchronous tree search for 2D. It reaches the proven optimum on far more jobs, at seconds-to-a-minute per solve — you submit the job and poll GET /v1/jobs/{id} for the result. Still deterministic and saw-cuttable.
  • lbf — The true-shape nesting engine. It packs irregular polygons into each other’s pockets for laser, plasma and waterjet; a higher-density sparrow build is planned.

Which endpoint for which material: flat sheets — plywood, MDF, glass, acrylic, sheet metal — go to /v1/optimize/2d; bars, tube, pipe and profile to /v1/optimize/1d; structural timber (a 50×150 only from 50×150) to /v1/optimize/wood; irregular polygons for laser, plasma and waterjet to /v1/optimize/nest.

One call, a full plan

curl https://api.cutoptim.com/v1/optimize/2d \
  -H "Authorization: Bearer co_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "parts": [
      { "name": "Door",    "w": 600, "h": 400, "qty": 4 },
      { "name": "Shelf",   "w": 800, "h": 300, "qty": 6 }
    ],
    "stock":   [{ "w": 2440, "h": 1220, "price": 42 }],
    "options": { "kerf": 3, "effort": "balanced" },
    "engine":  "heuristic"
  }'

Comes back as:

{
  "metrics": { "sheetCount": 1, "yieldPct": 80.62, "placed": 10, "total": 10,
               "cutLines": 10, "sawPasses": 13, "cutLength": 10720, "totalPrice": 42 },
  "sheets":  [ … ],
  "cutPlan": [{ "sheet": 0, "step": 1, "axis": "h", "pos": 400, "length": 2440, "stage": 1 }, … ],
  "guillotineValid": true,
  "engineVersion": "1.0.0+10e0c941",
  "deterministic": true
}

Full request and response shape, every option, all error codes and all three engines:API reference →

Fast or dense? Pick with one option

The effort option trades solve time against yield. Here is that trade, measured on one demanding job — every figure comes from the real packer.

Effort switch: material yield vs solve timeEffort switch: material yield vs solve time. fast: 350 boards · 76.2% · ≈1.9 s. balanced: 330 boards · 80.8% · ≈4.8 s. max: reserved — denser needs a slower search. On most (smaller) jobs the two are identical; the gap only opens on large jobs like this one. balanced is the default and is never denser than fast can reach.Effort switch: material yield vs solve timeOne demanding job — about 1,550 parts on a 2.07 × 5.6 m board. Every figure measured on the real packer.74%76%78%80%82%84%02 s4 s6 ssolve time · faster →material yield · denser ↑⇄ the effort switch+4.6 pts yield · −20 boards−5.7% material · ≈2.5× slowerfast350 boards · 76.2% · ≈1.9 s★ balanced · default330 boards · 80.8% · ≈4.8 smaxreserveddenser needs aslower search
On most (smaller) jobs the two are identical; the gap only opens on large jobs like this one. balanced is the default and is never denser than fast can reach.

And it is fast either way: even the largest production jobs — 2,000 parts and more — solve in single-digit seconds on the default engine, comfortably inside the API time budget.

Pricing

€49/month
10,000 requests / month — hard cap, no overage, no surprise bill
14-day trial · billed in EUR · once the cap is reached, calls return 402 until the month rolls over

Larger volumes. 10,000 requests a month is the standard plan, not a ceiling on what we can run. If you need more — higher volume, separate keys for staging and production, or a dedicated arrangement — tell us your numbers and we price it individually. Tell us your volume →

The regular CutOptim plans (Free / Pro / Workshop) are unrelated to the API — the in-app optimizer stays included in them. See app pricing →

Solutions by industry

The same engine, positioned for the way one trade cuts. Each page shows the endpoint, a request and a response, and the fields that matter for that material.

Downloadable resource
Engine API one-pager

The why, what and how of the CutOptim Engine API on two pages — the three modes, a request and response, determinism and pricing. Print-ready, with a QR back to this page.

PDF2 pagesFree
Download the PDF

Frequently Asked Questions

Does CutOptim have an API?
Yes — the CutOptim Engine API exposes the same cutting engine over HTTP, for an ERP, a quoting tool or machine software, in all three modes the app has: 2D panels, 1D linear, and timber with cross-section matching.
Is there an API for laser, plasma or waterjet cutting?
Yes — true-shape nesting of irregular polygons is the fourth Engine API mode, POST /v1/optimize/nest. You send each part as a polygon outline (with optional holes) plus the stock sheets; the engine interlocks the parts into each other’s concave pockets and returns the placement of every copy, so a laser, plasma or waterjet job packs far tighter than a bounding box — on a representative 272-part job, 6 sheets where the same parts by bounding box need 9. Per-sheet exclusion zones (a defect, a clamp) and continuous rotation come with it. It runs on the Engine API today; the app itself still cuts rectangles.
Is the Engine API deterministic?
Yes. The same input returns the same output, so responses are cacheable and testable, and the engine version can be pinned for reproducible results.
What does an optimize response contain?
The full layout, a guillotine cut plan with per-step stop positions, and the metrics (sheet count, yield, cut lines, saw passes, sawn length). The 2D endpoint also returns edge-banding metres per type, and every endpoint accepts a material tag and returns a per-material rollup. You can also ask for the layout as an inline SVG, DXF or CSV, and attach a meta object to parts and stock that is echoed back verbatim.
Can the API give me a drawing, not just coordinates?
Yes. Add include:["svg","csv","dxf"] to an optimize request and the response carries the layout as a ready-made file, inline: a self-contained 2D SVG drawing, an R12/AC1009 DXF, or a CSV cut list. No storage and no second call. SVG is 2D only; a 1D or wood request returns a warning instead.
Can I attach my own IDs to parts and read them back?
Yes. Any part or stock row may carry a meta object — your ERP article number, order-line id or customer ref — and it comes back verbatim on every placed piece and every sheet or rod, so the cut plan reconciles with your own system. It never affects the layout.
Can I check a request without spending a call?
Yes. POST /v1/validate/2d, /1d or /wood schema-validates the same body the matching optimize endpoint takes without solving — no key and no quota. A 400 names the exact bad field, and you get feasibility warnings (a part that fits no stock) before you spend a real call.
Are there SDKs, webhooks or asynchronous jobs?
No SDKs and no webhooks — but there is an OpenAPI 3.1 specification you can point a code generator at to create a typed client. Most optimize calls are plain synchronous HTTP that return the finished plan directly. The one exception is the asynchronous max engine (2D only): POST /v1/optimize/2d with engine:"max" returns 202 Accepted with a jobId, and you poll GET /v1/jobs/{id} until it finishes — for when reaching the proven optimum is worth seconds-to-a-minute of solve time.
What are the request limits?
Up to 2,000 parts, 50 stock rows and a 1 MB request body per call. Even the largest production jobs solve in single-digit seconds, comfortably inside the time budget.
Manage API keys