Cut List Optimizer: Sheet, Panel & Lumber Cutting Plans avatar

Cut List Optimizer: Sheet, Panel & Lumber Cutting Plans

Pricing

Pay per event

Go to Apify Store
Cut List Optimizer: Sheet, Panel & Lumber Cutting Plans

Cut List Optimizer: Sheet, Panel & Lumber Cutting Plans

Optimize cutting plans for plywood, MDF, melamine, glass and sheet metal, and for lumber, bars and pipes. Kerf, grain, edge banding, offcuts and costs; panel-saw, strip or CNC layouts. Diagrams, workshop PDF, Excel, CSV and DXF. Text, JSON or CSV input. For AI agents.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Jumble Mog

Jumble Mog

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

8 days ago

Last modified

Security

Limited permissions

Share

Get the cutting plan that wastes the least material, with every saw cut in order. List the parts you need and the sheets or lengths you have, as short text lines like Side: 720 x 560, qty 2, grain, JSON, CSV or a Google Sheet, and it works out where every part goes on plywood, MDF, particleboard, melamine, glass, acrylic or sheet metal, or along lumber, bars, tubes, pipes and profiles. It handles kerf, edge trim, grain direction, edge banding, several stock sizes with prices and limited quantities, offcuts you already have and different materials. Every plan comes back with each part's position, the saw cuts in order, the offcuts worth keeping, the material cost and yield, plus a diagram (PNG and SVG), a workshop PDF, an Excel workbook, a CSV, a DXF for CAD and CNC, and Markdown. It runs fast packing heuristics and Google's OR-Tools solvers, and says when a plan is proven to use the fewest sheets or lengths possible. Made for woodworkers, cabinet and furniture makers, kitchen and closet designers, builders, glaziers, sign makers and metal fabricators, for developers of cut-to-size shops and quoting tools, and for AI agents that need a real cutting plan from one API call.

A cutting plan made by this Actor for a kitchen base cabinet: two birch plywood sheets and one hardboard sheet drawn to scale, each part a colored rectangle with its name and size, grain shown as fine lines, the offcuts worth keeping in dashed green, and a summary saying 10 of 10 parts were cut, 41% of the stock goes into parts, 54% into offcuts worth keeping and 5% is waste, for $118, the fewest pieces of stock possible

What it does

  • Sheet goods: parts placed on sheets in two dimensions, with the fewest sheets (or the lowest cost) it can find, and offcuts kept large and in one piece where it can.
  • Lengths: pieces cut from lumber, bars, tubes, pipes, extrusions or rebar, solved as a cutting stock problem. Plans for lengths are usually proven the best possible.
  • Three ways to cut: panel saw, table saw or track saw layouts where every cut runs straight across the piece being cut (guillotine cuts), listed in order with where to set the fence; strip layouts, the simplest to cut; and free layouts for a CNC router, laser or waterjet that place parts anywhere.
  • The details that make a plan usable: the saw kerf, trimming chipped factory edges, grain that must run along a part's length, parts that may turn, and edge banding totals.
  • Your stock as it is: several sheet or length sizes with prices, limited quantities ("3 sheets left"), and offcuts from earlier jobs, which the least-waste and lowest-cost goals use before new stock. Parts go on stock of their own material ("material: MDF", or a name like "Back panel, hardboard"), and each material is planned on its own.
  • Choose the goal: least waste (the default), lowest cost when stock has prices, or fewest sheets or lengths.
  • Honest numbers: how much of the stock goes into parts, into offcuts worth keeping and into waste, the material cost, the number and length of saw cuts, and a lower bound. When the plan meets the bound, the result says no plan can use less.
  • Files for the workshop and the office: a diagram of every layout (PNG and SVG), a PDF with a summary page, one page per sheet layout with its parts and saw cuts, and the lengths, an Excel workbook (summary, parts, stock, layouts, saw cuts, offcuts, lengths), a CSV of every part's position, a DXF (layers for sheets, parts, offcuts, cuts and labels) for CAD and CNC software, and Markdown for a chat reply or an email.
  • Reads what you have: text lines in millimeters, centimeters, meters, inches with fractions (23 5/8", 23-5/8, 23⅝) or feet and inches (8' 4"), JSON objects with many spellings of each field, CSV or TSV, Excel files, or a Google Sheet link.
  • Many cut lists in one run: one per cabinet, room or customer order, up to 50, each with its own parts, stock and settings.

