Documentación de la API
Integra la gestión de pedidos, la optimización de corte 2D y la validación DXF CNC de Handifyit en tu flujo de trabajo. La optimización admite resultados JSON y exportaciones PDF, SVG, DXF, CSV y PTX. Las solicitudes autenticadas usan la cabecera Authorization: Bearer <token>.
También puedes trabajar en el navegador: crear pedidos, importar piezas, comparar resultados guardados, elegir uno y actualizar los estados. La guía siguiente cubre la API; consulta el flujo de pedidos para empezar sin código. Cómo funciona
Ir a: Prevalidador CNC · POST /api/validate-cnc · Ajustes guardados · Optimización · Importación CSV · Importación DXF · Swagger UI
Autenticación — tokens API de larga duración
Handifyit usa Tokens API de larga duración para llamadas automatizadas o desde servidores. Siguen siendo válidos hasta que los revoque. Obtenga uno siguiendo estos tres pasos.
Inicie sesión para obtener un token de acceso
Envíe sus credenciales y abra la página Perfil.
POST /login
Content-Type: application/json
{
"email": "[email protected]",
"password": "yourpassword"
}
→ 200 OK
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}Cree un token API de larga duración
Asigne un nombre descriptivo al token API. Copie el token recibido: su valor solo se muestra una vez.
POST /api/tokens
Authorization: Bearer <access_token>
Content-Type: application/json
{
"name": "My Production App"
}
→ 201 Created
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", ← guarde este valor
"name": "My Production App"
}También puede revocar tokens API desde el Perfil.
Use el token API en cada solicitud
Envíe el token API como Bearer en todas las llamadas a /api/*.
POST /api/optimize
Authorization: Bearer <your-api-token>
Content-Type: application/json
{ ... cuerpo de la solicitud ... }Cuerpo común de la solicitud
Los seis endpoints de optimización aceptan el mismo cuerpo JSON. Solo son obligatorios materials, stock_plates, parts y optimize_type; los demás campos tienen valores predeterminados.
materialsobligatorio—Lista de materiales. Cada objeto requiere id (entero), name (cadena), identifier (código corto) y puede incluir thickness en mm (18 por defecto). Piezas y tableros se agrupan por material_id.stock_platesobligatorio—Tableros disponibles para cortar. Cada objeto: width, height, quantity (1 por defecto), material_id.partsobligatorio—Piezas que cortar. Cada objeto: width, height, quantity (1 por defecto), material_id y can_rotate (true por defecto). La rotación se define por pieza.optimize_typeobligatorio—"saw" — cortes rectos de guillotina para sierras de paneles. "cnc" — distribución anidada para fresadoras CNC, más flexible pero más lenta.blade_widthopcional5Ancho de corte de sierra o fresa, 1–10, en las mismas unidades que piezas y tableros. Se descuenta entre cortes. La importación de archivos acepta 0–10.trim_stock_plateopcional10Margen retirado de cada borde antes de optimizar, 0–50, para eliminar material inutilizable.allow_mixed_stock_sizesopcionaltruePermite mezclar formatos de tableros de un material. Con false, todos sus tableros deben tener el mismo tamaño.pattern_directionopcional"none""paralleltowidth"performance_modeopcional"normal""fast" — respuesta más rápida. "normal" — equilibrado (recomendado). "high" — compactación intensiva para reducir desperdicios, con más tiempo de cálculo.random_seedopcional0Semilla entera del generador aleatorio. Reutilícela para reproducir distribuciones idénticas entre solicitudes.can_rotateopcional—Obsoleto. Este ajuste global se conserva por compatibilidad y fuerza la misma rotación en todas las piezas. Omítalo para aplicar los indicadores can_rotate de cada pieza.Ejemplo completo de solicitud
{
"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
}Límites del plan gratuito
Las cuentas gratuitas tienen estos límites en todos los endpoints de optimización (/api/optimize, /api/optimize/pdf, /api/optimize/dxf, /api/optimize/svg, /api/optimize/csv, /api/optimize/ptx y todas las variantes from-dxf y from-csv):
- 25 piezas por solicitud — la suma de todos los valores
part.quantitydel arraypartsno debe superar 25. Superarlo devuelve400. - 25 solicitudes de optimización al día — se cuentan por cuenta y se reinician a medianoche UTC. Superarlo devuelve
429.
Ejecuta el optimizador y devuelve la distribución completa en JSON. No crea archivos; utilice este endpoint para procesar o mostrar resultados en su aplicación.
Estructura de la respuesta
{
"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 respuesta contiene una entrada results por material. Cada entrada incluye:
layouts— un objeto por tablero utilizado;cutsindica la posición (x,y) y el tamaño de cada piezasummary—total_stock_used,total_parts,material_efficiency(0–100 %) ytotal_cut_length_mm
stock_width y stock_height describen la superficie útil, tras restar trim_stock_plate de los cuatro bordes. Las coordenadas cut parten de su esquina superior izquierda. part_id es el índice de la pieza en su grupo de material, no un identificador global.
cut_length_mm se mide de dos formas, indicadas por cut_length_method: "guillotine" es el recorrido de la sierra; "contour", el perímetro que recorre la fresa. Son magnitudes físicas diferentes: nunca las sume ni las compare entre sí.
stock_index es la posición del tablero de origen en stock_plates. offcuts son los restos sin piezas que los cortes dejan enteros, incluidos recortes pequeños. A diferencia de cuts, se posicionan sobre la superficie original. Sus medidas físicas ya descuentan el ancho de corte e incluyen bordes sin recortar.
saw_plan representa el mismo plan como árbol sobre el tablero original. Una región "split" se divide con cortes paralelos: cuts indica el inicio de cada banda según axis ("x": longitudinal; "y": transversal). Cada banda mide blade_width. children contiene una entrada por intervalo, o null si no queda nada. Las hojas son piezas "part", con cut_index que apunta a cuts, y restos "offcut". El valor null indica que no hay secuencia de cortes rectos, como ocurre con algunas distribuciones "cnc".
Optimiza y crea un PDF de varias páginas, una por tablero. Lo guarda en la nube y devuelve una URL de descarga firmada.
Solicitud
Mismo cuerpo JSON que /api/optimize (véase arriba).
Respuesta
{
"files": [
{
"name": "layout-1708433600000.pdf",
"url": "https://storage.example.com/pdf/1708433600000/layout-1708433600000.pdf"
}
]
}La respuesta contiene un único PDF con todos los tableros.
Optimiza y crea un DXF por tablero, compatible con la mayoría de sistemas CAD/CAM y controles CNC (AutoCAD, Fusion 360, Mach3, etc.). Devuelve una URL por archivo almacenado.
Solicitud
Mismo cuerpo JSON que /api/optimize (véase arriba).
Respuesta
{
"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 archivo por tablero. El nombre incluye el índice y la ejecución: plate-1-25318.dxf corresponde al tablero 1 de la ejecución 25318.
Optimiza y crea un CSV con todas las piezas de todos los materiales y tableros. Cada fila incluye posición, medidas de pieza y tablero, nombre y código del material para hojas de cálculo, ERP o posprocesadores. Lo guarda en la nube y devuelve su URL.
Solicitud
Mismo cuerpo JSON que /api/optimize (véase arriba).
Columnas CSV
Part ID, x, y, width, height, stock_width, stock_height, material(as name), material(as identifier)
Respuesta
{
"files": [
{
"name": "layout-1708433600000.csv",
"url": "https://storage.example.com/csv/1708433600000/layout-1708433600000.csv"
}
]
}Un único CSV con todos los cortes de todos los materiales y tableros.
Optimiza y crea un SVG por tablero. Estos gráficos vectoriales escalables sirven para vistas web e importación en Inkscape, Illustrator o Figma. Devuelve una URL por archivo almacenado.
Solicitud
Mismo cuerpo JSON que /api/optimize (véase arriba).
Respuesta
{
"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"
}
]
}La exportación PTX está en fase beta y aún no se ha validado en máquinas reales. Verifique los archivos exportados en su máquina antes de utilizarlos en producción.
Optimiza y crea un PTX (Pattern Exchange) por grupo de material. Este formato de transferencia para sierras HOLZMA / HOMAG funciona con HolzLink, CADmatic 4/5 y HOMAG intelliDivide. Cada archivo contiene el trabajo del material, sus patrones y secuencias de corte. Devuelve las URL de los archivos en la nube.
Solicitud
Mismo cuerpo JSON que /api/optimize (véase arriba). optimize_type: "saw" genera distribuciones de guillotina adecuadas para sierras de paneles.
Respuesta
{
"files": [
{
"name": "J1708433600000.PTX",
"url": "https://storage.example.com/ptx/1708433600000/J1708433600000.PTX"
}
]
}Un PTX por grupo de material. Cada archivo incluye:
HEADER, una filaJOBSy una filaMATERIALS— metadatos del programa, espesor, ancho de corte y recorte de bordes.BOARDS+PATTERNS— un par por distribución distinta, con medidas originales y número de tableros que la repiten. Las distribuciones iguales se combinan.PARTS_REQ+PARTS_INF+PARTS_UDI— filas correspondientes a cada geometría distinta de pieza del patrón, numeradas en todo el trabajo. Las cantidades incluyen todos los tableros repetidos. Descripciones y etiquetas de cantos opcionales están vacías; el código del material esDSP.CUTS— instrucciones de corte inicial, longitudinal, transversal, recorte y saneado; una secuencia por patrón con referencias a las piezas requeridas.
El espesor predeterminado es 18 mm, habitual en tableros para muebles. Medidas en milímetros. Programas y archivos usan J<timestamp>.PTX, con identificador numérico único por material.
Una distribución anidada "cnc" no siempre se puede ejecutar con sierra. En ese caso, el endpoint devuelve 422 en lugar de un archivo.
Importación de listas de piezas CSV
Los endpoints from-csv aceptan multipart/form-data en vez de JSON. Suba una lista desde una hoja de cálculo: el servidor genera parts a partir de sus filas. Materiales, tableros, ancho de corte y demás ajustes se envían como cadena JSON en params.
Formato CSV
↓ Descargar plantilla / ejemplo CSVTodos los campos admitidos y 10 piezas de ejemplo con distintas cantidades. Sustituya los códigos de material por los suyos.
Material Code,Width,Height,Quantity,Can Rotate
PLY18,800,600,4,1
PLY18,400,300,8,0
MDF16,1200,400,2,1Cómo se convierten las filas en piezas
- La cabecera es obligatoria. Se ignoran mayúsculas, espacios exteriores, guiones y guiones bajos en:
Material Code,Width,Height,Quantity,Can Rotate. Material Codese compara conidentifierde una entrada dematerials. Un código desconocido hace fallar la solicitud y el error señala la fila.Can Rotatees opcional:1permite girar 90°,0no. Una celda vacía o columna ausente significa sin rotación, para preservar la veta.Material Code,Width,HeightyQuantityson obligatorios en cada fila.- Admite coma, punto y coma, tabulación, BOM UTF-8 y texto entre comillas. Las dimensiones API son milímetros enteros positivos; las cantidades, enteros positivos.
Canteado de cada lado
Para Top, Right, Bottom y Left, use Edge Band (código), Edge Thickness (mm), Pre Milling (mm retirados) y Edge Method. Ejemplos: Top Edge Band, Top Edge Thickness. Los lados describen la pieza antes de girarla.
Deje vacíos los lados sin procesar. Métodos: none, band, pre_mill_band. Si se omite, se deduce del código, espesor y fresado. El canteado requiere espesor positivo; la API no consulta el catálogo. El importador del taller puede copiar de él un espesor ausente.
Dimension Mode acepta blank (predeterminado) o finished. El optimizador compensa espesor y prefresado. Límites opcionales: Banding Min Length, Banding Min Cross Size, Pre Milling Min Length, Pre Milling Min Cross Size, en mm; cero desactiva un límite. Processing Order enumera cada lado una vez, como top right bottom left. Los errores indican la fila.
El taller también importa Part Code, Part Name, Grain (none, paralleltowidth, paralleltolength), Priority y Notes. La API CSV sin estado ignora estos metadatos del pedido.
Campos de solicitud (multipart)
fileobligatorio—Lista de piezas CSV con la cabecera mostrada arriba.paramsobligatorio—Parámetros de optimización en JSON (tabla inferior). Todos los campos de OptimizeRequest, salvo parts.Campos JSON de «params»
materialsobligatorio—Se requiere al menos un material. Cada identifier se compara con el Material Code de una fila.stock_platesobligatorio—Como en /api/optimize; se requiere al menos un tablero.optimize_typeobligatorio—"saw" o "cnc" (como /api/optimize).blade_widthopcional5Ancho de corte en mm. Los imports aceptan 0, a diferencia del endpoint JSON.trim_stock_plateopcional10Como en /api/optimize.allow_mixed_stock_sizesopcionaltrueComo en /api/optimize.pattern_directionopcional"none"Como en /api/optimize.performance_modeopcional"normal"Como en /api/optimize.random_seedopcional0Como en /api/optimize.Ejemplo JSON de «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
}Ejemplo de solicitud (curl)
# resultado 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 — el formato de exportación va antes del sufijo «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"}'
# Mismo patrón para /svg/from-csv /dxf/from-csv /csv/from-csv /ptx/from-csvEndpoints
Lee el CSV, optimiza y devuelve la distribución JSON completa con la misma estructura que /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
}
}
]
}Mismo import con exportación. {format} es pdf, svg, dxf, csv o ptx. La respuesta usa { "files": [...] } con URL de descarga firmadas.
La exportación PTX está en fase beta y aún no se ha validado en máquinas reales. Verifique los archivos exportados en su máquina antes de utilizarlos en producción.
Optimización con importación DXF
Los endpoints from-dxf aceptan multipart/form-data en vez de JSON. El servidor extrae contornos exteriores DXF sin un array parts manual. Cada límite cerrado genera una pieza con width y height del rectángulo delimitador alineado con los ejes. Todos los ajustes se envían como JSON en params.
Extracción de piezas DXF
- Las entidades cerradas
LWPOLYLINE,POLYLINE,ELLIPSEySPLINEde nivel superior, sin contorno contenedor, se convierten en piezas. widthyheightson medidas del rectángulo alineado con los ejes, redondeadas a enteros enunit(mm por defecto). Se omiten piezas menores de 1 unidad en cualquier dimensión.- Todas las piezas reciben el material
material_id; por defecto, elidde la primera entrada dematerials. - Se ignoran contornos interiores (taladros, vaciados, ranuras). Solo el contorno exterior importa para optimizar.
Campos de solicitud (multipart)
fileobligatorio—Bytes del archivo DXF (R12–2018), con extensión .dxf obligatoria.paramsobligatorio—Parámetros JSON (tabla inferior): todos los campos de OptimizeRequest salvo parts, más unit y material_id.Campos JSON de «params»
materialsobligatorio—Como en /api/optimize; se requiere al menos un material.stock_platesobligatorio—Como en /api/optimize; se requiere al menos un tablero.optimize_typeobligatorio—"saw" o "cnc" (como /api/optimize).unitopcional"mm""cm"material_idopcionalid del primer materialIdentificador del material de todas las piezas DXF. Por defecto, el id de la primera entrada de materials.blade_widthopcional5Ancho de corte en mm. Los imports aceptan 0, a diferencia del endpoint JSON.can_rotateopcionaltrueSe aplica a todas las piezas DXF, ya que el dibujo no indica rotación por pieza.trim_stock_plateopcional10Como en /api/optimize.allow_mixed_stock_sizesopcionaltrueComo en /api/optimize.pattern_directionopcional"none"Como en /api/optimize.performance_modeopcional"normal"Como en /api/optimize.random_seedopcional0Como en /api/optimize.Ejemplo JSON de «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
}Ejemplo de solicitud (curl)
# resultado 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 — use el endpoint de exportación 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"}'
# Mismo patrón para /svg/from-dxf /dxf/from-dxf /csv/from-dxf /ptx/from-dxfEndpoints
Lee el DXF, optimiza y devuelve la distribución JSON completa con la misma estructura que /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
}
}
]
}Lee el DXF, optimiza y devuelve un plan PDF, una página por tablero, mediante URL firmada.
{
"files": [
{
"name": "layout-1708433600000.pdf",
"url": "https://storage.example.com/pdf/1708433600000/layout-1708433600000.pdf"
}
]
}Lee el DXF, optimiza y devuelve un SVG por tablero mediante URL firmadas.
{
"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"
}
]
}Lee el DXF, optimiza y devuelve una distribución DXF por tablero mediante URL firmadas.
{
"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"
}
]
}Lee el DXF, optimiza y devuelve una única lista de corte CSV mediante URL firmada.
{
"files": [
{
"name": "layout-1708433600000.csv",
"url": "https://storage.example.com/csv/1708433600000/layout-1708433600000.csv"
}
]
}La exportación PTX está en fase beta y aún no se ha validado en máquinas reales. Verifique los archivos exportados en su máquina antes de utilizarlos en producción.
Lee el DXF, optimiza y devuelve archivos PTX para sierras HOLZMA / HOMAG mediante URL firmadas.
{
"files": [
{
"name": "J1708433600000.PTX",
"url": "https://storage.example.com/ptx/1708433600000/J1708433600000.PTX"
}
]
}Prevalidación CNC
Antes de fabricar, el prevalidador CNC analiza un archivo DXF según los límites de la máquina. Extrae contornos y operaciones interiores (taladros, vaciados, ranuras) y detecta infracciones de reglas geométricas.
PART_TOO_SMALLerrorEl rectángulo delimitador es menor que part_min_width × part_min_height.PART_TOO_LARGEerrorEl rectángulo delimitador supera part_max_width × part_max_height.OPERATION_OUTSIDE_PARTerrorUno o más vértices de una operación están fuera de la pieza.OPERATION_INTERSECTS_EDGEerrorLas aristas de la operación cruzan el borde aunque los vértices estén dentro.OPERATION_TOO_CLOSE_TO_EDGEerror / advertenciaLa distancia al borde es menor que min_edge_offset. Error si < ½ límite; advertencia si < límite.DRILL_DIAMETER_TOO_SMALLerrorEl diámetro de taladro es menor que drill_min_diameter.DRILL_DIAMETER_TOO_LARGEerrorEl diámetro de taladro supera drill_max_diameter.OPERATIONS_INTERSECTerrorDos operaciones sobre la misma cara se solapan.OPERATIONS_TOO_CLOSEerror / advertenciaLa distancia entre superficies de dos operaciones es menor que min_op_spacing. Error si < ½ límite; advertencia si < límite.Suba un DXF como multipart/form-data. La respuesta es un ValidationReport completo: un PartResult por pieza con operaciones e infracciones.
Campos de solicitud (multipart)
fileobligatorio—Bytes DXF. Se admiten la mayoría de revisiones binarias R12–2018.configopcionalvalores predeterminadosObjeto ValidationConfig en JSON (tabla inferior). Todos los campos son opcionales; los omitidos toman su valor predeterminado.Campos de ValidationConfig
part_min_widthopcional50Ancho mínimo permitido de pieza en mm.part_min_heightopcional50Altura mínima permitida de pieza en mm.part_max_widthopcional2800Ancho máximo permitido de pieza en mm.part_max_heightopcional2070Altura máxima permitida de pieza en mm.drill_min_diameteropcional2Diámetro mínimo de broca en mm.drill_max_diameteropcional35Diámetro máximo de broca en mm.min_edge_offsetopcional8Distancia mínima (mm) de la arista de una operación al contorno de la pieza.min_op_spacingopcional8Distancia mínima entre superficies de dos operaciones en mm.groove_aspect_ratioopcional3.0Un contorno interior cerrado es una ranura, en vez de un vaciado genérico, si el lado largo ≥ esta proporción × el lado corto.unitopcional"mm""cm"Ejemplo de solicitud (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"}'Ejemplo de respuesta
{
"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
}
]
}Campos principales de la respuesta:
valid—truesolo si ninguna pieza tiene problemas de gravedad error.summary— totales:total_parts,total_operations,errors,warnings.parts[]— un objeto por pieza detectada con rectángulo delimitador, operaciones y problemas.issues[].severity—"error"(bloqueante) o"warning"(solo informativo).
Preajustes de configuración CNC
Guarde preajustes ValidationConfig con nombre para próximas validaciones. Son privados de su cuenta.
Devuelve todos los preajustes del usuario autenticado.
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"
}
]
}Crea un preajuste con nombre. Devuelve 201 Created con la entrada guardada.
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"
}Sustituye nombre y/o configuración. El cuerpo tiene la estructura de POST. Devuelve 200 OK con la entrada actualizada, o 404 si el ID no existe o pertenece a otro usuario.
Elimina permanentemente el preajuste. Devuelve 204 No Content si tiene éxito, o 404 si no existe.
Respuestas de error
Todos los endpoints devuelven errores en el mismo envoltorio JSON:
{ "message": "A part (800×600) does not fit any stock plate" }400— límite de piezas superado: la suma dequantityexcede el máximo por solicitud del plan. También indica CSV incorrecto o campo multipart ausente.401— token Bearer ausente, caducado o revocado.422— una pieza no cabe en ningún tablero o faltan tableros. La optimización es completa o falla; nunca devuelve distribución parcial. El mensaje identifica la pieza o restricción. PTX también devuelve 422 si no puede cortarse con sierra.429— límite diario alcanzado. Se reinicia a medianoche UTC.500— error interno del servidor, como fallo al subir un archivo.