Documentazione API

Integra la gestione ordini, l’ottimizzazione del taglio 2D e la verifica DXF CNC di Handifyit nel tuo flusso di lavoro. L’ottimizzazione supporta risultati JSON ed esportazioni PDF, SVG, DXF, CSV e PTX. Le richieste API autenticate usano l’header Authorization: Bearer <token>.

Puoi anche lavorare nel browser: creare ordini, importare pezzi, confrontare risultati salvati, sceglierne uno e aggiornare gli stati. La guida seguente tratta l’API; consulta il flusso degli ordini per iniziare senza codice. Come funziona

Vai a: Pre-validatore CNC · POST /api/validate-cnc · Preset · Ottimizzazione · Importazione CSV · Importazione DXF · Swagger UI

Autenticazione — token API di lunga durata

Handifyit usa Token API di lunga durata per chiamate automatiche o lato server. Restano validi fino alla revoca esplicita. Per ottenerne uno, segui questi tre passaggi.

1

Accedi per ottenere un token di accesso

Invia le credenziali e apri la pagina Profilo.

POST /login
Content-Type: application/json

{
  "email": "[email protected]",
  "password": "yourpassword"
}

→ 200 OK
{
  "access_token":  "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
2

Crea un token API di lunga durata

Assegna al token API un nome descrittivo. Copia il token ricevuto: il valore viene mostrato una sola volta.

POST /api/tokens
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "name": "My Production App"
}

→ 201 Created
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",  ← salva questo valore!
  "name": "My Production App"
}

Puoi revocare i token API anche dal Profilo.

3

Usa il token API in ogni richiesta

