Engine API
If you just cut panels, you do not need this page. The optimizer inside CutOptim already does everything described here. The Engine API is the same engine with no screen attached, for when other software needs cutting plans without a person opening the app.
Everything CutOptim does in your browser starts with one calculation: given these parts and this stock, what is the best way to cut them? The Engine API exposes exactly that calculation over the internet, so a different program can ask the question and get the answer back — no browser, no clicking, nobody logged in.
That is the whole idea. It is not a new optimizer, not a better optimizer, and not a bigger plan. It is the same engine, reachable by software instead of by a person.
Is this for me?
For the overwhelming majority of CutOptim users, the honest answer is no. If your working day involves opening CutOptim, typing in parts and stock, and printing or exporting the plan, the app is the product and this page is irrelevant to you.
The Engine API is for one situation: cutting plans need to appear inside software you already use, without anyone visiting CutOptim. In practice that means one of two people:
- You already run software that the cutting plan belongs inside. An ERP that holds your orders, a quoting tool that prices jobs, or a machine’s own software. Instead of an operator re-typing the same part list into CutOptim, that program asks the engine directly and shows the plan where the work already happens.
- You are having software built for you. By an in-house developer, a local software company, or the supplier of your machine. The Engine API is what they connect to.
Using the Engine API means somebody writes software against it. There is no interface, no spreadsheet to fill in and nothing to install — it is a service for programs, and the work is done by whoever writes that program. If nobody on your side is writing code, the app is what you want.
If you are not sure which side of that line you are on, a good test: could the plan appear without anyone asking for it? If yes, the API is relevant. If a person always decides to make a cutting plan, the app is already the right tool.
What it does
Your software sends the same two things you would type into the app — a list of parts and a list of stock — as JSON. The engine sends back a complete answer:
- The full layout. Every part, positioned on a specific sheet or bar, including whether it was rotated.
- A cut plan. Not just a picture of rectangles: the actual guillotine cut sequence, in order, so the plan can be executed on a panel saw.
- The numbers. How many sheets or bars the job takes, the yield percentage, how many cuts are needed, and the total price of the material used. For panels you also get the two honest cut counts — cut lines, which merges cuts that share one fence setting, and saw passes, which counts every pass — plus the total length sawn.
- Optionally, the drawing. Ask for
include: ["svg","csv","dxf"]and the response also carries the layout as a ready-made file — a self-contained 2D SVG drawing, an R12/AC1009 DXF, or a CSV cut list — inline in the JSON, with no storage and no second call. (SVG is 2D only.) - Your own identifiers, returned. Attach a
metaobject — an article number, an order line, a customer reference — to any part or stock row, and it comes back unchanged on every placed piece and every sheet or bar, so the plan lines up with your own system. This is the field to use when you want to send all your boards, tag each with your own code, and read back which board the optimizer chose — put the code instock[].metaand it is echoed onsheets[].meta. It never affects placement. Do not use thematerialfield for identification:materialis a hard partition (a part is only cut from stock of the same material), so tagging every stock row with a material while leaving the parts untagged makes every part come backunmatchedwith an empty result — see the material-aware section below.
There are four optimization modes, all matching the app — one for 2D panels, one for 1D linear material such as bars, profiles and tube, one for timber, where the material has a cross-section, and true-shape nesting (POST /v1/optimize/nest), which packs arbitrary polygons for laser, plasma and waterjet cutting (the app’s Nesting mode). Each optimize endpoint also has a free validation endpoint that checks a request without solving it (see below).
Endpoints
The base URL is https://api.cutoptim.com. The optimize and usage endpoints carry a key in an Authorization: Bearer <key> header; the validate and health endpoints need no key.
| Endpoint | What it does |
|---|---|
POST /v1/optimize/2d |
2D panel optimization |
POST /v1/optimize/1d |
1D / linear optimization — bars, profiles, tube |
POST /v1/optimize/wood |
Timber optimization — 1D with cross-section matching |
POST /v1/optimize/nest |
True-shape nesting — irregular polygons for laser, plasma and waterjet |
POST /v1/validate/2d · /1d · /wood · /nest |
Validate a request without solving — free, no key, no quota |
GET /v1/jobs/{id} |
Poll an asynchronous max-engine job — your own jobs only, no quota |
POST /v1/import/nest |
Read part outlines out of an SVG or DXF file — needs a key, spends no quota |
GET /v1/usage |
The ACCOUNT’s usage and quota for the current month (all keys share one) |
GET /v1/health |
Liveness check — needs no key |
Most calls are answered directly with the finished result. The one exception is the asynchronous max engine (see Three engines below): a max submission returns a job id, and you poll GET /v1/jobs/{id} until the plan is ready.
The validate endpoints take the same body as the matching optimize endpoint and check it without running the solve: a malformed request comes back as a 400 naming the exact bad field, and a well-formed one returns valid: true plus feasibility warnings (for example, a part that fits no stock). They cost nothing and need no key, so you can validate your payloads while you build the integration — before you even have a key — and confirm a request will not be rejected without spending one of your monthly calls.
Why timber has its own endpoint
Linear material knows one dimension, its length, so any bar can serve any part. Timber does not work that way: a 50×150 part cannot come out of a 50×100 bar, however much length is left in it. The wood endpoint therefore takes both cross-section sides on every part and every stock row, splits the job by cross-section, matches each section to its own stock, and returns the sections separately — each with its own bars and its own totals, alongside the figures for the whole job.
Two details worth knowing before you integrate it:
- The two cross-section sides can be sent in either order. 50×100 and 100×50 are the same bar turned over, so they are matched as one section. That means a difference in how your data happens to be entered cannot make material disappear.
- “No stock of this cross-section” and “did not fit” are reported separately. The first is a missing-material report, the second is a capacity problem, and they have different fixes — so mixing them into one list would send your user looking in the wrong place.
You could approximate this with several 1d calls of your own, grouping the parts yourself. It would cost one request from your quota per cross-section instead of one for the job, put the stock matching in your code, and produce a job total you would have to assemble yourself — one that would not necessarily agree with what the CutOptim app shows for the same job.
Parts from a CAD file
The nesting endpoint does not only take coordinates. A part may carry a source instead — an SVG or DXF document — and the server reads its outline, and any holes in it, out of the file. It is the same reader the app uses when you drop a drawing onto its Nesting mode, so a part library that already exists as CAD files does not have to be converted into coordinate lists first.
The file replaces only the geometry. Quantity, material, allowed rotations and your own metadata stay ordinary fields on the part row, exactly as they are when you send coordinates. One file describes one part; when a single drawing holds several separate components, POST /v1/import/nest splits it into ready-made part rows first — and that call needs a key but does not spend a request from your monthly quota.
Nothing is stored. The file exists only as the request itself: it is read in memory and gone by the time the answer is written. No copy is kept on disk or in a database, nothing is written to a log, and there is nothing to delete afterwards. Units are treated the same way — a DXF may declare millimetres or inches and we report what it said, but coordinates are never converted, because no value in this API carries a unit.
The same answer every time
The engine is deterministic: the same input always produces the same output. There is no randomness and no clock inside the algorithm.
This sounds academic but it is the practical reason to build on it. It means results can be cached — if you already asked about this exact job, you can safely reuse the answer instead of asking again. It also means the integration can be tested: a plan can be compared against a known-good result, and a difference is a real difference, not noise. Software that quotes a customer a price on Monday will quote the same price on Friday.
Three engines
The API offers a choice of engine. The first two run synchronously; the third is asynchronous. The difference is not quality — it is a trade-off between speed, whether the result can be cut on a panel saw, and how close it gets to the theoretical minimum.
heuristicis the default and the same one the app uses. It produces guillotine layouts: highest yield, every layout cuttable on a panel saw, and always a full cut plan. Synchronous.balancedis opt-in. It uses free nesting instead, which is dramatically faster on very large jobs — measured roughly 25× faster on a 2,000-part job — at the cost of slightly lower yield. The important catch: its layouts often cannot be cut edge-to-edge, so for those it returns no cut plan at all. Synchronous.maxis opt-in and 2D only. It is a server-side tree search that reaches the proven optimum on far more jobs than the default, and its layouts are still guillotine-cuttable. The cost is time: amaxsolve takes seconds to a minute, so it does not answer in the response. Instead,POST /v1/optimize/2dwithengine: "max"returns a job id, and you pollGET /v1/jobs/{id}until it is ready. It is still deterministic. Reach for it when a large, valuable job is worth the wait for the last few boards. It models one stock format at full sheet size with unlimited supply, so a request that also carries a second stock format, per-sidetrim, limited stock (respectStock), materials or grain groups is refused up front with a400naming exactly what it cannot do — before a call is charged. Send those jobs toheuristic, which models all of them.
balanced is not “better results”. It is faster and yields slightly less, and when its layout is not guillotine-cuttable there is no cut plan to hand to a saw operator. Choose it only when speed on a very large job matters more than a saw-ready plan. If you are unsure, stay on the default.
Limits
Each request is bounded, so a runaway job fails clearly instead of hanging:
| Limit | Value |
|---|---|
| Parts per request | 2,000 |
| Stock rows per request | 50 |
| Request body size | 1 MB |
| Request body size — nest paths that may carry a drawing | 10 MB |
| Active keys per account | 10 |
Keyless validate calls per address |
120 / minute |
max jobs queued or running per account |
5 |
Getting access
Start on the Engine API page. The Engine API is billed separately from the app plans, and no plan upgrade turns it on.
- Subscribe, or ask. Subscribing on the Engine API page is the fastest route — it runs a trial period, and access lands on your account by itself. If you would rather describe your integration first, or you need a volume beyond the standard plan, get in touch instead and say what you want to connect and roughly how many cutting plans a month it will need.
- Access appears on your account. Nothing else about your account changes.
- Create a key. An API keys card appears on your dashboard once your account has API access. You create, name and delete keys there yourself.
- Copy the key immediately. The full key is shown exactly once, at the moment you create it.
A key is displayed only once. CutOptim stores only a sha256 hash of it, never the key itself — so it cannot be read back out later, by you or by us. Copy it straight into your software’s configuration when you create it. If you lose a key, delete it and create a new one; if a key is ever exposed, delete it and the calls stop working immediately.
Treat a key like a password: it belongs in your software’s configuration, not in an email, a spreadsheet or a screenshot.
What the API keys card on your dashboard does
Three controls, and it is worth being precise about what each one changes — especially the last one, which people expect to touch billing and does not.
- Create key. Generates a new key and shows it once, right there. You give it a name (
ERP integration,staging) purely so you can tell your keys apart later. Up to 10 active keys per account. - The usage bar. Two numbers: your account’s total for the calendar month against the monthly quota, and per key, how much that key has spent. The per-key figure is there to answer which integration is eating the allowance — it is not a separate budget.
- Revoke. Stops that one key working, from the next call onwards. The row stays visible so its history is not lost.
Revoking a key has nothing to do with your subscription. It does not cancel anything, does not refund anything and does not free up quota — the plan keeps running and the allowance keeps standing, you simply no longer hold that particular key. Revoke when a key has been exposed or an integration is retired. To stop being billed, cancel the subscription instead; access then continues to the end of the period you already paid for, and after that even existing keys stop working.
One quota for the account, not one per key
Every active key on your account draws on the same monthly allowance. Creating a second key does not create a second quota — keys exist so you can separate staging from production, give each integration its own credential, and revoke one without disturbing the others.
GET /v1/usage reports the account’s position (used, limit, remaining), so it answers the question you actually have — how much is left before calls start failing — regardless of which key you asked with. When the allowance runs out, every key returns 402, not just the one that spent it.
Price and quota
The Engine API is billed separately from the app plans, with a fixed number of requests per month. The current price, the monthly request quota and the trial length are all listed on the Engine API page — that page reads them from our pricing configuration, so it is always the accurate figure.
For the technical detail — the exact request and response shape, every option, all error codes and how versioning works — see the API reference.
What this does not change
Worth stating plainly, because the Engine API is easy to misread as a change to the product:
- The optimizer in the app is unchanged. It still runs in your browser, exactly as before.
- Free, Pro and Workshop are unaffected. They still include the in-app optimizer, with the same limits as before. Nothing was moved behind the API.
- Nothing you do in the app consumes API requests. The monthly API quota is only touched by calls your own software makes.
The Engine API is an addition for people integrating CutOptim into other software. If that is not you, nothing changed.