Who it's for

  • Woodworkers, cabinet and furniture makers, DIYers: plywood, MDF and melamine cut lists for cabinets, wardrobes, shelves, desks and built-ins, with grain and edge banding.
  • Kitchen, closet and furniture designers: sheet counts and material cost for quotes, and cut lists to send to the workshop or a panel-cutting service.
  • Builders and deck or frame builders: lumber cut lists (2x4, 2x6) that buy the right mix of 8, 10 and 12 ft boards.
  • Metal fabricators and welders: tubes, angle, flat bar, pipe and extrusions, with the saw kerf and the drops worth keeping.
  • Glass, acrylic and sign shops, CNC and laser users: free layouts for sheets of glass, acrylic, aluminum composite and sheet metal.
  • Developers: a cutting optimization API for cut-to-size web shops, quoting tools, ERP and no-code flows (Make, n8n, Zapier), billed per plan with no monthly plan.
  • AI agents and LLM apps: language models can't pack parts onto sheets or count cuts reliably. An agent can pass the parts and stock as plain text and get back a checked plan, its numbers and its files.

How to use it

  1. List the parts in Parts to cut, one per line, such as Side: 720 x 560, qty 2, grain. The form starts with a kitchen base cabinet, so you can click Start right away.
  2. List what you can cut from in Stock to cut from, such as Birch ply 18mm: 2440 x 1220, $52 or 2x4: 8 ft, $4.50.
  3. Set the Kerf (empty means 3 mm, or 1/8" in inches), the Cut style and anything else that differs from the defaults.
  4. Click Start. The Plans view shows the diagram and summary, Parts every part and where it went, Sheet layouts and Length layouts each layout with its cuts, Stock what was used and what it cost, and Not placed any part that couldn't be cut, with the reason.

You can also run it through the Apify API, from Make, n8n, Zapier and other integrations, or as a tool for AI agents.

Writing parts and stock

A part as text: the name (before a colon or first on the line), the size (length x width, or just a length for lumber, bars and pipes), then any of these, separated by commas or semicolons:

PartExamples
Size720 x 560, 720x560, 23 5/8 x 11 1/4, 8' 4" x 2', 72,5 x 56 cm, 1200 (a length)
Quantityqty 2, 2 pcs, x 2, (2), 2x Door 715 x 397, or a third number (720 x 560 x 2)
Graingrain (the part's length runs along the sheet's length), grain: width, no grain
Edge bandingbanding: all, banding: front, banding: L1 L2, banding: 2L 1W
Materialmaterial: MDF, or a stock name in the line (Back panel, hardboard), or a thickness (18mm)
Note# left side or note: drill for hinges

A lumber size in front of a length is the lumber's profile: 2x4 x 92 5/8, qty 10 or Joist 2x4: 92 5/8 is a 92 5/8" piece of 2x4.

A part as an object (field names are matched loosely, so Name, qty, w, edge banding or grain direction work too):

{"name": "Side", "length": 720, "width": 560, "quantity": 2, "grain": true, "banding": "front", "material": "Birch ply 18mm", "note": "left and right"}

Stock as text: the name (which is also the material parts are matched to), the size, the price and how many there are, which you leave out for as many as needed:

StockExamples
SheetsBirch ply 18mm: 2440 x 1220, $52, 10 sheets, MDF 2800 x 2070 @ 38.50, 4x8 sheet: 96 x 48, $45
Lengths2x4: 8 ft, $4.50, Steel tube 40x40x2: 6 m, 20 pcs, 12.40 each, Bar: 6000
OffcutsOffcut: 900 x 600 (one of each unless you give a count), Remnant 1200 x 800, trim 0
Price$52, €41,50, £85 per sheet, cost 30 EUR, 12.40 each

Stock as an object: {"name": "Birch ply 18mm", "length": 2440, "width": 1220, "quantity": 10, "price": 52}, with offcut, material, thickness and trim as options.

As a table: paste CSV or TSV into Parts as CSV or Stock as CSV with a header row such as name,length,width,quantity,material,grain,banding (or name,length,width,quantity,price for stock), or give a link to a CSV, Excel or JSON file or a Google Sheet. Without a header the columns are name, length, width and quantity.

Units: sizes take the unit written with them. Bare numbers take the most common written unit, or are guessed from the stock: 96 x 48 is inches, 244 x 122 centimeters and 2440 x 1220 millimeters, and the notes say what was assumed. Set Units to be sure.

Examples

A kitchen base cabinet in millimeters (the form's example):

{
"title": "Kitchen base cabinet",
"parts": [
"Side: 720 x 560, qty 2, grain",
"Top and bottom: 764 x 560, qty 2",
"Shelf: 762 x 520, qty 2, banding: front",
"Back: 796 x 716, material: hardboard",
"Door: 715 x 397, qty 2, grain, banding: all",
"Drawer front: 796 x 140, banding: all"
],
"stock": ["Birch ply 18mm: 2440 x 1220, $52", "Hardboard 3mm: 2440 x 1220, $14"]
}

Cut 10 of 10 parts from 2 sheets of Birch ply 18mm (2440 × 1220 mm) and 1 sheet of Hardboard 3mm (2440 × 1220 mm). 41% of the stock goes into parts, 54% into 7 offcuts worth keeping and 5% is waste. The stock costs $118. That's the fewest pieces of stock possible.

A deck frame in feet and inches, choosing between 8 and 10 ft boards:

{
"title": "Deck frame",
"parts": ["Joist 2x4 x 92 5/8, qty 10", "Blocking 2x4: 22 1/2 x 6", "Post 2x6: 48, qty 4"],
"stock": ["2x4: 8ft, $4.50", "2x4: 10 ft, $6.20", "2x6: 8', $7.80"]
}

Cut 20 of 20 parts from 4 lengths of 2x4 (96"), 6 lengths of 2x4 (120") and 4 lengths of 2x6 (96"). 84% of the stock goes into parts, 13% into 4 offcuts worth keeping and 3% is waste. The stock costs $86.40. No plan uses less material.

Steel tube frames from a CSV, with a 2 mm saw kerf:

{
"title": "Steel frames",
"partsCsv": "name,length,quantity\nTop rail,1450,4\nLeg,880,8\nBrace,620,8\nCross bar,1150,6",
"stock": ["Square tube 40x40x2: 6 m, 12.50 each"],
"kerf": "2 mm"
}

Cut 26 of 26 parts from 5 lengths of Square tube 40x40x2 (6000 mm). 82% of the stock goes into parts, 16% into 2 offcuts worth keeping and 2% is waste. The stock costs $62.50. That's the fewest pieces of stock possible.

Acrylic signs on a laser cutter (a free layout with a 0.2 mm kerf):

{
"title": "Acrylic signs",
"parts": ["Sign: 600 x 400, qty 3", "Small sign 300 x 200 x 8", "Letter plate 150 x 150, qty 12"],
"stock": ["Acrylic 3mm: 1220 x 610, $38"],
"cutStyle": "nested",
"kerf": 0.2
}

A wardrobe as objects, choosing the cheaper of two sheet sizes, with 10 mm trimmed off every sheet edge:

{
"title": "Wardrobe",
"parts": [
{"name": "Side", "length": 2000, "width": 580, "quantity": 2, "grain": true, "banding": "front"},
{"name": "Shelf", "length": 964, "width": 560, "quantity": 5, "banding": "front"},
{"name": "Top", "length": 1000, "width": 580, "quantity": 2, "banding": "L1"},
{"name": "Door", "length": 1990, "width": 497, "quantity": 2, "grain": true, "banding": "all"}
],
"stock": [
{"name": "White melamine 18mm", "length": 2800, "width": 2070, "price": 61},
{"name": "White melamine 18mm", "length": 2440, "width": 1220, "price": 34}
],
"goal": "lowest-cost",
"edgeTrim": "10 mm"
}

Several cut lists in one run: settings given at the top apply to every job unless a job sets its own, and a job with its own parts or stock doesn't take the shared ones.

{
"stock": ["Birch ply 18mm: 2440 x 1220, $52"],
"kerf": "3 mm",
"jobs": [
{"title": "Bookcase", "parts": ["Side: 1800 x 300, qty 2, grain", "Shelf: 764 x 280, qty 5"]},
{"title": "Desk", "parts": ["Top: 1400 x 700", "Leg panel: 720 x 650, qty 2", "Modesty panel: 1300 x 400"]}
]
}

How-to examples

These are examples from Examples above; the result lines are what their runs say in summary.

How to make a plywood cutting plan for a cabinet

{"title": "Kitchen base cabinet",
"parts": ["Side: 720 x 560, qty 2, grain", "Top and bottom: 764 x 560, qty 2", "Shelf: 762 x 520, qty 2, banding: front",
"Back: 796 x 716, material: hardboard", "Door: 715 x 397, qty 2, grain, banding: all", "Drawer front: 796 x 140, banding: all"],
"stock": ["Birch ply 18mm: 2440 x 1220, $52", "Hardboard 3mm: 2440 x 1220, $14"]}

Result: "Cut 10 of 10 parts from 2 sheets of Birch ply 18mm (2440 × 1220 mm) and 1 sheet of Hardboard 3mm (2440 × 1220 mm). 41% of the stock goes into parts, 54% into 7 offcuts worth keeping and 5% is waste. The stock costs $118. That's the fewest pieces of stock possible." Every saw cut is listed in order, with where to set the fence.

How to work out how many boards to buy for a deck

{"title": "Deck frame",
"parts": ["Joist 2x4 x 92 5/8, qty 10", "Blocking 2x4: 22 1/2 x 6", "Post 2x6: 48, qty 4"],
"stock": ["2x4: 8ft, $4.50", "2x4: 10 ft, $6.20", "2x6: 8', $7.80"]}

Result: "Cut 20 of 20 parts from 4 lengths of 2x4 (96"), 6 lengths of 2x4 (120") and 4 lengths of 2x6 (96"). 84% of the stock goes into parts, 13% into 4 offcuts worth keeping and 3% is waste. The stock costs $86.40. No plan uses less material." Inches with fractions and feet both work.

How to cut steel tube or pipe lengths with the least waste

{"title": "Steel frames", "partsCsv": "name,length,quantity\nTop rail,1450,4\nLeg,880,8\nBrace,620,8\nCross bar,1150,6",
"stock": ["Square tube 40x40x2: 6 m, 12.50 each"], "kerf": "2 mm"}

Result: "Cut 26 of 26 parts from 5 lengths of Square tube 40x40x2 (6000 mm). 82% of the stock goes into parts, 16% into 2 offcuts worth keeping and 2% is waste. The stock costs $62.50. That's the fewest pieces of stock possible."

How to let an AI agent make cut lists

Add this Actor to the Apify MCP server with https://mcp.apify.com/?tools=jumblemog/cut-list-optimizer. The agent writes the parts and stock as short lines like Side: 720 x 560, qty 2, grain and gives the user the summary, the diagram and the PDF.

FAQ

Does it work for both sheets and lengths? Yes: plywood, MDF and melamine sheets in two dimensions, and lumber, bars, tubes, pipes and rebar in one.

Does it allow for the saw blade? Yes. Set kerf to the blade's width, and trim chipped factory edges if you need to.

Can the cuts be made on a table saw? Yes. Guillotine layouts, where every cut runs straight across the piece, are the default. Strip layouts and free layouts for CNC and laser cutters are there too.

Does it keep the wood grain the right way? Yes. Parts marked grain aren't turned.

Which files do I get? A diagram of every layout (PNG and SVG), a PDF with one page per sheet, an Excel workbook, a CSV of part positions and a DXF for CAD and CNC software.

Input

FieldWhat it's for
partsThe parts: text lines or objects with name, length, width (none for lengths), quantity, grain, banding, material, note.
stockWhat to cut from: text lines or objects with name, length, width, quantity (none for as many as needed), price, offcut, material, trim.
partsCsv, stockCsvThe same as CSV or TSV text, or a link to a CSV, Excel or JSON file or a Google Sheet.
unitsauto (default), mm, cm, m, in or ft: the unit of bare numbers and of the results.
kerfThe width of each cut, such as 3 mm, 1/8" or 0 for a shear (default 3 mm or 1/8").
edgeTrimHow much to trim off every sheet edge and each end of a length first (default none).
cutStyleguillotine (default, panel or table saw), strips or nested (CNC, laser, waterjet).
allowRotationLet parts without grain turn a quarter turn (default on).
goalleast-waste (default), lowest-cost or fewest-stock.
minOffcutThe smallest leftover listed as an offcut to keep (default 150 mm or 6" across for sheets, 300 mm or 12" for lengths).
currency, titleThe currency of prices (default the one written with them, or $) and the plan's name.
timeLimitSecondsHow long to search for a better plan (default 10, up to 300).
jobsSeveral cut lists in one run.

Output

One dataset item per cut list (shortened here):

{
"job": 1,
"title": "Kitchen base cabinet",
"status": "complete",
"summary": "Cut 10 of 10 parts from 2 sheets of Birch ply 18mm (2440 × 1220 mm) and 1 sheet of Hardboard 3mm (2440 × 1220 mm). 41% of the stock goes into parts, 54% into 7 offcuts worth keeping and 5% is waste. The stock costs $118. That's the fewest pieces of stock possible.",
"unit": "mm",
"cutStyle": "guillotine",
"kerf": 3,
"partsTotal": 10,
"partsPlaced": 10,
"sheetsUsed": 3,
"materialCost": 118,
"currency": "$",
"yieldPercent": 41.5,
"wastePercent": 4.8,
"optimal": true,
"bound": "Birch ply 18mm: at least 2 sheets; Hardboard 3mm: at least 1 sheet",
"cutCount": 18,
"cutLength": {"value": 21231, "text": "21.23 m"},
"edgeBanding": {"value": 7844, "text": "7.84 m"},
"stock": [
{"name": "Birch ply 18mm", "size": "2440 × 1220 mm", "available": null, "used": 2, "priceEach": 52, "cost": 104, "offcut": false}
],
"usableOffcuts": [{"size": "1721 × 796 mm", "length": 1721, "width": 796, "count": 1}],
"layouts": [
{
"layout": "S1",
"stock": "Birch ply 18mm",
"stockSize": "2440 × 1220 mm",
"sheets": 1,
"fillPercent": 78.7,
"parts": [{"label": 2, "name": "Top and bottom", "size": "764 × 560 mm", "x": 0, "y": 0, "length": 560, "width": 764, "turned": true}],
"offcuts": [{"size": "591 × 358 mm", "x": 1849, "y": 765, "length": 591, "width": 358, "usable": true}],
"cuts": [
{"number": 1, "direction": "rip", "at": 1164, "atText": "1164 mm from the top", "piece": "2440 × 1220 mm"},
{"number": 2, "direction": "cross-cut", "at": 1123, "atText": "1123 mm from the left", "piece": "2440 × 1164 mm"}
],
"cutCount": 10
}
],
"bars": [],
"unplaced": [],
"parts": [{"label": 1, "name": "Side", "size": "720 × 560 mm", "quantity": 2, "placed": 2, "grain": true, "layouts": ["S1"]}],
"cutList": "# Kitchen base cabinet\n\nCut 10 of 10 parts ...\n\n## Stock\n\n| Stock | Size | Used | Available | Cost |\n...",
"imageUrl": "https://api.apify.com/v2/key-value-stores/.../records/plan-001-Kitchen-base-cabinet.png",
"pdfUrl": "https://api.apify.com/v2/key-value-stores/.../records/plan-001-Kitchen-base-cabinet.pdf",
"xlsxUrl": "https://api.apify.com/v2/key-value-stores/.../records/plan-001-Kitchen-base-cabinet.xlsx",
"csvUrl": "https://api.apify.com/v2/key-value-stores/.../records/plan-001-Kitchen-base-cabinet.csv",
"dxfUrl": "https://api.apify.com/v2/key-value-stores/.../records/plan-001-Kitchen-base-cabinet.dxf",
"svgUrl": "https://api.apify.com/v2/key-value-stores/.../records/plan-001-Kitchen-base-cabinet.svg",
"markdownUrl": "https://api.apify.com/v2/key-value-stores/.../records/plan-001-Kitchen-base-cabinet.md",
"jsonUrl": "https://api.apify.com/v2/key-value-stores/.../records/plan-001-Kitchen-base-cabinet.json",
"warnings": [],
"notes": []
}

Positions are measured from the sheet's left end (x, along its length) and top edge (y, across it). Each saw cut says where to set the fence on the piece being cut: a rip runs along the sheet's length and a cross-cut across it, and cuts are listed in the order they can be made. Lengths come back in bars, each with its pieces in order ("piecesText": "#1 92 5/8\", #2 22 1/2\""), the offcut and whether it's worth keeping. A cut list with parts that couldn't be placed is incomplete, and unplaced says why, such as "Bigger than any stock it can be cut from: the largest is 2440 × 1220 mm after trim." or "Not enough stock: every Ply sheet there is was used."

cutList is the whole plan as Markdown, ready for a chat reply, an email or a wiki. The run's OUTPUT record holds every plan as one JSON object, so the run-sync API endpoint answers with them directly.

How it works

Sizes are turned into exact whole numbers (micrometers, or 1/64,000 inch), rounding parts up and stock down, with the kerf added to every part and to the usable stock, so plans are exact and parts always come out at least as large as asked.

Sheets are packed by a portfolio of fast heuristics (guillotine, maximal-rectangles and strip packing with different part orders and placement rules), then improved by repeatedly taking the emptiest sheet and a few others and packing their parts onto fewer sheets, with an exact constraint programming search (OR-Tools CP-SAT) for free layouts of up to 40 parts. Area and part-size lower bounds tell when the number of sheets can't go lower. Panel-saw and strip plans are built as a tree of straight cuts, which gives the saw cuts in order.

Lengths are solved as a cutting stock problem: column generation (OR-Tools' GLOP with a knapsack search for new patterns) finds the best mix of cutting patterns and a lower bound, CP-SAT turns it into whole bars, and an exact arc-flow model (SCIP) settles smaller cases. Plans with one stock length are usually proven optimal, and a last pass uses as few different patterns as it can at the same cost, so the saw stop is moved less often.

Several materials or stock groups are planned separately, sharing the time limit, and offcuts you list are used before new stock under the least-waste goal.

Checks

Every plan in the tests is checked by separate code from the solvers': each part inside its sheet and the edge trim, at least a kerf from every other part, at its size, never turned against its grain, and placed exactly as many times as asked (or reported as not placed); every saw cut on the sheet and clear of every part; pieces on a length in order, a kerf apart and within the length; and no more stock used than there is. The length solver is checked on Wikipedia's cutting stock example (73 rolls, proven). 102 tests pass, and the same checks hold on jobs of over 400 parts in each cut style.

Pricing

You pay per cutting plan made, at the price shown on this page, with every file included. Plans that can't be made are never charged. Solving past the first 30 seconds of a plan adds a small solver time charge per started 10 seconds, so with the default 10-second time limit it never applies. If you set a maximum cost per run, the Actor checks before each plan that it fits and shortens the time limit to stay within it.

Speed

Most cut lists (up to a few dozen parts) are finished in a second or two, often proven optimal, and a run through the API answers in about 10 to 15 seconds, including the cloud container starting and the files being saved. Hundreds of parts use more of the time limit: in tests, 430 mixed parts on 2440 × 1220 sheets reached about 95% yield in 6 seconds. Give large jobs 30 to 60 seconds to search further.

Tips and limits

  • Grain: grain keeps a part's length along the sheet's length (the way the grain runs on plywood and wood-look melamine). Write the part's length in the grain direction, or use grain: width.
  • Rotation: parts without grain may turn a quarter turn unless Allow rotation is off.
  • Kerf and trim: the kerf is taken off between parts, not at the sheet's edges; use Edge trim for chipped or uneven factory edges.
  • Materials: a part goes on stock whose name or material matches its own (material: MDF matches MDF 18mm: 2800 x 2070). Parts that name no material go on the first material listed, and the notes say so when other stock was left unused.
  • Offcuts: leftovers at least Minimum offcut across are listed as offcuts to keep; anything smaller counts as waste. List last job's offcuts as stock to use them first.
  • Three numbers: 720 x 560 x 2 is two parts, and 720 x 560 x 18 mm (a unit, or a fraction like 3/4) is the thickness. The notes and warnings say how anything unusual was read.
  • Limits: 5,000 part lines and 5,000 stock lines per job, 5,000 sheet parts in all (counting quantities) and 200,000 pieces cut from lengths, 50 jobs per run, and up to 300 seconds of solving per plan. A run stops once jobs that can't be planned have taken 3 minutes.
  • Links: CSV, TSV, JSON and Excel files, GitHub file links and Google Sheets links (shared as "Anyone with the link" or published to the web). Every site's robots.txt is checked first.

For AI agents and developers

This Actor works with the Apify MCP server, so AI agents can call it as a tool: send the parts and stock as text lines and read summary, cutList, unplaced and the file links from the result. A direct API call that waits for the answer:

curl -X POST "https://api.apify.com/v2/acts/jumblemog~cut-list-optimizer/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"parts": ["Side: 720 x 560, qty 2, grain", "Shelf: 762 x 520, qty 3"], "stock": ["Plywood 18mm: 2440 x 1220, $52"]}'

run-sync instead returns the run's OUTPUT: the status, how many plans were made and every plan as JSON.

In Python, with the apify-client package:

from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("jumblemog/cut-list-optimizer").call(run_input={
"parts": [
{"name": "Side", "length": 720, "width": 560, "quantity": 2, "grain": True},
{"name": "Shelf", "length": 762, "width": 520, "quantity": 3, "banding": "front"},
],
"stock": [{"name": "Plywood 18mm", "length": 2440, "width": 1220, "price": 52}],
"kerf": 3,
})
for plan in client.dataset(run["defaultDatasetId"]).iterate_items():
print(plan["summary"], plan["pdfUrl"])
for layout in plan["layouts"]:
for cut in layout["cuts"] or []:
print(layout["layout"], cut["number"], cut["direction"], cut["atText"])

Credits

  • Optimization: Google OR-Tools with its CP-SAT, GLOP, knapsack and SCIP solvers (Apache License 2.0).
  • Files: openpyxl (MIT) for Excel, vl-convert (BSD-3-Clause) for the PNG and PDF pages, pypdf (BSD-3-Clause) to join them, and the Inter font (SIL Open Font License), subset with fontTools (MIT).