Invia il token API come Bearer in tutte le chiamate a /api/*.

POST /api/optimize
Authorization: Bearer <your-api-token>
Content-Type: application/json

{ ... corpo della richiesta ... }

Corpo comune della richiesta

Tutti i sei endpoint di ottimizzazione accettano lo stesso corpo JSON. Sono obbligatori solo materials, stock_plates, parts e optimize_type; gli altri campi hanno valori predefiniti.

CampoStatoValore predefinitoDescrizione
materialsobbligatorio—Elenco dei materiali. Ogni oggetto richiede id (intero), name (stringa), identifier (codice breve) e può includere thickness in mm (predefinito 18). Pezzi e pannelli sono raggruppati per material_id.
stock_platesobbligatorio—Pannelli disponibili per il taglio. Ogni oggetto: width, height, quantity (predefinito 1), material_id.
partsobbligatorio—Pezzi da tagliare. Ogni oggetto: width, height, quantity (predefinito 1), material_id e can_rotate (predefinito true). La rotazione si decide per pezzo.
optimize_typeobbligatorio—"saw" — tagli rettilinei a ghigliottina per sezionatrici. "cnc" — disposizione annidata per fresatrici CNC, più flessibile ma più lenta.
blade_widthfacoltativo5Larghezza del taglio di lama o fresa, 1–10, nelle unità dei pezzi e pannelli. Viene sottratta tra i tagli. L’importazione di file accetta 0–10.
trim_stock_platefacoltativo10Margine rimosso da ogni bordo prima dell’ottimizzazione, 0–50, per escludere il materiale inutilizzabile.
allow_mixed_stock_sizesfacoltativotrueConsente formati diversi nello stesso materiale. Con false, tutti i pannelli del materiale devono avere la stessa misura.
pattern_directionfacoltativo"none""paralleltowidth"
performance_modefacoltativo"normal""fast" — risposta più rapida. "normal" — equilibrato (consigliato). "high" — compattazione intensiva per ridurre gli scarti, con calcolo più lungo.
random_seedfacoltativo0Seme intero del generatore casuale. Riutilizza lo stesso valore per riprodurre disposizioni identiche tra richieste.
can_rotatefacoltativo—Obsoleto. Questa impostazione globale rimane per compatibilità e impone la stessa rotazione a tutti i pezzi. Omettila per applicare i singoli valori can_rotate.

Esempio completo di richiesta

{
  "materials": [
    { "id": 1, "name": "Plywood 18mm", "identifier": "PLY18", "thickness": 18 }
  ],
  "stock_plates": [
    { "width": 2440, "height": 1220, "quantity": 5, "material_id": 1 }
  ],
  "parts": [
    { "width": 800, "height": 600, "quantity": 4, "material_id": 1, "can_rotate": true  },
    { "width": 400, "height": 300, "quantity": 8, "material_id": 1, "can_rotate": false }
  ],
  "optimize_type":           "saw",
  "blade_width":              5,
  "trim_stock_plate":         10,
  "allow_mixed_stock_sizes":  true,
  "pattern_direction":       "none",
  "performance_mode":        "normal",
  "random_seed":              0
}

Limiti del piano gratuito

Agli account gratuiti si applicano questi limiti su tutti gli endpoint di ottimizzazione (/api/optimize, /api/optimize/pdf, /api/optimize/dxf, /api/optimize/svg, /api/optimize/csv, /api/optimize/ptx e tutte le varianti from-dxf e from-csv):

  • 25 pezzi per richiesta — la somma dei valori part.quantity nell’array parts non deve superare 25. Il superamento restituisce 400.
  • 25 richieste di ottimizzazione al giorno — conteggio per account, azzerato a mezzanotte UTC. Il superamento restituisce 429.
POST/api/optimize

Esegue l’ottimizzatore e restituisce l’intera disposizione in JSON. Non crea file; usa questo endpoint per elaborare o visualizzare risultati nella tua applicazione.

Struttura della risposta

{
  "results": [
    {
      "material": { "id": 1, "name": "Plywood 18mm", "identifier": "PLY18",
                    "thickness": 18 },
      "layouts": [
        {
          "stock_width":  2420,
          "stock_height": 1200,
          "stock_index":  0,
          "cuts": [
            { "x": 0,   "y": 0,   "width": 800, "height": 600, "part_id": 0 },
            { "x": 805, "y": 0,   "width": 400, "height": 300, "part_id": 1 },
            { "x": 805, "y": 305, "width": 400, "height": 300, "part_id": 1 }
          ],
          "cut_length_mm":     10420,
          "cut_length_method": "guillotine",
          "offcuts": [
            { "x": 1220, "y": 0, "width": 1220, "height": 1220 },
            …
          ],
          "saw_plan": {
            "kind": "split", "x": 0, "y": 0, "width": 2440, "height": 1220,
            "axis": "x", "cuts": [5, 810, 1215],
            "children": [
              { "kind": "offcut", "x": 0, "y": 0, "width": 5, "height": 1220 },
              { "kind": "split", "x": 10, "y": 0, "width": 800, "height": 1220,
                "axis": "y", "cuts": [5, 610],
                "children": [
                  { "kind": "offcut", "x": 10, "y": 0, "width": 800, "height": 5 },
                  { "kind": "part", "x": 10, "y": 10, "width": 800, "height": 600,
                    "cut_index": 0 },
                  …
                ] },
              …
            ]
          }
        }
      ],
      "summary": {
        "total_stock_used":    1,
        "total_parts":         12,
        "material_efficiency": 91.8,
        "total_cut_length_mm": 10420
      }
    }
  ]
}

La risposta contiene una voce results per materiale. Ogni voce include:

  • layouts — un oggetto per pannello utilizzato; cuts elenca posizione (x, y) e dimensioni di ogni pezzo
  • summary — total_stock_used, total_parts, material_efficiency (0–100 %) e total_cut_length_mm

stock_width e stock_height descrivono la superficie utile, sottraendo trim_stock_plate dai quattro bordi. Le coordinate cut partono dall’angolo superiore sinistro di questa superficie. part_id è l’indice del pezzo nel proprio gruppo di materiale, non un identificativo globale.

cut_length_mm ha due misure, indicate da cut_length_method: "guillotine" è il percorso della sezionatrice; "contour", il perimetro percorso dalla fresa. Sono grandezze fisiche diverse: non sommarle né confrontarle tra loro.

stock_index è la posizione del pannello sorgente in stock_plates. offcuts sono i resti senza pezzi lasciati interi dai tagli, inclusi piccoli scarti. A differenza di cuts, si trovano sulla superficie grezza. Le dimensioni fisiche già sottraggono il taglio e includono i bordi non rifilati.

saw_plan rappresenta lo stesso piano come albero sul pannello grezzo. Una regione "split" viene divisa da tagli paralleli: cuts indica l’inizio delle fasce lungo axis ("x": longitudinale; "y": trasversale). Ogni fascia è larga blade_width. children contiene una voce per intervallo, o null se non resta nulla. Le foglie sono pezzi "part", con cut_index riferito a cuts, e resti "offcut". Il valore null indica l’assenza di una sequenza rettilinea, possibile con disposizioni "cnc".

POST/api/optimize/pdf

Ottimizza e genera un PDF multipagina, una pagina per pannello. Il file viene salvato nel cloud e si restituisce un URL di download firmato.

Richiesta

Stesso corpo JSON di /api/optimize (vedi sopra).

Risposta

{
  "files": [
    {
      "name": "layout-1708433600000.pdf",
      "url":  "https://storage.example.com/pdf/1708433600000/layout-1708433600000.pdf"
    }
  ]
}

La risposta contiene un unico PDF con tutti i pannelli.

POST/api/optimize/dxf

Ottimizza e genera un DXF per pannello, compatibile con la maggior parte dei software CAD/CAM e controlli CNC (AutoCAD, Fusion 360, Mach3, ecc.). Restituisce URL individuali dei file salvati.

Richiesta

Stesso corpo JSON di /api/optimize (vedi sopra).

Risposta

{
  "files": [
    {
      "name": "plate-1-25318.dxf",
      "url":  "https://storage.example.com/dxf/1708433600000/plate-1-25318.dxf"
    },
    {
      "name": "plate-2-25318.dxf",
      "url":  "https://storage.example.com/dxf/1708433600000/plate-2-25318.dxf"
    }
  ]
}

Un file per pannello. Il nome contiene indice e identificativo dell’esecuzione: plate-1-25318.dxf indica il pannello 1 dell’esecuzione 25318.

POST/api/optimize/csv

Ottimizza e genera un CSV con tutti i pezzi di tutti i materiali e pannelli. Ogni riga contiene posizione, misure del pezzo e pannello, nome e codice materiale, per fogli di calcolo, ERP o postprocessori. Il file viene salvato nel cloud e si restituisce il suo URL.

Richiesta

Stesso corpo JSON di /api/optimize (vedi sopra).

Colonne CSV

Part ID, x, y, width, height, stock_width, stock_height, material(as name), material(as identifier)

Risposta

{
  "files": [
    {
      "name": "layout-1708433600000.csv",
      "url":  "https://storage.example.com/csv/1708433600000/layout-1708433600000.csv"
    }
  ]
}

Un unico CSV con tutti i tagli di tutti i materiali e pannelli.

POST/api/optimize/svg

Ottimizza e genera un SVG per pannello. La grafica vettoriale scalabile è adatta ad anteprime web e importazione in Inkscape, Illustrator o Figma. Restituisce URL individuali dei file salvati.

Richiesta

Stesso corpo JSON di /api/optimize (vedi sopra).

Risposta

{
  "files": [
    {
      "name": "plate-1-25318.svg",
      "url":  "https://storage.example.com/svg/1708433600000/plate-1-25318.svg"
    },
    {
      "name": "plate-2-25318.svg",
      "url":  "https://storage.example.com/svg/1708433600000/plate-2-25318.svg"
    }
  ]
}
POST/api/optimize/ptx
Beta

L’esportazione PTX è in fase beta e non è ancora stata verificata su macchine reali. Verificare i file esportati sulla propria macchina prima di utilizzarli in produzione.

Ottimizza e genera un PTX (Pattern Exchange) per gruppo di materiale. Il formato per sezionatrici HOLZMA / HOMAG è accettato da HolzLink, CADmatic 4/5 e HOMAG intelliDivide. Ogni file contiene il lavoro del materiale, schemi e sequenze di taglio. Restituisce gli URL dei file nel cloud.

Richiesta

Stesso corpo JSON di /api/optimize (vedi sopra). optimize_type: "saw" genera schemi a ghigliottina adatti alle sezionatrici.

Risposta

{
  "files": [
    {
      "name": "J1708433600000.PTX",
      "url":  "https://storage.example.com/ptx/1708433600000/J1708433600000.PTX"
    }
  ]
}

Un PTX per gruppo di materiale. Ogni file include:

  • HEADER, una riga JOBS e una riga MATERIALS — metadati del programma, spessore, larghezza del taglio e rifilatura.
  • BOARDS + PATTERNS — una coppia per schema distinto, con misure grezze e numero di pannelli che lo usano. Gli schemi identici vengono uniti.
  • PARTS_REQ + PARTS_INF + PARTS_UDI — righe corrispondenti a ogni geometria distinta nello schema, numerate nell’intero lavoro. Le quantità includono tutti i pannelli ripetuti. Descrizioni ed etichette dei bordi facoltative sono vuote; il codice materiale è DSP.
  • CUTS — istruzioni di taglio iniziale, longitudinale, trasversale, ripresa e rifilatura; una sequenza per schema con riferimenti ai pezzi richiesti.

Spessore predefinito: 18 mm, comune per pannelli da mobili. Misure in millimetri. Nomi di programma e file: J<timestamp>.PTX, con identificativo numerico unico per materiale.

Una disposizione annidata "cnc" non è sempre tagliabile con una sezionatrice. In tal caso l’endpoint restituisce 422 anziché un file.

Importazione di elenchi pezzi CSV

Gli endpoint from-csv accettano multipart/form-data invece di JSON. Carica un elenco da un foglio di calcolo: il server crea parts dalle righe. Materiali, pannelli, taglio e altre impostazioni vanno come stringa JSON in params.

Formato CSV

↓ Scarica modello / esempio CSVTutti i campi supportati e 10 pezzi di esempio con quantità diverse. Sostituisci i codici materiale con i tuoi.

Material Code,Width,Height,Quantity,Can Rotate
PLY18,800,600,4,1
PLY18,400,300,8,0
MDF16,1200,400,2,1

Come le righe diventano pezzi

  • L’intestazione è obbligatoria. Maiuscole, spazi esterni, trattini e underscore sono ignorati nei nomi: Material Code, Width, Height, Quantity, Can Rotate.
  • Material Code viene associato a identifier di una voce in materials. Un codice sconosciuto fa fallire la richiesta indicando la riga.
  • Can Rotate è facoltativo: 1 permette 90°, 0 lo vieta. Cella vuota o colonna assente significa nessuna rotazione, per preservare la venatura.
  • Material Code, Width, Height e Quantity sono obbligatori in ogni riga.
  • Sono supportati virgola, punto e virgola, tabulazione, BOM UTF-8 e testo tra virgolette. Le misure API sono millimetri interi positivi; le quantità, interi positivi.

Bordatura di ogni lato

Per Top, Right, Bottom e Left, usa Edge Band (codice), Edge Thickness (mm), Pre Milling (mm rimossi) e Edge Method. Esempi: Top Edge Band, Top Edge Thickness. I lati descrivono il pezzo prima della rotazione.

Lascia vuoti i lati non lavorati. Metodi: none, band, pre_mill_band. Il metodo omesso si ricava da codice, spessore e fresatura. I lati bordati richiedono spessore positivo; l’API non consulta il catalogo. L’importatore del laboratorio può copiarne uno spessore mancante.

Dimension Mode accetta blank (predefinito) o finished. L’ottimizzatore compensa spessore e prefresatura. Limiti macchina facoltativi: Banding Min Length, Banding Min Cross Size, Pre Milling Min Length, Pre Milling Min Cross Size, in mm; zero disattiva il limite. Processing Order elenca ogni lato una volta, come top right bottom left. Gli errori indicano la riga.

Il laboratorio importa anche Part Code, Part Name, Grain (none, paralleltowidth, paralleltolength), Priority e Notes. L’API CSV senza stato ignora questi metadati dell’ordine.

Campi della richiesta (multipart)

CampoStatoTipoDescrizione
fileobbligatorio—Elenco pezzi CSV con l’intestazione sopra.
paramsobbligatorio—Parametri di ottimizzazione JSON (tabella sotto). Tutti i campi di OptimizeRequest tranne parts.

Campi JSON di «params»

CampoStatoValore predefinitoDescrizione
materialsobbligatorio—È richiesto almeno un materiale. Ogni identifier viene associato al Material Code della riga.
stock_platesobbligatorio—Come in /api/optimize; è richiesto almeno un pannello.
optimize_typeobbligatorio—"saw" o "cnc" (come /api/optimize).
blade_widthfacoltativo5Larghezza del taglio in mm. Gli import accettano 0, a differenza dell’endpoint JSON.
trim_stock_platefacoltativo10Come in /api/optimize.
allow_mixed_stock_sizesfacoltativotrueCome in /api/optimize.
pattern_directionfacoltativo"none"Come in /api/optimize.
performance_modefacoltativo"normal"Come in /api/optimize.
random_seedfacoltativo0Come in /api/optimize.

Esempio JSON di «params»

{
  "materials": [
    { "id": 1, "name": "Plywood 18mm", "identifier": "PLY18", "thickness": 18 },
    { "id": 2, "name": "MDF 16mm",     "identifier": "MDF16", "thickness": 16 }
  ],
  "stock_plates": [
    { "width": 2440, "height": 1220, "quantity": 5, "material_id": 1 },
    { "width": 2800, "height": 2070, "quantity": 3, "material_id": 2 }
  ],
  "optimize_type":           "saw",
  "blade_width":              5,
  "trim_stock_plate":         10,
  "allow_mixed_stock_sizes":  true,
  "pattern_direction":       "none",
  "performance_mode":        "normal",
  "random_seed":              0
}

Esempio di richiesta (curl)

# risultato JSON
curl -X POST https://handifyit.com/api/optimize/from-csv \
  -H "Authorization: Bearer <your-api-token>" \
  -F "[email protected]" \
  -F 'params={
    "materials":    [{"id":1,"name":"Plywood 18mm","identifier":"PLY18","thickness":18}],
    "stock_plates": [{"width":2440,"height":1220,"quantity":5,"material_id":1}],
    "optimize_type":   "saw",
    "blade_width":      5,
    "trim_stock_plate": 10
  }'

# PDF — il formato di esportazione precede il suffisso «from-csv»:
curl -X POST https://handifyit.com/api/optimize/pdf/from-csv \
  -H "Authorization: Bearer <your-api-token>" \
  -F "[email protected]" \
  -F 'params={"materials":[...],"stock_plates":[...],"optimize_type":"saw"}'

# Stesso schema per /svg/from-csv /dxf/from-csv /csv/from-csv /ptx/from-csv

Endpoint

POST/api/optimize/from-csv

Legge il CSV, ottimizza e restituisce la disposizione JSON completa con la struttura di /api/optimize.

{
  "results": [
    {
      "material": { "id": 1, "name": "Plywood 18mm", "identifier": "PLY18",
                    "thickness": 18 },
      "layouts": [
        {
          "stock_width":  2420,
          "stock_height": 1200,
          "stock_index":  0,
          "cuts": [
            { "x": 0,   "y": 0,   "width": 800, "height": 600, "part_id": 0 },
            { "x": 805, "y": 0,   "width": 400, "height": 300, "part_id": 1 },
            { "x": 805, "y": 305, "width": 400, "height": 300, "part_id": 1 }
          ],
          "cut_length_mm":     10420,
          "cut_length_method": "guillotine",
          "offcuts": [
            { "x": 1220, "y": 0, "width": 1220, "height": 1220 },
            …
          ],
          "saw_plan": {
            "kind": "split", "x": 0, "y": 0, "width": 2440, "height": 1220,
            "axis": "x", "cuts": [5, 810, 1215],
            "children": [
              { "kind": "offcut", "x": 0, "y": 0, "width": 5, "height": 1220 },
              { "kind": "split", "x": 10, "y": 0, "width": 800, "height": 1220,
                "axis": "y", "cuts": [5, 610],
                "children": [
                  { "kind": "offcut", "x": 10, "y": 0, "width": 800, "height": 5 },
                  { "kind": "part", "x": 10, "y": 10, "width": 800, "height": 600,
                    "cut_index": 0 },
                  …
                ] },
              …
            ]
          }
        }
      ],
      "summary": {
        "total_stock_used":    1,
        "total_parts":         12,
        "material_efficiency": 91.8,
        "total_cut_length_mm": 10420
      }
    }
  ]
}
POST/api/optimize/{format}/from-csv

Stesso import con esportazione. {format} è pdf, svg, dxf, csv o ptx. La risposta usa { "files": [...] } con URL firmati.

Beta

L’esportazione PTX è in fase beta e non è ancora stata verificata su macchine reali. Verificare i file esportati sulla propria macchina prima di utilizzarli in produzione.

Ottimizzazione con importazione DXF

Gli endpoint from-dxf accettano multipart/form-data invece di JSON. Il server estrae contorni esterni DXF senza array parts manuale. Ogni contorno chiuso produce un pezzo con width e height dal rettangolo di delimitazione allineato agli assi. Le impostazioni vanno come JSON in params.

Estrazione dei pezzi DXF

  • Le entità chiuse LWPOLYLINE, POLYLINE, ELLIPSE e SPLINE al livello superiore, senza contorno contenitore, diventano pezzi.
  • width e height sono le misure del rettangolo allineato agli assi, arrotondate a interi nell’unità unit (predefinita mm). Si saltano pezzi sotto 1 unità in qualsiasi dimensione.
  • Tutti i pezzi ricevono il materiale material_id; per impostazione predefinita il id della prima voce di materials.
  • I contorni interni (fori, aperture, scanalature) sono ignorati. Per l’ottimizzazione conta solo il contorno esterno.

Campi della richiesta (multipart)

CampoStatoTipoDescrizione
fileobbligatorio—Byte del file DXF (R12–2018), con estensione .dxf obbligatoria.
paramsobbligatorio—Parametri JSON (tabella sotto): tutti i campi di OptimizeRequest tranne parts, più unit e material_id.

Campi JSON di «params»

CampoStatoValore predefinitoDescrizione
materialsobbligatorio—Come in /api/optimize; è richiesto almeno un materiale.
stock_platesobbligatorio—Come in /api/optimize; è richiesto almeno un pannello.
optimize_typeobbligatorio—"saw" o "cnc" (come /api/optimize).
unitfacoltativo"mm""cm"
material_idfacoltativoid del primo materialeIdentificativo materiale per tutti i pezzi DXF. Predefinito: il id della prima voce di materials.
blade_widthfacoltativo5Larghezza del taglio in mm. Gli import accettano 0, a differenza dell’endpoint JSON.
can_rotatefacoltativotrueApplicato a tutti i pezzi DXF, perché il disegno non specifica la rotazione per pezzo.
trim_stock_platefacoltativo10Come in /api/optimize.
allow_mixed_stock_sizesfacoltativotrueCome in /api/optimize.
pattern_directionfacoltativo"none"Come in /api/optimize.
performance_modefacoltativo"normal"Come in /api/optimize.
random_seedfacoltativo0Come in /api/optimize.

Esempio JSON di «params»

{
  "materials": [
    { "id": 1, "name": "Plywood 18mm", "identifier": "PLY18", "thickness": 18.0 }
  ],
  "stock_plates": [
    { "width": 2440, "height": 1220, "quantity": 5, "material_id": 1 }
  ],
  "optimize_type":           "saw",
  "blade_width":              5,
  "can_rotate":               true,
  "trim_stock_plate":         10,
  "allow_mixed_stock_sizes":  true,
  "pattern_direction":       "none",
  "performance_mode":        "normal",
  "random_seed":              0,
  "unit":                    "mm",
  "material_id":              1
}

Esempio di richiesta (curl)

# risultato JSON
curl -X POST https://handifyit.com/api/optimize/from-dxf \
  -H "Authorization: Bearer <your-api-token>" \
  -F "[email protected]" \
  -F 'params={
    "materials":       [{"id":1,"name":"Plywood 18mm","identifier":"PLY18","thickness":18}],
    "stock_plates":    [{"width":2440,"height":1220,"quantity":5,"material_id":1}],
    "optimize_type":   "saw",
    "blade_width":      5,
    "can_rotate":       true,
    "trim_stock_plate": 10,
    "unit":            "mm"
  }'

# PDF — usa l’endpoint di esportazione PDF:
curl -X POST https://handifyit.com/api/optimize/pdf/from-dxf \
  -H "Authorization: Bearer <your-api-token>" \
  -F "[email protected]" \
  -F 'params={"materials":[...],"stock_plates":[...],"optimize_type":"saw"}'

# Stesso schema per /svg/from-dxf /dxf/from-dxf /csv/from-dxf /ptx/from-dxf

Endpoint

POST/api/optimize/from-dxf

Legge il DXF, ottimizza e restituisce la disposizione JSON completa con la struttura di /api/optimize.

{
  "results": [
    {
      "material": { "id": 1, "name": "Plywood 18mm", "identifier": "PLY18",
                    "thickness": 18 },
      "layouts": [
        {
          "stock_width":  2420,
          "stock_height": 1200,
          "stock_index":  0,
          "cuts": [
            { "x": 0,   "y": 0,   "width": 800, "height": 600, "part_id": 0 },
            { "x": 805, "y": 0,   "width": 400, "height": 300, "part_id": 1 },
            { "x": 805, "y": 305, "width": 400, "height": 300, "part_id": 1 }
          ],
          "cut_length_mm":     10420,
          "cut_length_method": "guillotine",
          "offcuts": [
            { "x": 1220, "y": 0, "width": 1220, "height": 1220 },
            …
          ],
          "saw_plan": {
            "kind": "split", "x": 0, "y": 0, "width": 2440, "height": 1220,
            "axis": "x", "cuts": [5, 810, 1215],
            "children": [
              { "kind": "offcut", "x": 0, "y": 0, "width": 5, "height": 1220 },
              { "kind": "split", "x": 10, "y": 0, "width": 800, "height": 1220,
                "axis": "y", "cuts": [5, 610],
                "children": [
                  { "kind": "offcut", "x": 10, "y": 0, "width": 800, "height": 5 },
                  { "kind": "part", "x": 10, "y": 10, "width": 800, "height": 600,
                    "cut_index": 0 },
                  …
                ] },
              …
            ]
          }
        }
      ],
      "summary": {
        "total_stock_used":    1,
        "total_parts":         12,
        "material_efficiency": 91.8,
        "total_cut_length_mm": 10420
      }
    }
  ]
}
POST/api/optimize/pdf/from-dxf

Legge il DXF, ottimizza e restituisce un piano PDF, una pagina per pannello, tramite URL firmato.

{
  "files": [
    {
      "name": "layout-1708433600000.pdf",
      "url":  "https://storage.example.com/pdf/1708433600000/layout-1708433600000.pdf"
    }
  ]
}
POST/api/optimize/svg/from-dxf

Legge il DXF, ottimizza e restituisce un SVG per pannello tramite URL firmati.

{
  "files": [
    {
      "name": "plate-1-25318.svg",
      "url":  "https://storage.example.com/svg/1708433600000/plate-1-25318.svg"
    },
    {
      "name": "plate-2-25318.svg",
      "url":  "https://storage.example.com/svg/1708433600000/plate-2-25318.svg"
    }
  ]
}
POST/api/optimize/dxf/from-dxf

Legge il DXF, ottimizza e restituisce un layout DXF per pannello tramite URL firmati.

{
  "files": [
    {
      "name": "plate-1-25318.dxf",
      "url":  "https://storage.example.com/dxf/1708433600000/plate-1-25318.dxf"
    },
    {
      "name": "plate-2-25318.dxf",
      "url":  "https://storage.example.com/dxf/1708433600000/plate-2-25318.dxf"
    }
  ]
}
POST/api/optimize/csv/from-dxf

Legge il DXF, ottimizza e restituisce un unico elenco di taglio CSV tramite URL firmato.

{
  "files": [
    {
      "name": "layout-1708433600000.csv",
      "url":  "https://storage.example.com/csv/1708433600000/layout-1708433600000.csv"
    }
  ]
}
POST/api/optimize/ptx/from-dxf
Beta

L’esportazione PTX è in fase beta e non è ancora stata verificata su macchine reali. Verificare i file esportati sulla propria macchina prima di utilizzarli in produzione.

Legge il DXF, ottimizza e restituisce PTX per sezionatrici HOLZMA / HOMAG tramite URL firmati.

{
  "files": [
    {
      "name": "J1708433600000.PTX",
      "url":  "https://storage.example.com/ptx/1708433600000/J1708433600000.PTX"
    }
  ]
}

Prevalidazione CNC

Prima della produzione, il prevalidatore CNC analizza un file DXF secondo i vincoli macchina. Estrae contorni e operazioni interne (fori, aperture, scanalature) e rileva violazioni delle regole geometriche.

CodiceGravitàDescrizione
PART_TOO_SMALLerroreIl rettangolo di delimitazione è sotto part_min_width × part_min_height.
PART_TOO_LARGEerroreIl rettangolo di delimitazione supera part_max_width × part_max_height.
OPERATION_OUTSIDE_PARTerroreUno o più vertici di un’operazione sono fuori dal pezzo.
OPERATION_INTERSECTS_EDGEerroreI bordi dell’operazione attraversano il contorno anche se i vertici sono interni.
OPERATION_TOO_CLOSE_TO_EDGEerrore / avvisoLa distanza dal bordo è sotto min_edge_offset. Errore se < ½ limite, avviso se < limite.
DRILL_DIAMETER_TOO_SMALLerroreIl diametro del foro è sotto drill_min_diameter.
DRILL_DIAMETER_TOO_LARGEerroreIl diametro del foro supera drill_max_diameter.
OPERATIONS_INTERSECTerroreDue operazioni sulla stessa faccia si sovrappongono.
OPERATIONS_TOO_CLOSEerrore / avvisoLa distanza tra superfici di due operazioni è sotto min_op_spacing. Errore se < ½ limite, avviso se < limite.
POST/api/validate-cnc

Carica DXF come multipart/form-data. La risposta è un ValidationReport completo: un PartResult per pezzo con operazioni e violazioni.

Campi della richiesta (multipart)

CampoStatoTipoDescrizione
fileobbligatorio—Byte DXF. Sono supportate quasi tutte le revisioni binarie R12–2018.
configfacoltativovalori predefinitiOggetto ValidationConfig in JSON (tabella sotto). Tutti i campi sono facoltativi; quelli omessi usano il valore predefinito.

Campi di ValidationConfig

CampoStatoValore predefinitoDescrizione
part_min_widthfacoltativo50Larghezza minima consentita del pezzo in mm.
part_min_heightfacoltativo50Altezza minima consentita del pezzo in mm.
part_max_widthfacoltativo2800Larghezza massima consentita del pezzo in mm.
part_max_heightfacoltativo2070Altezza massima consentita del pezzo in mm.
drill_min_diameterfacoltativo2Diametro minimo della punta in mm.
drill_max_diameterfacoltativo35Diametro massimo della punta in mm.
min_edge_offsetfacoltativo8Distanza minima (mm) dal bordo di un’operazione al contorno del pezzo.
min_op_spacingfacoltativo8Distanza minima tra superfici di due operazioni in mm.
groove_aspect_ratiofacoltativo3.0Un contorno interno chiuso è una scanalatura anziché un’apertura generica se il lato lungo ≥ questo rapporto × il lato corto.
unitfacoltativo"mm""cm"

Esempio di richiesta (curl)

curl -X POST https://handifyit.com/api/validate-cnc \
  -H "Authorization: Bearer <your-api-token>" \
  -F "[email protected]" \
  -F 'config={"part_min_width":50,"part_min_height":50,\
              "part_max_width":2800,"part_max_height":2070,\
              "drill_min_diameter":2,"drill_max_diameter":35,\
              "min_edge_offset":8,"min_op_spacing":8,\
              "groove_aspect_ratio":3,"unit":"mm"}'

Esempio di risposta

{
  "valid": false,
  "summary": {
    "total_parts":      3,
    "total_operations": 12,
    "total_issues":     2,
    "errors":           1,
    "warnings":         1
  },
  "parts": [
    {
      "id":    "part_1",
      "layer": "PART",
      "bbox":  { "min_x": 0, "min_y": 0, "max_x": 400, "max_y": 300,
                 "width": 400, "height": 300 },
      "operations": [
        {
          "id":     "op_1",
          "kind":   "drilling",
          "side":   "through",
          "layer":  "DRILL",
          "bbox":   { "min_x": 46, "min_y": 46, "max_x": 54, "max_y": 54,
                      "width": 8, "height": 8 },
          "center": { "x": 50, "y": 50 },
          "diameter": 8
        }
      ],
      "issues": [
        {
          "code":         "OPERATION_TOO_CLOSE_TO_EDGE",
          "message":      "Operation op_1 is 3.50 mm from the part edge (minimum: 8.0 mm)",
          "severity":     "error",
          "operation_id": "op_1"
        }
      ],
      "valid": false
    }
  ]
}

Campi principali della risposta:

  • valid — true solo se nessun pezzo ha problemi di gravità errore.
  • summary — totali: total_parts, total_operations, errors, warnings.
  • parts[] — un oggetto per pezzo rilevato con rettangolo di delimitazione, operazioni e problemi.
  • issues[].severity — "error" (bloccante) o "warning" (solo indicativo).

Preimpostazioni CNC

Salva preimpostazioni ValidationConfig con nome per verifiche successive. Sono private del tuo account.

GET/api/cnc-configs

Restituisce tutte le preimpostazioni dell’utente autenticato.

GET /api/cnc-configs
Authorization: Bearer <your-api-token>

→ 200 OK
{
  "configs": [
    {
      "id":         "d4f2a1b3-...",
      "name":       "Standard Router",
      "config":     { ... },
      "created_at": "2026-04-05T10:00:00Z",
      "updated_at": "2026-04-05T10:00:00Z"
    }
  ]
}
POST/api/cnc-configs

Crea una preimpostazione con nome. Restituisce 201 Created con la voce salvata.

POST /api/cnc-configs
Authorization: Bearer <your-api-token>
Content-Type: application/json

{
  "name": "Standard Router",
  "config": {
    "part_min_width":     50,
    "part_min_height":    50,
    "part_max_width":     2800,
    "part_max_height":    2070,
    "drill_min_diameter": 2,
    "drill_max_diameter": 35,
    "min_edge_offset":    8,
    "min_op_spacing":     8,
    "groove_aspect_ratio": 3,
    "unit": "mm"
  }
}

→ 201 Created
{
  "id":         "d4f2a1b3-...",
  "name":       "Standard Router",
  "config":     { ... },
  "created_at": "2026-04-05T10:00:00Z",
  "updated_at": "2026-04-05T10:00:00Z"
}
PUT/api/cnc-configs/{id}

Sostituisce nome e/o configurazione. Il corpo ha la struttura di POST. Restituisce 200 OK con la voce aggiornata o 404 se l’ID non esiste o appartiene a un altro utente.

DELETE/api/cnc-configs/{id}

Elimina definitivamente la preimpostazione. Restituisce 204 No Content se riesce o 404 se non esiste.

Risposte di errore

Tutti gli endpoint restituiscono errori nello stesso involucro JSON:

{ "message": "A part (800×600) does not fit any stock plate" }
  • 400 — limite pezzi superato: la somma di quantity supera il limite per richiesta del piano. Segnala anche CSV non valido o campo multipart mancante.
  • 401 — token Bearer mancante, scaduto o revocato.
  • 422 — un pezzo non entra in alcun pannello o i pannelli non bastano. L’ottimizzazione riesce interamente o fallisce; non restituisce layout parziali. Il messaggio indica pezzo o vincolo. PTX restituisce 422 anche se il piano non è segabile.
  • 429 — limite giornaliero raggiunto. Azzeramento a mezzanotte UTC.
  • 500 — errore interno del server, per esempio caricamento file fallito.