API-Dokumentation

Integrieren Sie Auftragsverwaltung, 2D-Zuschnittoptimierung und DXF-CNC-Prüfung von Handifyit in Ihren Arbeitsablauf. Die Optimierung unterstützt JSON-Ergebnisse und PDF-, SVG-, DXF-, CSV- und PTX-Exporte. Authentifizierte API-Anfragen verwenden den Header Authorization: Bearer <token>.

Sie können auch im Browser arbeiten: Zuschnittaufträge erstellen, Teile importieren, gespeicherte Läufe vergleichen, ein Ergebnis wählen und Statuswerte ändern. Die folgende Anleitung behandelt die API; der Auftragsablauf zeigt den Einstieg ohne Code. So funktioniert es

Springe zu: CNC-Vorvalidierung · POST /api/validate-cnc · Voreinstellungen · Optimierung · CSV-Import · DXF-Import · Swagger UI

Authentifizierung — langlebige API-Token

Handifyit verwendet Langlebige API-Token für automatisierte oder serverseitige Aufrufe. Sie bleiben gültig, bis Sie sie ausdrücklich widerrufen. Die folgenden drei Schritte zeigen, wie Sie eines erhalten.

1

Anmelden und Zugriffstoken erhalten

Senden Sie Ihre Zugangsdaten und öffnen Sie die Seite Profil.

POST /login
Content-Type: application/json

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

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

Langlebiges API-Token erstellen

Geben Sie dem API-Token einen aussagekräftigen Namen. Kopieren Sie das erhaltene Token: Der Wert wird nur einmal angezeigt.

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

{
  "name": "My Production App"
}

→ 201 Created
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",  ← diesen Wert speichern!
  "name": "My Production App"
}

API-Token lassen sich auch über das Profil widerrufen.

3

API-Token bei jeder Anfrage verwenden

