Engine API
Se ti occupi solo di tagliare pannelli, questa pagina non ti serve. L’ottimizzatore dentro CutOptim fa già tutto quello che è descritto qui. L’Engine API è lo stesso motore senza uno schermo attaccato, per quando un altro software ha bisogno di piani di taglio senza che una persona apra l’app.
Tutto quello che CutOptim fa nel tuo browser parte da un solo calcolo: dati questi pezzi e questo materiale, qual è il modo migliore di tagliarli? L’Engine API espone esattamente quel calcolo su internet, così un programma diverso può porre la domanda e riavere la risposta — senza browser, senza clic, senza che nessuno abbia fatto l’accesso.
È tutta l’idea. Non è un nuovo ottimizzatore, non è un ottimizzatore migliore e non è un livello di abbonamento superiore. È lo stesso motore, raggiungibile da un software invece che da una persona.
Fa per me?
Per la grandissima maggioranza degli utenti di CutOptim, la risposta onesta è no. Se la tua giornata di lavoro consiste nell’aprire CutOptim, inserire pezzi e materiale e stampare o esportare il piano, l’app è il prodotto e questa pagina non ti riguarda.
L’Engine API serve a una sola situazione: i piani di taglio devono comparire dentro un software che già usi, senza che nessuno visiti CutOptim. In pratica si tratta di uno di questi due casi:
- Usi già un software dentro cui il piano di taglio dovrebbe stare. Un ERP che tiene i tuoi ordini, uno strumento di preventivazione che calcola il prezzo dei lavori, o il software della macchina stessa. Invece di far ribattere a un operatore la stessa distinta di pezzi in CutOptim, quel programma interroga direttamente il motore e mostra il piano dove il lavoro avviene già.
- Ti stai facendo sviluppare un software. Da uno sviluppatore interno, da una software house locale o dal fornitore della tua macchina. L’Engine API è ciò a cui si collegano.
Usare l’Engine API significa che qualcuno scrive del software che la richiama. Non c’è nessuna interfaccia, nessun foglio di calcolo da compilare e niente da installare — è un servizio per programmi, e il lavoro lo fa chi scrive quel programma. Se dalla tua parte nessuno scrive codice, l’app è quello che ti serve.
Se non sei sicuro da quale lato di quella linea ti trovi, una buona prova: il piano potrebbe comparire senza che nessuno lo chieda? Se sì, l’API è pertinente. Se è sempre una persona a decidere di fare un piano di taglio, l’app è già lo strumento giusto.
Cosa fa
Il tuo software invia le stesse due cose che inseriresti nell’app — un elenco di pezzi e un elenco di materiale — in JSON. Il motore restituisce una risposta completa:
- Lo schema completo. Ogni pezzo, posizionato su un pannello o su una barra precisi, compresa l’indicazione se è stato ruotato.
- Un piano di taglio. Non solo un disegno di rettangoli: la vera sequenza di taglio guillotine, in ordine, così che il piano possa essere eseguito su una sezionatrice.
- I numeri. Quanti pannelli o barre richiede il lavoro, la percentuale di resa, quanti tagli servono e il prezzo totale del materiale usato. Per i pannelli ottieni anche i due conteggi onesti dei tagli — le linee di taglio, che uniscono i tagli che condividono un’unica regolazione della guida, e i passaggi della lama, che contano ogni singolo passaggio — più la lunghezza totale tagliata.
- Opzionalmente, il disegno. Chiedi
include: ["svg","csv","dxf"]e la risposta trasporta anche lo schema come file già pronto — un disegno SVG 2D autonomo, un DXF R12/AC1009 o una distinta di taglio CSV — inline nel JSON, senza archiviazione e senza una seconda chiamata. (L’SVG è solo 2D.) Nelle richieste 2D puoi chiedere anchelabels(dati di etichetta per pezzo),planHash(un’impronta del piano),pdf(il PDF del piano di taglio) elabelsPdf(il PDF delle etichette): i PDF in base64, disegnati con lo stesso codice dell’app. - I tuoi identificativi, restituiti. Allega un oggetto
meta— un codice articolo, una riga d’ordine, un riferimento cliente — a qualsiasi pezzo o riga di materiale, e torna invariato su ogni pezzo posizionato e su ogni pannello o barra, così il piano si allinea con il tuo sistema. È questo il campo da usare quando vuoi inviare tutti i tuoi pannelli, contrassegnare ciascuno con un tuo codice e rileggere quale pannello ha scelto l’ottimizzatore: metti il codice instock[].metae ti torna susheets[].meta. Non influisce mai sul posizionamento. Non usare invece il campomaterialper identificare:materialè una partizione rigida (un pezzo viene tagliato solo da righe di materiale con lo stesso valorematerial), quindi assegnare unmateriala ogni riga di materiale lasciando i pezzi senza tag fa tornare ogni pezzo comeunmatched, con un risultato vuoto.
Le modalità di ottimizzazione sono quattro, tutte corrispondenti all’app — una per i pannelli 2D, una per il materiale 1D lineare come barre, profili e tubi, una per il legno, dove il materiale ha una sezione, e il nesting a forma reale (POST /v1/optimize/nest), che annida poligoni arbitrari per il taglio laser, plasma e a getto d’acqua (la modalità Nesting dell’app). Ogni endpoint di ottimizzazione ha anche un endpoint di validazione gratuito che verifica una richiesta senza risolverla (vedi sotto).
Endpoint
La base URL è https://api.cutoptim.com. Gli endpoint di ottimizzazione e usage portano una chiave in un header Authorization: Bearer <key>; gli endpoint di validazione e health non richiedono alcuna chiave.
| Endpoint | Cosa fa |
|---|---|
POST /v1/optimize/2d |
ottimizzazione 2D per pannelli |
POST /v1/optimize/1d |
ottimizzazione 1D / lineare — barre, profili, tubi |
POST /v1/optimize/wood |
Ottimizzazione del legno — 1D con abbinamento della sezione |
POST /v1/optimize/nest |
Nesting a forma reale — poligoni irregolari per laser, plasma e getto d’acqua |
POST /v1/validate/2d · /1d · /wood · /nest |
Valida una richiesta senza risolverla — gratis, nessuna chiave, nessuna quota |
GET /v1/jobs/{id} |
Interroga un lavoro asincrono del motore max — solo i tuoi lavori, nessuna quota |
POST /v1/import/nest |
Legge i contorni dei pezzi da un file SVG o DXF — richiede una chiave, non consuma quota |
GET /v1/usage |
consumo e quota dell’ACCOUNT nel mese corrente (tutte le chiavi ne condividono una) |
GET /v1/health |
controllo di liveness — non richiede nessuna chiave |
La maggior parte delle chiamate riceve direttamente il risultato finito. L’unica eccezione è il motore asincrono max (vedi Tre motori più sotto): un invio max restituisce un id di lavoro e interroghi GET /v1/jobs/{id} finché il piano non è pronto.
Gli endpoint di validazione prendono lo stesso corpo dell’endpoint di ottimizzazione corrispondente e lo verificano senza eseguire la risoluzione: una richiesta malformata torna come 400 che indica il campo esatto sbagliato, mentre una ben formata restituisce valid: true più avvisi di fattibilità (per esempio un pezzo che non entra in alcun materiale). Non costano nulla e non richiedono alcuna chiave, così puoi validare i tuoi payload mentre costruisci l’integrazione — ancora prima di avere una chiave — e confermare che una richiesta non verrà rifiutata senza spendere una delle tue chiamate mensili.
Direzione della venatura sui pannelli
Il compensato e i pannelli impiallacciati hanno una venatura, e un pezzo in vista deve essere tagliato con la venatura nel verso giusto. Su POST /v1/optimize/2d, invia grain su una riga di materiale — "w" o "h", il lato del pannello lungo il quale corre la venatura — e grain su un pezzo, il lato del pezzo che deve correre lungo di essa. Ogni pezzo così impostato viene posizionato con la venatura lungo quella del suo pannello: ruotato di 90° quando è quello che serve (rotated: true sul posizionamento, come per qualsiasi rotazione), e rotatable viene ignorato per esso. Un pezzo senza grain ruota comunque liberamente, anche su una riga di materiale senza grain (MDF, melaminico); un pezzo CON grain mantiene anche su una riga così l’orientamento che gli danno le righe venate — con material si tengono separati pannelli venati e lisci. Un pezzo che entrerebbe solo ruotato di 90° contro la venatura compare in unplaced nella misura inviata, una riga di warnings lo nomina e POST /v1/validate/2d lo segnala prima che si consumi una chiamata.
Nella stessa richiesta possono stare righe di materiale con la venatura in direzioni diverse — un 2440 × 1220 con "w" e un 1220 × 2440 con "h" — e ogni pannello torna nel verso della propria riga, con grain ripetuto in sheets[]. Con material, un pezzo è vincolato a una venatura solo se il suo materiale ha un pannello con venatura. Il grain di un pezzo, se nella richiesta non c’è materiale con venatura, non ha effetto, e una riga in warnings lo segnala. options.trim e un options.firstCut forzato valgono per ogni pannello nell’orientamento della propria riga, anche su una riga la cui venatura corre nell’altro verso. La modalità Direzione venatura dell’app CutOptim esegue lo stesso codice. (dal 2026-10-02)
Corrispondenza venatura sui pannelli (set abbinati)
La direzione della venatura tiene ogni pezzo con la venatura nel verso giusto. Alcuni frontali chiedono di più: un frontale di cassetto sopra due ante il cui disegno prosegue dall’uno all’altro, come se i tre fossero ancora un’unica tavola. Su POST /v1/optimize/2d, dai un id a quelle righe di pezzi e nominale in matchedSets:
{
"parts": [
{ "id": "DF", "name": "Drawer front", "w": 48.125, "h": 6 },
{ "id": "DOOR", "name": "Door", "w": 24, "h": 30, "qty": 2 },
{ "name": "Shelf", "w": 22.5, "h": 11.25, "qty": 4 }
],
"stock": [{ "w": 96, "h": 48, "qty": 2, "grain": "w" }],
"options": { "kerf": 0.125 },
"matchedSets": [
{ "id": "base-1", "name": "Base cabinet fronts", "grain": "w",
"layout": { "dir": "rows", "lines": [["DF"], ["DOOR", "DOOR"]] } }
]
}
- Che cos’è un set.
layout.lineselenca i membri perparts[].id. Condir: "rows"ogni linea è una riga di membri affiancati e le righe si impilano dall’alto in basso, quindi[["DF"], ["DOOR", "DOOR"]]è un frontale di cassetto sopra due ante; con"cols"ogni linea è una colonna e le colonne stanno affiancate. Un pezzo può comparire più volte in uno stesso set (Anta, Anta), ma può appartenere a un solo set.qty(predefinito 1) è il numero di istanze che ti servono — tre mobili identici sonoqty: 3— e ilqtydei pezzi stessi deve coprire ogni istanza. Un set ha almeno 2 e al massimo 24 membri, e una richiesta accetta al massimo 50 set. - Come viene tagliato. Il set attraversa l’ottimizzatore come un unico rettangolo — il blocco — e torna come i suoi membri, esattamente a un kerf di distanza, ricavati da un unico pezzo di pannello. Il
graindel set ("w"o"h", lungo la larghezza o l’altezza del blocco) decide la direzione di ogni membro; ilgraindi un singolo membro non viene usato all’interno del set, e un avviso nomina ogni membro che sovrascrive. Senzagraindel set, il blocco può ruotare quando ogni membro èrotatable.installGapè la fuga tra i membri sul mobile (predefinita: il kerf); sul pannello restano comunque a un kerf di distanza. - Cosa torna. Ogni membro posizionato porta
matchedSet: l’iddel set, qualeinstancee la suapositionin ordine di lettura sul fronte del mobile — dall’alto in basso, da sinistra a destra, a partire da 1 — più unhintcome"left"o"right"dove non è ambiguo. La risposta aggiunge un riepilogomatchedSets, una voce per set: la sualetter(A, B … nell’ordine della richiesta), quante istanze sono state tagliate come un unico blocco (asBlock), divise o lasciate non posizionate, la dimensione del blocco e iwarningsdel set. Quando un blocco non entra in nessun pannello,onMiss: "split"(il predefinito) posiziona i membri uno a uno con un avviso, eonMiss: "unplaced"li elenca inunplaced. - Avvisi, non errori. Una misura che non combacia è un avviso sul set, non un rifiuto. Ogni riga inizia con il suo codice —
align:(le linee non sono a filo),gap:(il kerf è più largo diinstallGap),grain:,split:,unplaced:,unmatched:(nessuno stock del materiale del set),priority:egrainGroup:— ealignegapsono valutati a 1/64 della tua unità o a un quarto di kerf, il minore dei due. Un set che non si può disporre affatto — un id di membro che nessun pezzo porta, un id referenziato su due pezzi, meno di due membri, troppo pochi pezzi perqty— è un400che nomina il campo esatto, prima che una chiamata venga addebitata. parts[].idsi può inviare senza rischi. Viene controllato solo un id a cui un set fa riferimento (una stringa stampabile non vuota di al massimo 64 caratteri, oppure un intero, su esattamente un pezzo). Ogni altro id viene ignorato, qualunque cosa contenga, quindi i codici articolo del tuo ERP possono restare sulle righe. E nulla cambia per una richiesta senza set: solo un arraymatchedSetsnon vuoto attiva la funzione — assente,null,[]o un valore che non è un array riceve esattamente la risposta di prima.- Export. Con i set,
csvguadagna le colonneSetePositionin fondo,svgstampa il codice di posizione (A1, A2 …) nelle etichette dei pezzi e disegna la cornice di ogni set in un gruppomatched-setsseparato —options.setOutlines: falselascia fuori quel gruppo — edxfporta il codice di posizione sul layer LABELS.pdfelabelsPdfnon contrassegnano i set: disegnano i membri come pezzi ordinari, ewarningslo dice; i segni dei set sono insheets[].parts[].matchedSet,csvesvg. - Motori ed endpoint. I motori
heuristicebalanceddispongono i set (balancednon ordina perpriority, quindi conrespectStockun set può perdere lì il suo posto, con un avvisopriority:). Il motoremaxrifiuta unmatchedSetsnon vuoto con un400il cuidetails.unsupportedlo nomina, prima che una chiamata venga addebitata; uno vuoto è un normale lavoromax.matchedSetseparts[].idvalgono solo per il 2D: gli endpoint 1D, wood e nest li ignorano. grainGroupè deprecato. È ancora accettato e funziona esattamente come prima: i pezzi che condividono un gruppo restano su un unico pannello. Non li ha mai posizionati uno accanto all’altro, quindi non dà una venatura continua tra di loro — per quello usamatchedSets.
La Corrispondenza venatura dell’app CutOptim dispone i set con lo stesso nucleo.
Perché il legno ha un endpoint dedicato
Il materiale lineare conosce una sola dimensione, la lunghezza, quindi qualsiasi barra può servire qualsiasi pezzo. Con il legno non funziona così: un pezzo 50×150 non può uscire da una barra 50×100, per quanta lunghezza avanzi. L’endpoint del legno prende perciò entrambi i lati della sezione su ogni pezzo e ogni riga di materiale, divide il lavoro per sezione, abbina a ciascuna sezione il proprio materiale e restituisce le sezioni separatamente — ognuna con le proprie barre e i propri totali, accanto ai numeri dell’intero lavoro.
Due dettagli da conoscere prima di integrarlo:
-
I due lati della sezione si possono inviare in qualsiasi ordine. 50×100 e 100×50 sono la stessa trave girata e vengono trattate come un’unica sezione. Così una differenza nel modo in cui i tuoi dati sono stati inseriti non può far sparire del materiale.
-
«Nessun materiale di questa sezione» e «non è entrato» sono segnalati separatamente. Il primo è un problema di materiale mancante, il secondo di capacità, e si risolvono in modi diversi — mescolarli in un unico elenco manderebbe il tuo utente a cercare nel posto sbagliato.
Potresti approssimare tutto questo con più chiamate 1d tue, raggruppando i pezzi da solo. Ti costerebbe una richiesta di quota per sezione invece di una per il lavoro, sposterebbe l’abbinamento del materiale nel tuo codice e produrrebbe un totale che dovresti comporre tu — e che non coinciderebbe necessariamente con quanto l’app CutOptim mostra per lo stesso lavoro.
Pezzi da un file CAD
L’endpoint di nesting non accetta solo coordinate. Un pezzo può portare invece un source — un documento SVG o DXF — e il server ne estrae il contorno, e gli eventuali fori, dal file. È lo stesso lettore che l’app usa quando trascini un disegno sulla sua modalità Nesting, quindi una libreria di pezzi che esiste già come file CAD non va prima riscritta in elenchi di coordinate.
Il file sostituisce solo la geometria. Quantità, materiale, rotazioni ammesse e i tuoi metadati restano campi ordinari della riga del pezzo, esattamente come quando invii coordinate. Un file descrive un pezzo; quando un singolo disegno contiene più componenti separati, POST /v1/import/nest lo divide prima in righe pronte — e quella chiamata richiede una chiave ma non consuma una richiesta della tua quota mensile.
Nulla viene memorizzato. Il file esiste solo come la richiesta stessa: viene letto in memoria e sparisce nel momento in cui la risposta è scritta. Non resta copia su disco o in un database, nulla finisce in un log e non c’è nulla da cancellare dopo. Con le unità facciamo lo stesso — un DXF può dichiarare millimetri o pollici e noi riportiamo ciò che ha detto, ma le coordinate non vengono mai convertite, perché nessun valore di questa API porta un’unità.
Sempre la stessa risposta
Il motore è deterministico: lo stesso input produce sempre lo stesso output. Non c’è casualità e non c’è nessun orologio dentro l’algoritmo.
Suona accademico, ma è la ragione pratica per costruirci sopra. Significa che i risultati possono essere messi in cache — se hai già chiesto di questo lavoro esatto, puoi riutilizzare la risposta in sicurezza invece di richiederla di nuovo. Significa anche che l’integrazione può essere testata: un piano può essere confrontato con un risultato noto come corretto, e una differenza è una differenza reale, non rumore. Un software che lunedì preventiva un prezzo a un cliente, venerdì preventiverà lo stesso prezzo.
C’è un’unica eccezione opt-in, e lo dichiara: il motore max per il nesting (sotto) impiega un budget di tempo fisso per cercare, quindi quanto arriva lontano dipende da quanto lavoro entra in quel tempo. Le sue risposte portano deterministic: false. Ogni altro motore — incluso il predefinito del nesting, lbf — è deterministico.
Riprovare in sicurezza. Se la connessione cade, non si sa se la richiesta è arrivata. Inviate un’intestazione Idempotency-Key — un valore che scegliete per ogni lavoro — e riprovate con la stessa chiave: entro 24 ore la stessa richiesta restituisce la risposta salvata, segnata con Idempotency-Replayed: true, e non viene addebitata una seconda volta. Anche un lavoro max non viene accodato due volte. La chiave demo pubblica ignora questa intestazione. (Dal 2026-10-15.)
Webhook per i job asincroni. Invece di interrogare GET /v1/jobs/{id}, registrate un endpoint (un URL https://) nella dashboard e ricevete un POST firmato — job.succeeded o job.failed — quando un job max asincrono termina. Verificate l’intestazione CutOptim-Signature con il segreto ricevuto, rispondete entro 10 secondi e leggete il piano con GET /v1/jobs/{id}. Una consegna non riuscita viene ritentata: 8 tentativi in 24 ore. (Dal 2026-10-19.)
SDK ufficiali. Client open source per TypeScript, Python e PHP — npm install @cutoptim/engine, pip install cutoptim, composer require cutoptim/engine — con richieste tipizzate, tentativi che non vengono mai addebitati due volte (ogni chiamata porta un Idempotency-Key), un aiuto per attendere i job asincroni e la verifica dei webhook. Codice su GitHub; dettagli nella guida agli SDK (in inglese).
Server MCP per assistenti IA. Claude Code, Cursor, VS Code e Claude Desktop possono chiamare il motore come strumenti tramite il server Model Context Protocol ospitato su https://api.cutoptim.com/mcp, con la stessa chiave API (Authorization: Bearer …) e la stessa quota: una chiamata a uno strumento è una chiamata API, e gli strumenti validate_* sono gratuiti. Gira anche in locale con il pacchetto npx -y @cutoptim/mcp (chiave in CUTOPTIM_API_KEY), e il MCP Registry ufficiale lo elenca come io.github.cutoptim/engine. Le configurazioni dei client sono nella guida MCP (in inglese).
Tre motori
L’API offre la scelta del motore. I primi due funzionano in modo sincrono; il terzo è asincrono. La differenza non è la qualità — è un compromesso tra velocità, realizzabilità del risultato su una sezionatrice e quanto ci si avvicina al minimo teorico.
heuristicè il predefinito ed è lo stesso che usa l’app. Produce schemi guillotine: resa massima, ogni schema tagliabile su una sezionatrice, e sempre un piano di taglio completo. Sincrono.balancedsi attiva su richiesta. Usa invece il nesting libero, che è enormemente più rapido sui lavori molto grandi — misurato circa 25× più rapido su un lavoro da 2.000 pezzi — al costo di una resa leggermente inferiore. L’insidia importante: i suoi schemi spesso non sono tagliabili da bordo a bordo, quindi per quelli non restituisce alcun piano di taglio. Sincrono.maxsi attiva su richiesta, per i pannelli 2D (e, separatamente, per il nesting a forma reale — vedi sotto). Sul 2D è una ricerca ad albero lato server che raggiunge l’ottimo dimostrato su molti più lavori rispetto al predefinito, e i suoi schemi restano tagliabili a guillotine. Il costo è il tempo: una risoluzionemaxrichiede da secondi a un minuto, quindi non risponde nella risposta. Invece,POST /v1/optimize/2dconengine: "max"restituisce un id di lavoro, e interroghiGET /v1/jobs/{id}finché non è pronto. Rimane deterministico. Ricorri a esso quando un lavoro grande e di valore vale l’attesa per gli ultimi pannelli. Modella un solo formato di stock a piena dimensione con disponibilità illimitata, quindi una richiesta che porta anche un secondo formato di stock,trimper lato, stock limitato (respectStock), materiali, gruppi di venatura o unmatchedSetsnon vuoto viene rifiutata in anticipo con un400che indica esattamente ciò che non può fare — prima che una chiamata venga addebitata. Manda quei lavori aheuristic, che li modella tutti.
Nesting: lbf e max
Il nesting a forma reale ha due motori propri. lbf è il predefinito: istantaneo, sincrono e deterministico. max si attiva su richiesta ed è asincrono, esattamente come il max 2D — POST /v1/optimize/nest con engine: "max" restituisce un id di lavoro, e interroghi GET /v1/jobs/{id}.
Il max per il nesting esegue prima il passaggio lbf, così ha sempre una risposta valida in mano. Poi impiega un budget di tempo (options.timeBudgetMs, 60 secondi per default, tra 10 e 180) cercando uno schema con meno pannelli, riempiendo un pannello alla volta. Non restituisce mai più pannelli di lbf: quando la ricerca non trova un miglioramento, ottieni lo schema lbf e un avviso che lo segnala. Poiché la ricerca è limitata nel tempo, le sue risposte portano deterministic: false. Accetta più dimensioni di pannello per materiale e respectStock, e classifica il proprio risultato con la stessa regola di lbf (sotto): sostituisce il piano lbf solo quando è migliore — mai solo perché ha meno pannelli. Un pannello poligonale o le zone di esclusione, che la sua ricerca a strisce non può modellare, vengono serviti dal passaggio lbf all’interno del lavoro, con un avviso — mai rifiutati. Il vecchio nome sparrow è accettato come alias di max.
I pezzi rettangolari ottengono una griglia esatta (dal 2026-09-28). lbf trova le posizioni per campionamento, e questo non cade quasi mai su una griglia senza alcun gioco: tre pezzi da 500 mm affiancati su un pannello da 1500 mm con spaziatura zero entrano esattamente, mentre una ricerca per campionamento ne posiziona due. Per questo entrambi i motori provano anche due alternative e mantengono quella che si classifica meglio con la stessa regola: i pezzi limitati agli angoli retti che consentono, e i rettangoli d’ingombro dei pezzi impacchettati da un algoritmo esatto per rettangoli (rettangoli che non si sovrappongono non possono contenere pezzi sovrapposti, quindi vale per qualsiasi contorno). A parità — stessi pannelli, stessa area di pannello — vince il piano che riempie i pannelli in ordine, dal primo all’ultimo, poi quello con meno pezzi fuori dagli angoli retti. Non c’è nulla da attivare, e secondo la classifica un risultato può solo migliorare; un piano che i rettangoli portano al minor numero di pannelli consentito dall’area dei pezzi fa anche rispondere max subito, invece di cercare.
Un lavoro di qualche decina di pezzi di solito richiede circa 15 secondi di budget (timeBudgetMs: 15000); il lavoro termina all’incirca uno o due secondi dopo il budget, più l’eventuale tempo trascorso in coda. Interroga GET /v1/jobs/{id} ogni due o tre secondi — interrogare non costa quota. Nessun budget può promettere un numero preciso di pannelli.
Nesting: distanza dal bordo, dimensioni del pannello e il costo di ogni pannello
- Distanza dal bordo.
options.minSeparationè la spaziatura tra i pezzi, e da sola si applica anche al bordo del pannello.options.edgeClearanceimposta il bordo separatamente — per esempio 5 tra i pezzi e 0 o 10 al bordo. Omettilo e il bordo mantieneminSeparation, esattamente come prima. Funziona su entrambi i motori, richiede pannelli rettangolari (weh), e le zone di esclusione mantengonominSeparationcome i pezzi. Un pannello poligonale, o un valore che non lascia spazio su un pannello, viene rifiutato con un400prima che una chiamata venga addebitata. - Scegliere una dimensione di pannello. Quando un materiale ha due o più righe di materiale,
lbfle prova nel tuo ordine, ogni dimensione da sola e in ordine dalla più economica, e tiene la migliore — quindi il risultato non dipende più dall’ordine in cui elenchi le righe. La classifica è: più pezzi da tagliare assolutamente posizionati (vedi sotto), poi più pezzi posizionati, poi minore area totale dei pannelli (materiale), poi meno pannelli. Conoptions.minimizeCostclassifica invece in base al prezzo totale (price, ocostper una riga senza prezzo) — ma solo quando ogni riga di quel materiale ne porta uno; altrimenti ripiega sull’area e lo segnala inwarnings. - Mescolare le dimensioni. Dopodiché, ogni pannello — a partire dal meno riempito — viene ri-annidato da solo sulle righe più economiche o più piccole, e sostituito quando l’intero piano classifica meglio. Così le dimensioni possono essere mescolate all’interno di un materiale: tipicamente due pannelli grandi e uno più piccolo per ultimo, dove l’ultimo pannello semi-vuoto un tempo era uno grande. Con
options.respectStock, nessuna riga viene usata più spesso della suaqty. Il motoremaxapplica la stessa classifica. - Pezzi da tagliare assolutamente.
parts[].priority: truecontrassegna un pezzo da tagliare assolutamente. Conta conoptions.respectStock— un materiale limitato, dove non tutti i pezzi potrebbero entrare: i pezzi da tagliare assolutamente vengono allora posizionati per primi, così un pezzo qualsiasi non si aggiudica mai lo spazio sul pannello di cui ha bisogno un pezzo da tagliare assolutamente, e ogni classifica qui sopra mette in testa il piano che ne mantiene di più, anche se posiziona meno pezzi in totale. Entrambi i motori lo rispettano (maxmantiene lo schemalbfogni volta che qualcosa resta senza posto). SenzarespectStockogni pezzo che entra viene comunque posizionato, quindi il flag non cambia nulla. Un pezzo da tagliare assolutamente che non entra in alcun pannello resta comunque elencato inunplaced. (Dal 2026-09-22 — prima il motore di nesting accettava il campo ma lo ignorava.) - Scorta limitata su cui non entra tutto. Con
options.respectStock, quando il piano lascia ancora pezzi non posizionati, il motore riempie inoltre le lastre una alla volta con i rettangoli di ingombro dei pezzi — ognuna il più piena possibile, e un pezzo che entra in una sola misura di lastra va lì per primo (un fianco alto sull’unica lastra grande, non su una striscia di sfrido). Quel piano viene preso solo se posiziona più pezzi (prima quelli obbligatori) o usa meno materiale; un lavoro in cui entra tutto torna esattamente come prima. Rispetta le rotazioni ammesse di ogni pezzo,minSeparationededgeClearance. (Dal 2026-10-14.) - Il costo di ogni pannello. Ogni pannello porta
stock— l’indice della riga di materiale della richiesta da cui è stato tagliato — e la risposta aggiungestockUsage: una voce per ogni riga di materiale usata, con il suo numero di pannelli, il prezzo totale e la densità. L’unità è la riga di materiale, non la dimensione: due righe con le stesse dimensioni ma un prezzo o unmetadiverso sono due voci. - Lunghezza di taglio e sfondamenti. Ogni pannello porta
cutLength— la somma dei perimetri dei contorni e dei fori dei pezzi collocati, nella tua unità di misura — epierces, uno per ogni contorno chiuso;metricstotalizza entrambi. È la lunghezza geometrica del contorno: nessun taglio a linea comune, ingresso lama o micro-giunto — li aggiunge il tuo CAM. - Area usata, per l’addebito di una parte di pannello. Ogni pannello porta
usedWidtheusedHeight— il punto più lontano raggiunto da un pezzo collocato rispetto all’angolo di origine del pannello, nella tua unità di misura, sul pannello reale (conedgeClearanceè incluso il margine al bordo) — eusedArea, il loro prodotto;stockUsage[].usedArealo totalizza per riga di materiale. È ciò di cui un ERP ha bisogno per addebitare un taglio orizzontale (usedHeight× la larghezza del pannello), un taglio verticale (usedWidth× l’altezza del pannello) o il riquadro d’ingombro (usedArea) invece del pannello intero — la regola di addebito resta tua. Per rendere piccoli questi numeri, entrambi i motori compattano per default il pannello meno riempito di ogni materiale: i suoi pezzi vengono ri-annidati sullo stesso pannello con sottoinsiemi di rotazione tra quelli consentiti a ciascun pezzo — 0/180, 0/90/180/270 e un solo orientamento per ogni copia, incrociati con unallowedRotationsdiscreto, mai un angolo nuovo — e viene mantenuto lo schema con l’area usata più piccola. Conengine: "max"quel pannello viene poi riposizionato anche dalla ricerca stessa — lungo l’altezza del pannello e, se il piano ha un solo pannello, anche lungo la larghezza — e si mantiene, con la stessa regola, lo schema più compatto. Il numero di pannelli, le dimensioni, il prezzo e i pezzi posizionati non cambiano mai;options.compact: falserestituisce lo schema non compattato. Se addebiti una striscia invece del riquadro d’ingombro, impostaoptions.compactFordi conseguenza:"horizontal"mantiene lo schema con l’usedHeightpiù basso (una striscia sull’intera larghezza del pannello),"vertical"quello con l’usedWidthpiù piccolo (una striscia sull’intera altezza del pannello); il valore predefinito"box"mantiene l’usedAreapiù piccola. Le modalità a striscia provano anche ogni copia ruotata di un quarto (90° o 270°) doveallowedRotationslo consente. Quanto si riduce l’area usata dipende dai pezzi. (Dal 2026-09-22.)
balanced non significa «risultati migliori». È più rapido e rende leggermente meno, e quando il suo schema non è tagliabile a guillotine non c’è nessun piano di taglio da consegnare a chi sta alla sega. Scegli questo motore solo quando la velocità su un lavoro molto grande conta più di un piano pronto per la sega. Se hai dei dubbi, resta sul predefinito.
Limiti
Ogni richiesta ha dei limiti, così un lavoro fuori controllo fallisce in modo chiaro invece di rimanere bloccato:
| Limite | Valore |
|---|---|
| Pezzi per richiesta | 2.000 |
| Righe di materiale per richiesta | 50 |
| Dimensione del corpo della richiesta | 1 MB |
| Dimensione del corpo della richiesta — percorsi nest che possono portare un disegno | 10 MB |
| Chiavi attive per account | 10 |
Chiamate validate senza chiave per indirizzo |
120 / minuto |
| Chiavi API sconosciute per indirizzo | 30 / minuto — poi 429 per il resto del minuto |
| Attesa di uno slot di calcolo libero (percorsi sincroni) | circa 8 s — poi 429, nulla viene addebitato |
Lavori max in queued/running per account |
5 |
Budget di ricerca del max per il nesting, per lavoro |
10–180 s (default 60 s) |
Conservazione di Idempotency-Key |
24 ore |
| Endpoint webhook per account | 5 |
| Tentativi di consegna webhook | 8 in 24 ore |
Ottenere l’accesso
Parti dalla pagina Engine API. L’Engine API è fatturata separatamente dai piani dell’app e nessun passaggio di piano la attiva.
- Prova, poi abbonati — oppure scrivici. Puoi chiamare l’API prima di pagare: i pulsanti Esegui questo esempio nel riferimento API usano una chiave demo pubblica, e qualsiasi account con accesso effettuato può creare chiavi di test gratuite dalla dashboard (una propria piccola quota mensile, mai fatturata, nessun abbonamento necessario). Quando sei pronto, abbonarsi dalla pagina Engine API è la via più rapida: il piano d’ingresso, Studio, parte con una prova gratuita e l’accesso arriva da solo sul tuo account. Se preferisci descrivere prima la tua integrazione, o ti serve un volume oltre il piano standard, scrivici e indica che cosa vuoi collegare e all’incirca quanti piani di taglio al mese servono.
- L’accesso viene aggiunto al tuo account. Nient’altro del tuo account cambia.
- Crea una chiave. La card chiavi API è nella tua dashboard per ogni account con accesso effettuato: senza abbonamento crea chiavi di test, con l’accesso API anche chiavi live. Le chiavi le crei, le nomini e le elimini lì tu stesso.
- Copia subito la chiave. La chiave completa viene mostrata una sola volta, nel momento in cui la crei.
Una chiave viene mostrata soltanto una volta. CutOptim ne conserva solo un hash sha256, mai la chiave stessa — quindi non è più rileggibile in seguito, né da te né da noi. Copiala subito nella configurazione del tuo software quando la crei. Se perdi una chiave, eliminala e creane una nuova; se una chiave viene esposta, eliminala e le chiamate smettono immediatamente di funzionare.
Tratta una chiave come una password: sta nella configurazione del tuo software, non in un’email, in un foglio di calcolo o in uno screenshot.
Che cosa fa la scheda Chiavi API nella dashboard
Quattro comandi, e vale la pena essere precisi su cosa cambia ciascuno — soprattutto l’ultimo, che molti si aspettano tocchi la fatturazione. Non la tocca.
- Piano, cambio e fatturazione. Mostra il piano dell’account (Studio o Scale). Passa a Scale (o Passa a Studio) cambia il piano dopo una conferma, e la quota mensile dell’account cambia subito. Fatturazione apre le impostazioni di fatturazione, dove aggiorni la carta, vedi le fatture o disdici.
- Crea chiave. Genera una nuova chiave e la mostra una volta sola, lì. Il nome (
Integrazione ERP,staging) serve solo a distinguerle in seguito. Fino a 10 chiavi attive per account. Le chiavi di test si creano allo stesso modo e si contano a parte: hanno una propria piccola quota mensile e non vengono mai fatturate. - La barra di utilizzo. Due numeri: il totale del tuo account per il mese solare rispetto alla quota, e per ciascuna chiave quanto ha consumato. Il dato per chiave risponde a quale integrazione sta consumando il monte — non è un budget separato.
- Revoca. Blocca quella singola chiave dalla chiamata successiva. La riga resta visibile, così lo storico non va perso.
Revocare una chiave non ha nulla a che vedere con l’abbonamento. Non disdice nulla, non rimborsa nulla e non libera quota — il piano continua e il monte resta, semplicemente non possiedi più quella chiave. Revoca quando una chiave è stata esposta o un’integrazione viene dismessa. Per smettere di pagare, disdici invece l’abbonamento: l’accesso prosegue fino alla fine del periodo già pagato e dopo smettono di funzionare anche le chiavi esistenti.
Una quota per l’account, non una per chiave
Ogni chiave attiva del tuo account attinge allo stesso monte mensile. Creare una seconda chiave non crea una seconda quota — le chiavi servono a separare staging e produzione, dare a ogni integrazione la propria credenziale e revocarne una senza disturbare le altre.
GET /v1/usage riporta la posizione dell’account (used, limit, remaining) e risponde quindi alla domanda che hai davvero — quanto resta prima che le chiamate falliscano — indipendentemente dalla chiave con cui hai chiesto. Esaurito il monte, ogni chiave restituisce 402, non solo quella che l’ha speso.
Piani, prezzo e quota
L’Engine API viene fatturata separatamente dai piani dell’app, ogni mese, in EUR, con due piani:
| Piano | Cosa cambia |
|---|---|
| Studio | Il piano d’ingresso, con una prova gratuita |
| Scale | Una quota mensile di richieste più ampia, senza prova — ci si arriva passando da Studio |
Tutto il resto è uguale su entrambi: gli stessi motori, tutte e quattro le modalità, ogni opzione, le stesse risposte. Ogni richiesta conta allo stesso modo — un lavoro di nesting costa una richiesta, esattamente come uno 2D o 1D.
- Limite rigido, nessun costo extra. Quando la quota mensile è esaurita, le chiamate restituiscono
402fino al ripristino il primo giorno del mese successivo. Nessuna fattura a sorpresa. - Due email, perché il limite non ti colga di sorpresa. Inviamo un’email all’account al 90% della quota e di nuovo quando è esaurita.
- Il cambio di piano si fa con un pulsante nella scheda Chiavi API della tua dashboard (Passa a Scale / Passa a Studio); la nuova quota si applica subito. Un upgrade viene addebitato subito per il resto del periodo; un downgrade non viene rimborsato e il prezzo più basso si applica dal prossimo rinnovo. Il cambio è disponibile al termine della prova.
- Volumi maggiori del piano Scale vengono quotati individualmente — scrivici.
I prezzi e le quote attuali sono indicati sulla pagina Engine API — quella pagina li legge dalla nostra configurazione dei prezzi, quindi il dato è sempre quello corretto.
Per il dettaglio tecnico — la struttura esatta di richiesta e risposta, tutte le opzioni, tutti i codici di errore e come funziona il versionamento — vedi il riferimento API.
Componenti open source
I motori di CutOptim si basano su librerie open source, usate senza modifiche sui nostri server:
- jagua-rs — il motore di collisione geometrica dietro il nesting a forma reale (MPL-2.0).
- sparrow — la ricerca dietro il motore
maxper il nesting (MIT, KU Leuven). - PackingSolver — la ricerca ad albero dietro il motore
max2D (MIT).
Tutto ciò che le circonda — l’API, la corrispondenza tra il contratto e questi motori, i packer rettangolari e l’app stessa — è codice proprio di CutOptim.
Cosa non cambia
Vale la pena dirlo con chiarezza, perché l’Engine API si può facilmente fraintendere come un cambiamento del prodotto:
- L’ottimizzatore nell’app è invariato. Gira ancora nel tuo browser, esattamente come prima.
- Gratuito, Pro e Officina non sono toccati. Includono ancora l’ottimizzatore integrato nell’app, con gli stessi limiti di prima. Niente è stato spostato dietro l’API.
- Niente di ciò che fai nell’app consuma richieste API. La quota API mensile viene toccata solo dalle chiamate che fa il tuo software.
L’Engine API è un’aggiunta per chi integra CutOptim in altri software. Se non è il tuo caso, non è cambiato niente.