Übergeben Sie das API-Token als Bearer-Token bei allen Aufrufen von /api/*.

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

{ ... Anfrageinhalt ... }

Gemeinsamer Anfrageinhalt

Alle sechs Optimierungsendpunkte akzeptieren denselben JSON-Inhalt. Nur materials, stock_plates, parts und optimize_type sind erforderlich; die übrigen Felder haben Standardwerte.

FeldStatusStandardwertBeschreibung
materialserforderlich—Liste der Materialien. Jedes Objekt benötigt id (Ganzzahl), name (Zeichenfolge), identifier (kurzer Code) und optional thickness in mm (Standard 18). Teile und Platten werden nach material_id gruppiert.
stock_plateserforderlich—Verfügbare Zuschnittplatten. Jedes Objekt: width, height, quantity (Standard 1), material_id.
partserforderlich—Zu schneidende Teile. Jedes Objekt: width, height, quantity (Standard 1), material_id und can_rotate (Standard true). Die Drehbarkeit wird pro Teil festgelegt.
optimize_typeerforderlich—"saw" — geradlinige Guillotineschnitte für Plattensägen. "cnc" — verschachtelte Anordnung für CNC-Fräsen, flexibler, aber langsamer.
blade_widthoptional5Schnittfugenbreite von Säge oder Fräser, 1–10, in derselben Einheit wie die Teile und Platten. Wird zwischen Schnitten abgezogen. Dateiimporte akzeptieren 0–10.
trim_stock_plateoptional10Besäumung an jeder Plattenkante vor der Optimierung, 0–50, um unbrauchbares Randmaterial zu entfernen.
allow_mixed_stock_sizesoptionaltrueErlaubt unterschiedliche Plattenformate innerhalb eines Materials. Mit false müssen alle Platten eines Materials gleich groß sein.
pattern_directionoptional"none""paralleltowidth"
performance_modeoptional"normal""fast" — schnellste Antwort. "normal" — ausgewogen (empfohlen). "high" — intensive Verdichtung mit weniger Verschnitt, aber längerer Berechnung.
random_seedoptional0Ganzzahliger Startwert des Zufallsgenerators. Derselbe Wert ermöglicht identische Anordnungen bei wiederholten Anfragen.
can_rotateoptional—Veraltet. Diese globale Einstellung bleibt aus Kompatibilitätsgründen erhalten und erzwingt dieselbe Drehbarkeit für alle Teile. Lassen Sie sie weg, damit die einzelnen can_rotate-Werte gelten.

Vollständiges Anfragebeispiel

{
  "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
}

Grenzen des kostenlosen Tarifs

Für kostenlose Konten gelten diese Grenzen bei allen Optimierungsendpunkten (/api/optimize, /api/optimize/pdf, /api/optimize/dxf, /api/optimize/svg, /api/optimize/csv, /api/optimize/ptx und allen Varianten von from-dxf und from-csv):

  • 25 Teile pro Anfrage — die Summe aller part.quantity-Werte im Array parts darf 25 nicht überschreiten. Andernfalls wird 400 zurückgegeben.
  • 25 Optimierungsanfragen pro Tag — pro Konto gezählt, Zurücksetzung um Mitternacht UTC. Eine Überschreitung liefert 429.
POST/api/optimize

Führt die Optimierung aus und liefert die vollständige Anordnung als JSON. Erstellt keine Dateien. Verwenden Sie diesen Endpunkt zur Verarbeitung oder Darstellung in Ihrer Anwendung.

Aufbau der Antwort

{
  "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
      }
    }
  ]
}

Die Antwort enthält einen results-Eintrag pro Material. Jeder Eintrag umfasst:

  • layouts — ein Objekt pro verwendeter Platte; cuts enthält Position (x, y) und Größe jedes Teils
  • summary — total_stock_used, total_parts, material_efficiency (0–100 %) und total_cut_length_mm

stock_width und stock_height beschreiben die nutzbare Fläche nach Abzug von trim_stock_plate an allen vier Kanten. Die cut-Koordinaten beginnen links oben in dieser Fläche. part_id ist der Teileindex innerhalb seiner Materialgruppe, keine globale Kennung.

cut_length_mm wird auf zwei Arten gemessen, die cut_length_method angibt: "guillotine" ist der Weg der Plattensäge, "contour" der vom Fräser umrundete Teileumfang. Diese unterschiedlichen physikalischen Größen dürfen nie addiert oder miteinander verglichen werden.

stock_index ist die Position der Ausgangsplatte in stock_plates. offcuts sind die unzerteilten, teilefreien Reste der geplanten Schnitte, einschließlich kleiner Abfälle. Anders als cuts liegen sie auf der unbesäumten Platte. Ihre physischen Maße berücksichtigen bereits die Schnittfuge und enthalten unbesäumte Ränder.

saw_plan bildet denselben Plan als Baum auf der Rohplatte ab. Ein "split"-Bereich wird durch parallele Schnitte geteilt: cuts nennt die Anfangspositionen der Schnittbänder entlang axis ("x": längs; "y": quer). Jedes Band ist blade_width breit. children enthält einen Eintrag pro Zwischenraum, oder null, wenn nichts bleibt. Blätter sind "part"-Teile, deren cut_index auf cuts verweist, sowie "offcut"-Reste. Der Wert null bedeutet, dass keine geradlinige Schnittfolge möglich ist, etwa bei manchen "cnc"-Anordnungen.

POST/api/optimize/pdf

Optimiert und erstellt ein mehrseitiges PDF mit einer Seite pro Platte. Die Datei wird im Cloud-Speicher abgelegt; eine signierte Download-URL wird zurückgegeben.

Anfrage

Derselbe JSON-Inhalt wie bei /api/optimize (siehe oben).

Antwort

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

Die Antwort enthält eine PDF-Datei mit allen Platten.

POST/api/optimize/dxf

Optimiert und erstellt eine DXF-Datei pro Platte. Kompatibel mit den meisten CAD/CAM-Systemen und CNC-Steuerungen (AutoCAD, Fusion 360, Mach3 usw.). Liefert einzelne URLs für die gespeicherten Dateien.

Anfrage

Derselbe JSON-Inhalt wie bei /api/optimize (siehe oben).

Antwort

{
  "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"
    }
  ]
}

Eine Datei pro Platte. Der Name enthält Plattenindex und Laufkennung: plate-1-25318.dxf bezeichnet Platte 1 aus Lauf 25318.

POST/api/optimize/csv

Optimiert und erstellt eine CSV-Datei für alle Teile, Materialien und Platten. Jede Zeile enthält Position, Teile- und Plattenmaße sowie Materialname und -code für Tabellen, ERP oder eigene Nachbearbeitung. Die Datei wird in der Cloud gespeichert und ihre URL zurückgegeben.

Anfrage

Derselbe JSON-Inhalt wie bei /api/optimize (siehe oben).

CSV-Spalten

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

Antwort

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

Eine CSV-Datei mit allen Schnitten aller Materialien und Platten.

POST/api/optimize/svg

Optimiert und erstellt eine SVG-Datei pro Platte. Skalierbare Vektorgrafiken eignen sich für Webvorschauen und Inkscape, Illustrator oder Figma. Liefert einzelne URLs für die gespeicherten Dateien.

Anfrage

Derselbe JSON-Inhalt wie bei /api/optimize (siehe oben).

Antwort

{
  "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

Der PTX-Export befindet sich in der Betaphase und wurde noch nicht an realen Maschinen geprüft. Prüfen Sie die exportierten Dateien vor dem Produktionseinsatz an Ihrer Maschine.

Optimiert und erstellt eine PTX-Datei (Pattern Exchange) pro Materialgruppe. Dieses Übertragungsformat für HOLZMA-/HOMAG-Plattensägen wird von HolzLink, CADmatic 4/5 und HOMAG intelliDivide unterstützt. Jede Datei enthält einen Materialauftrag mit Schnittmustern und Sägefolgen. Liefert URLs der Cloud-Dateien.

Anfrage

Derselbe JSON-Inhalt wie bei /api/optimize (siehe oben). optimize_type: "saw" erzeugt Guillotine-Anordnungen für Plattensägen.

Antwort

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

Eine PTX-Datei pro Materialgruppe. Jede Datei enthält:

  • HEADER, eine JOBS-Zeile und eine MATERIALS-Zeile — Programmmetadaten, Plattendicke, Schnittfuge und Besäumung.
  • BOARDS + PATTERNS — ein Paar pro unterschiedlicher Anordnung mit Rohmaßen und Wiederholungszahl. Identische Anordnungen werden zusammengefasst.
  • PARTS_REQ + PARTS_INF + PARTS_UDI — passende Zeilen für jede unterschiedliche Teilegeometrie im Muster, über den Auftrag nummeriert. Mengen berücksichtigen alle wiederholten Platten. Optionale Beschreibungen und Kantenetiketten sind leer; Materialcode: DSP.
  • CUTS — Kopf-, Längs-, Quer-, Nachschnitt- und Besäumungsanweisungen; eigene Folge pro Muster mit Verweisen auf benötigte Teile.

Standarddicke: 18 mm, üblich bei Möbelplatten. Maße in Millimetern. Programm- und Dateinamen verwenden J<timestamp>.PTX mit einer eindeutigen numerischen Kennung pro Material.

Eine verschachtelte "cnc"-Anordnung ist nicht immer auf einer Plattensäge ausführbar. Dann liefert der Endpunkt 422 statt einer Datei.

CSV-Teilelisten importieren

Die from-csv-Endpunkte akzeptieren multipart/form-data statt JSON. Laden Sie eine Teileliste aus einer Tabelle hoch: Der Server erzeugt parts aus den Zeilen. Materialien, Platten, Schnittfuge und weitere Einstellungen werden als JSON-Zeichenfolge in params übergeben.

CSV-Format

↓ CSV-Vorlage / Beispiel herunterladenAlle unterstützten Felder und 10 Beispielteile mit verschiedenen Mengen. Ersetzen Sie die Materialcodes durch Ihre eigenen.

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

Wie Zeilen zu Teilen werden

  • Eine Kopfzeile ist erforderlich. Groß-/Kleinschreibung, Randabstände, Bindestriche und Unterstriche werden ignoriert: Material Code, Width, Height, Quantity, Can Rotate.
  • Material Code wird mit identifier eines Eintrags in materials abgeglichen. Unbekannte Materialcodes führen zum Fehler mit Angabe der Zeile.
  • Can Rotate ist optional: 1 erlaubt eine Drehung um 90°, 0 nicht. Leere Zelle oder fehlende Spalte bedeutet keine Drehung, um die Maserung zu bewahren.
  • Material Code, Width, Height und Quantity sind in jeder Zeile erforderlich.
  • Komma, Semikolon, Tabulator, UTF-8-BOM und Text in Anführungszeichen werden unterstützt. API-Maße sind positive ganze Millimeter; Mengen sind positive Ganzzahlen.

Kantenbearbeitung pro Seite

Für Top, Right, Bottom und Left verwenden Sie Edge Band (Code), Edge Thickness (mm), Pre Milling (abgetragene mm) und Edge Method. Beispiele: Top Edge Band, Top Edge Thickness. Seiten beziehen sich auf das Teil vor der Drehung.

Unbearbeitete Seiten bleiben leer. Methoden: none, band, pre_mill_band. Fehlende Methoden werden aus Code, Dicke und Fräsen abgeleitet. Bekantete Seiten erfordern positive Dicke; die API schlägt keine Katalogcodes nach. Der Arbeitsbereich-Import kann fehlende Dicken aus dem Katalog übernehmen.

Dimension Mode akzeptiert blank (Standard) oder finished. Der Optimierer gleicht Dicke und Vorfräsen aus. Optionale Maschinengrenzen: Banding Min Length, Banding Min Cross Size, Pre Milling Min Length, Pre Milling Min Cross Size, jeweils in mm; null deaktiviert die Grenze. Processing Order nennt jede Seite einmal, etwa top right bottom left. Fehler nennen die Zeilennummer.

Der Arbeitsbereich importiert auch Part Code, Part Name, Grain (none, paralleltowidth, paralleltolength), Priority und Notes. Diese Auftragsmetadaten ignoriert die zustandslose CSV-Optimierungs-API.

Anfragefelder (multipart)

FeldStatusTypBeschreibung
fileerforderlich—CSV-Teileliste mit der oben gezeigten Kopfzeile.
paramserforderlich—Optimierungsparameter als JSON (Tabelle unten). Alle Felder von OptimizeRequest außer parts.

JSON-Felder von „params“

FeldStatusStandardwertBeschreibung
materialserforderlich—Mindestens ein Material ist erforderlich. identifier wird mit dem Material Code jeder Zeile abgeglichen.
stock_plateserforderlich—Wie bei /api/optimize; mindestens eine Platte ist erforderlich.
optimize_typeerforderlich—"saw" oder "cnc" (wie /api/optimize).
blade_widthoptional5Schnittfuge in mm. Anders als der JSON-Endpunkt erlauben Dateiimporte 0.
trim_stock_plateoptional10Wie bei /api/optimize.
allow_mixed_stock_sizesoptionaltrueWie bei /api/optimize.
pattern_directionoptional"none"Wie bei /api/optimize.
performance_modeoptional"normal"Wie bei /api/optimize.
random_seedoptional0Wie bei /api/optimize.

JSON-Beispiel für „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
}

Anfragebeispiel (curl)

# JSON-Ergebnis
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 — das Exportformat steht vor dem Suffix „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"}'

# Gleiches Muster für /svg/from-csv /dxf/from-csv /csv/from-csv /ptx/from-csv

Endpunkte

POST/api/optimize/from-csv

Liest CSV, optimiert und liefert die vollständige JSON-Anordnung mit derselben Struktur wie /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

Derselbe Import mit Export. {format} ist pdf, svg, dxf, csv oder ptx. Die Antwort verwendet { "files": [...] } mit signierten Download-URLs.

Beta

Der PTX-Export befindet sich in der Betaphase und wurde noch nicht an realen Maschinen geprüft. Prüfen Sie die exportierten Dateien vor dem Produktionseinsatz an Ihrer Maschine.

Optimierung mit DXF-Import

Die from-dxf-Endpunkte akzeptieren multipart/form-data statt JSON. Der Server liest äußere DXF-Konturen ohne manuelles parts-Array. Jede geschlossene Grenze wird zum Teil, dessen width und height aus dem achsenparallelen Begrenzungsrechteck stammen. Alle Einstellungen werden als JSON-Zeichenfolge in params übergeben.

Extraktion der DXF-Teile

  • Geschlossene LWPOLYLINE-, POLYLINE-, ELLIPSE- und SPLINE-Objekte auf oberster Ebene ohne umgebende Kontur werden zu Teilen.
  • width und height sind die achsenparallelen Begrenzungsmaße, auf Ganzzahlen in der Einheit unit gerundet (Standard mm). Teile unter 1 Einheit in einer Dimension werden übersprungen.
  • Alle Teile erhalten das Material material_id; standardmäßig die id des ersten Eintrags in materials.
  • Innenkonturen (Bohrungen, Ausschnitte, Nuten) werden ignoriert. Für die Zuschnittoptimierung zählt nur die äußere Grenze.

Anfragefelder (multipart)

FeldStatusTypBeschreibung
fileerforderlich—DXF-Dateibytes (R12–2018), mit erforderlicher Dateiendung .dxf.
paramserforderlich—JSON-Parameter (Tabelle unten): alle Felder von OptimizeRequest außer parts, zusätzlich unit und material_id.

JSON-Felder von „params“

FeldStatusStandardwertBeschreibung
materialserforderlich—Wie bei /api/optimize; mindestens ein Material ist erforderlich.
stock_plateserforderlich—Wie bei /api/optimize; mindestens eine Platte ist erforderlich.
optimize_typeerforderlich—"saw" oder "cnc" (wie /api/optimize).
unitoptional"mm""cm"
material_idoptionalid des ersten MaterialsMaterialkennung für alle DXF-Teile. Standard ist die id des ersten Eintrags in materials.
blade_widthoptional5Schnittfuge in mm. Anders als der JSON-Endpunkt erlauben Dateiimporte 0.
can_rotateoptionaltrueGilt für alle DXF-Teile, da die Zeichnung keine individuelle Drehbarkeit angibt.
trim_stock_plateoptional10Wie bei /api/optimize.
allow_mixed_stock_sizesoptionaltrueWie bei /api/optimize.
pattern_directionoptional"none"Wie bei /api/optimize.
performance_modeoptional"normal"Wie bei /api/optimize.
random_seedoptional0Wie bei /api/optimize.

JSON-Beispiel für „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
}

Anfragebeispiel (curl)

# JSON-Ergebnis
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 — den PDF-Exportendpunkt verwenden:
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"}'

# Gleiches Muster für /svg/from-dxf /dxf/from-dxf /csv/from-dxf /ptx/from-dxf

Endpunkte

POST/api/optimize/from-dxf

Liest DXF, optimiert und liefert die vollständige JSON-Anordnung mit derselben Struktur wie /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

Liest DXF, optimiert und liefert einen PDF-Schnittplan, eine Seite pro Platte, über eine signierte URL.

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

Liest DXF, optimiert und liefert eine SVG-Datei pro Platte über signierte URLs.

{
  "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

Liest DXF, optimiert und liefert eine DXF-Anordnung pro Platte über signierte URLs.

{
  "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

Liest DXF, optimiert und liefert eine CSV-Schnittliste über eine signierte URL.

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

Der PTX-Export befindet sich in der Betaphase und wurde noch nicht an realen Maschinen geprüft. Prüfen Sie die exportierten Dateien vor dem Produktionseinsatz an Ihrer Maschine.

Liest DXF, optimiert und liefert PTX-Dateien für HOLZMA-/HOMAG-Sägen über signierte URLs.

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

CNC-Vorprüfung

Vor der Fertigung prüft der CNC-Validator eine DXF-Datei anhand der Maschinengrenzen. Er liest Teilekonturen und innere Bearbeitungen wie Bohrungen, Ausschnitte und Nuten und erkennt Verstöße gegen geometrische Regeln.

CodeSchweregradBeschreibung
PART_TOO_SMALLFehlerDas Begrenzungsrechteck ist kleiner als part_min_width × part_min_height.
PART_TOO_LARGEFehlerDas Begrenzungsrechteck überschreitet part_max_width × part_max_height.
OPERATION_OUTSIDE_PARTFehlerMindestens ein Konturpunkt einer Bearbeitung liegt außerhalb des Teils.
OPERATION_INTERSECTS_EDGEFehlerBearbeitungskanten kreuzen die Teilegrenze, auch wenn die Eckpunkte innen liegen.
OPERATION_TOO_CLOSE_TO_EDGEFehler / WarnungDer Kantenabstand ist kleiner als min_edge_offset. Fehler bei < ½ Grenze, Warnung bei < Grenze.
DRILL_DIAMETER_TOO_SMALLFehlerDer Bohrdurchmesser ist kleiner als drill_min_diameter.
DRILL_DIAMETER_TOO_LARGEFehlerDer Bohrdurchmesser überschreitet drill_max_diameter.
OPERATIONS_INTERSECTFehlerZwei Bearbeitungen auf derselben Seite überlappen.
OPERATIONS_TOO_CLOSEFehler / WarnungDer Oberflächenabstand zwischen Bearbeitungen ist kleiner als min_op_spacing. Fehler bei < ½ Grenze, Warnung bei < Grenze.
POST/api/validate-cnc

Laden Sie DXF als multipart/form-data hoch. Die Antwort ist ein vollständiger ValidationReport: ein PartResult pro Teil mit Bearbeitungen und Verstößen.

Anfragefelder (multipart)

FeldStatusTypBeschreibung
fileerforderlich—DXF-Dateibytes. Die meisten binären Revisionen R12–2018 werden unterstützt.
configoptionalStandardwerteValidationConfig-Objekt als JSON (Tabelle unten). Alle Felder sind optional; ausgelassene Werte erhalten den Standard.

Felder von ValidationConfig

FeldStatusStandardwertBeschreibung
part_min_widthoptional50Minimale zulässige Teilebreite in mm.
part_min_heightoptional50Minimale zulässige Teilehöhe in mm.
part_max_widthoptional2800Maximale zulässige Teilebreite in mm.
part_max_heightoptional2070Maximale zulässige Teilehöhe in mm.
drill_min_diameteroptional2Minimaler Bohrerdurchmesser in mm.
drill_max_diameteroptional35Maximaler Bohrerdurchmesser in mm.
min_edge_offsetoptional8Mindestabstand (mm) von einer Bearbeitungskante zur Teilegrenze.
min_op_spacingoptional8Mindestabstand zwischen den Oberflächen zweier Bearbeitungen in mm.
groove_aspect_ratiooptional3.0Eine geschlossene Innenkontur gilt als Nut statt als allgemeiner Ausschnitt, wenn die lange Seite ≥ diesem Verhältnis × der kurzen Seite ist.
unitoptional"mm""cm"

Anfragebeispiel (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"}'

Antwortbeispiel

{
  "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
    }
  ]
}

Wichtige Antwortfelder:

  • valid — true nur, wenn kein Teil Probleme des Schweregrads Fehler hat.
  • summary — Gesamtzahlen: total_parts, total_operations, errors, warnings.
  • parts[] — ein Objekt je erkanntem Teil mit Begrenzungsrechteck, Bearbeitungen und Problemen.
  • issues[].severity — "error" (blockierend) oder "warning" (nur Hinweis).

CNC-Konfigurationsvorlagen

Speichern Sie benannte ValidationConfig-Vorlagen für spätere Prüfungen. Sie sind nur für Ihr Konto zugänglich.

GET/api/cnc-configs

Liefert alle gespeicherten Vorlagen des angemeldeten Benutzers.

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

Erstellt eine benannte Vorlage. Liefert 201 Created mit dem gespeicherten Eintrag.

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}

Ersetzt Namen und/oder Konfiguration. Der Inhalt hat dieselbe Struktur wie POST. Liefert 200 OK mit dem aktualisierten Eintrag oder 404, wenn die ID fehlt oder einem anderen Benutzer gehört.

DELETE/api/cnc-configs/{id}

Löscht die Vorlage dauerhaft. Liefert bei Erfolg 204 No Content, andernfalls 404, wenn sie fehlt.

Fehlerantworten

Alle Endpunkte geben Fehler in derselben JSON-Struktur zurück:

{ "message": "A part (800×600) does not fit any stock plate" }
  • 400 — Teilelimit überschritten: Die Summe von quantity übersteigt das Tariflimit pro Anfrage. Meldet auch fehlerhafte CSV-Dateien oder fehlende Multipart-Felder.
  • 401 — Bearer-Token fehlt, ist abgelaufen oder wurde widerrufen.
  • 422 — ein Teil passt auf keine Platte oder die Platten reichen nicht. Die Optimierung gelingt vollständig oder scheitert; es gibt keine Teilanordnung. Die Meldung nennt das Teil oder die Grenze. PTX liefert ebenfalls 422, wenn die Anordnung nicht sägbar ist.
  • 429 — Tageslimit erreicht. Zurücksetzung um Mitternacht UTC.
  • 500 — interner Serverfehler, etwa fehlgeschlagener Datei-Upload.