Documentação da API
Integre a gestão de encomendas, a otimização de corte 2D e a validação DXF CNC do Handifyit no seu fluxo de trabalho. A otimização suporta resultados JSON e exportações PDF, SVG, DXF, CSV e PTX. Os pedidos API autenticados usam o cabeçalho Authorization: Bearer <token>.
Também pode trabalhar no navegador: criar encomendas, importar peças, comparar resultados guardados, escolher um resultado e atualizar estados. O guia abaixo aborda a API; consulte o fluxo de encomendas para começar sem código. Como Funciona
Ir para: Pré-Validador CNC · POST /api/validate-cnc · Predefinições · Otimização · Importação CSV · Importação DXF · Swagger UI
Autenticação — tokens API de longa duração
O Handifyit usa Tokens API de longa duração para chamadas automáticas ou do servidor. Permanecem válidos até serem revogados explicitamente. Siga estes três passos para obter um.
Inicie sessão para obter um token de acesso
Envie as suas credenciais e abra a página Perfil.
POST /login
Content-Type: application/json
{
"email": "[email protected]",
"password": "yourpassword"
}
→ 200 OK
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}Crie um token API de longa duração
Dê um nome descritivo ao token API. Copie o token recebido: o valor só é apresentado uma 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"
}Também pode revogar tokens API no Perfil.
Use o token API em cada pedido
Envie o token API como Bearer em todas as chamadas a /api/*.
POST /api/optimize
Authorization: Bearer <your-api-token>
Content-Type: application/json
{ ... corpo do pedido ... }Corpo comum do pedido
Os seis endpoints de otimização aceitam o mesmo corpo JSON. Só materials, stock_plates, parts e optimize_type são obrigatórios; os restantes campos têm valores predefinidos.
materialsobrigatório—Lista de materiais. Cada objeto exige id (inteiro), name (texto), identifier (código curto) e pode incluir thickness em mm (18 por defeito). Peças e painéis agrupam-se por material_id.stock_platesobrigatório—Painéis disponíveis para corte. Cada objeto: width, height, quantity (1 por defeito), material_id.partsobrigatório—Peças a cortar. Cada objeto: width, height, quantity (1 por defeito), material_id e can_rotate (true por defeito). A rotação é definida por peça.optimize_typeobrigatório—"saw" — cortes retos de guilhotina para serras de painéis. "cnc" — disposição aninhada para fresadoras CNC, mais flexível mas mais lenta.blade_widthopcional5Largura do corte da serra ou fresa, 1–10, nas unidades das peças e painéis. É descontada entre cortes. A importação de ficheiros aceita 0–10.trim_stock_plateopcional10Margem retirada de cada borda antes da otimização, 0–50, para excluir material inutilizável.allow_mixed_stock_sizesopcionaltruePermite formatos diferentes no mesmo material. Com false, todos os painéis desse material têm de ter a mesma dimensão.pattern_directionopcional"none""paralleltowidth"performance_modeopcional"normal""fast" — resposta mais rápida. "normal" — equilibrado (recomendado). "high" — compactação intensiva para reduzir desperdício, com processamento mais longo.random_seedopcional0Semente inteira do gerador aleatório. Reutilize o valor para reproduzir disposições idênticas entre pedidos.can_rotateopcional—Obsoleto. Este ajuste global mantém-se por compatibilidade e impõe a mesma rotação a todas as peças. Omita-o para aplicar os valores can_rotate de cada peça.Exemplo completo de pedido
{
"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
}Limites do plano gratuito
As contas gratuitas têm estes limites em todos os endpoints de otimização (/api/optimize, /api/optimize/pdf, /api/optimize/dxf, /api/optimize/svg, /api/optimize/csv, /api/optimize/ptx e todas as variantes from-dxf e from-csv):
- 25 peças por pedido — a soma dos valores
part.quantityno arraypartsnão pode exceder 25. Exceder devolve400. - 25 pedidos de otimização por dia — contagem por conta, reiniciada à meia-noite UTC. Exceder devolve
429.
Executa o otimizador e devolve a disposição completa em JSON. Não cria ficheiros; use este endpoint para processar ou apresentar resultados na sua aplicação.
Estrutura da resposta
{
"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
}
}
]
}A resposta contém uma entrada results por material. Cada entrada inclui:
layouts— um objeto por painel utilizado;cutslista posição (x,y) e dimensão de cada peçasummary—total_stock_used,total_parts,material_efficiency(0–100 %) etotal_cut_length_mm
stock_width e stock_height descrevem a área útil, após retirar trim_stock_plate das quatro bordas. As coordenadas cut partem do canto superior esquerdo dessa área. part_id é o índice da peça no seu grupo de material, não um identificador global.
cut_length_mm tem duas medidas, indicadas por cut_length_method: "guillotine" é o percurso da serra; "contour", o perímetro percorrido pela fresa. São grandezas físicas diferentes: nunca as some nem compare entre si.
stock_index é a posição do painel de origem em stock_plates. offcuts são os restos sem peças deixados inteiros pelos cortes, incluindo pequenos resíduos. Ao contrário de cuts, posicionam-se na área original. As dimensões físicas já descontam o corte e incluem bordas não aparadas.
saw_plan representa o mesmo plano como árvore no painel original. Uma região "split" é dividida por cortes paralelos: cuts indica o início das faixas ao longo de axis ("x": longitudinal; "y": transversal). Cada faixa mede blade_width. children tem uma entrada por intervalo, ou null quando nada resta. As folhas são peças "part", com cut_index a apontar para cuts, e restos "offcut". O valor null significa que não existe sequência de cortes retos, como em certas disposições "cnc".
Otimiza e gera um PDF com várias páginas, uma por painel. Guarda-o na nuvem e devolve um URL de transferência assinado.
Pedido
Mesmo corpo JSON que /api/optimize (ver acima).
Resposta
{
"files": [
{
"name": "layout-1708433600000.pdf",
"url": "https://storage.example.com/pdf/1708433600000/layout-1708433600000.pdf"
}
]
}A resposta contém um único PDF com todos os painéis.
Otimiza e gera um DXF por painel, compatível com a maioria dos sistemas CAD/CAM e controladores CNC (AutoCAD, Fusion 360, Mach3, etc.). Devolve URLs individuais dos ficheiros guardados.
Pedido
Mesmo corpo JSON que /api/optimize (ver acima).
Resposta
{
"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"
}
]
}Um ficheiro por painel. O nome inclui o índice e a execução: plate-1-25318.dxf corresponde ao painel 1 da execução 25318.
Otimiza e gera um CSV com todas as peças de todos os materiais e painéis. Cada linha inclui posição, dimensões da peça e painel, nome e código do material, para folhas de cálculo, ERP ou pós-processadores. Guarda o ficheiro na nuvem e devolve o URL.
Pedido
Mesmo corpo JSON que /api/optimize (ver acima).
Colunas CSV
Part ID, x, y, width, height, stock_width, stock_height, material(as name), material(as identifier)
Resposta
{
"files": [
{
"name": "layout-1708433600000.csv",
"url": "https://storage.example.com/csv/1708433600000/layout-1708433600000.csv"
}
]
}Um único CSV com todos os cortes de todos os materiais e painéis.
Otimiza e gera um SVG por painel. Estes gráficos vetoriais escaláveis servem para pré-visualizações web e importação no Inkscape, Illustrator ou Figma. Devolve URLs individuais dos ficheiros guardados.
Pedido
Mesmo corpo JSON que /api/optimize (ver acima).
Resposta
{
"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"
}
]
}A exportação PTX está em fase beta e ainda não foi validada em máquinas reais. Verifique os ficheiros exportados na sua máquina antes de os utilizar em produção.
Otimiza e gera um PTX (Pattern Exchange) por grupo de material. Este formato para serras HOLZMA / HOMAG é aceite pelo HolzLink, CADmatic 4/5 e HOMAG intelliDivide. Cada ficheiro contém o trabalho do material, padrões e sequências de corte. Devolve os URLs dos ficheiros na nuvem.
Pedido
Mesmo corpo JSON que /api/optimize (ver acima). optimize_type: "saw" gera disposições de guilhotina adequadas a serras de painéis.
Resposta
{
"files": [
{
"name": "J1708433600000.PTX",
"url": "https://storage.example.com/ptx/1708433600000/J1708433600000.PTX"
}
]
}Um PTX por grupo de material. Cada ficheiro inclui:
HEADER, uma linhaJOBSe uma linhaMATERIALS— metadados do programa, espessura, largura de corte e aparagem.BOARDS+PATTERNS— um par por disposição distinta, com dimensões originais e número de painéis que a usam. Disposições iguais são combinadas.PARTS_REQ+PARTS_INF+PARTS_UDI— linhas correspondentes a cada geometria distinta no padrão, numeradas em todo o trabalho. As quantidades incluem todos os painéis repetidos. Descrições e etiquetas de bordas opcionais ficam vazias; o código do material éDSP.CUTS— instruções de corte inicial, longitudinal, transversal, recorte e aparagem; uma sequência por padrão com referências às peças necessárias.
Espessura predefinida: 18 mm, comum em painéis para mobiliário. Medidas em milímetros. Programas e ficheiros usam J<timestamp>.PTX, com identificador numérico único por material.
Uma disposição aninhada "cnc" nem sempre é cortável com serra. Nesse caso, o endpoint devolve 422 em vez de um ficheiro.
Importação de listas de peças CSV
Os endpoints from-csv aceitam multipart/form-data em vez de JSON. Envie uma lista de uma folha de cálculo: o servidor cria parts a partir das linhas. Materiais, painéis, largura de corte e restantes ajustes seguem como texto JSON em params.
Formato CSV
↓ Transferir modelo / exemplo CSVTodos os campos suportados e 10 peças de exemplo com quantidades variadas. Substitua os códigos de material pelos seus.
Material Code,Width,Height,Quantity,Can Rotate
PLY18,800,600,4,1
PLY18,400,300,8,0
MDF16,1200,400,2,1Como as linhas se tornam peças
- O cabeçalho é obrigatório. Maiúsculas, espaços exteriores, hífenes e sublinhados são ignorados nos nomes:
Material Code,Width,Height,Quantity,Can Rotate. Material Codeé associado aidentifierde uma entrada emmaterials. Um código desconhecido faz falhar o pedido; o erro indica a linha.Can Rotateé opcional:1permite rodar 90°,0não. Célula vazia ou coluna ausente significa sem rotação, para preservar o veio.Material Code,Width,HeighteQuantitysão obrigatórios em cada linha.- São suportados vírgula, ponto e vírgula, tabulação, BOM UTF-8 e texto entre aspas. Dimensões API são milímetros inteiros positivos; quantidades são inteiros positivos.
Orlagem de cada lado
Para Top, Right, Bottom e Left, use Edge Band (código), Edge Thickness (mm), Pre Milling (mm removidos) e Edge Method. Exemplos: Top Edge Band, Top Edge Thickness. Os lados descrevem a peça antes de rodar.
Deixe vazios os lados não processados. Métodos: none, band, pre_mill_band. O método omitido é inferido do código, espessura e fresagem. Lados orlados exigem espessura positiva; a API não consulta o catálogo. O importador da oficina pode copiar dele uma espessura ausente.
Dimension Mode aceita blank (predefinido) ou finished. O otimizador compensa espessura e pré-fresagem. Limites de máquina opcionais: Banding Min Length, Banding Min Cross Size, Pre Milling Min Length, Pre Milling Min Cross Size, em mm; zero desativa o limite. Processing Order lista cada lado uma vez, como top right bottom left. Erros indicam a linha.
A oficina também importa Part Code, Part Name, Grain (none, paralleltowidth, paralleltolength), Priority e Notes. A API CSV sem estado ignora estes metadados da encomenda.
Campos do pedido (multipart)
fileobrigatório—Lista de peças CSV com o cabeçalho indicado acima.paramsobrigatório—Parâmetros de otimização JSON (tabela abaixo). Todos os campos de OptimizeRequest, exceto parts.Campos JSON de «params»
materialsobrigatório—É necessário pelo menos um material. Cada identifier corresponde ao Material Code de uma linha.stock_platesobrigatório—Como em /api/optimize; é necessário pelo menos um painel.optimize_typeobrigatório—"saw" ou "cnc" (como /api/optimize).blade_widthopcional5Largura de corte em mm. Os imports aceitam 0, ao contrário do endpoint JSON.trim_stock_plateopcional10Como em /api/optimize.allow_mixed_stock_sizesopcionaltrueComo em /api/optimize.pattern_directionopcional"none"Como em /api/optimize.performance_modeopcional"normal"Como em /api/optimize.random_seedopcional0Como em /api/optimize.Exemplo 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
}Exemplo de pedido (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 — o formato de exportação vem antes do sufixo «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"}'
# Mesmo padrão para /svg/from-csv /dxf/from-csv /csv/from-csv /ptx/from-csvEndpoints
Lê CSV, otimiza e devolve a disposição JSON completa com a estrutura de /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
}
}
]
}Mesmo import com exportação. {format} é pdf, svg, dxf, csv ou ptx. A resposta usa { "files": [...] } com URLs assinados.
A exportação PTX está em fase beta e ainda não foi validada em máquinas reais. Verifique os ficheiros exportados na sua máquina antes de os utilizar em produção.
Otimização com importação DXF
Os endpoints from-dxf aceitam multipart/form-data em vez de JSON. O servidor extrai contornos exteriores DXF sem array parts manual. Cada contorno fechado gera uma peça com width e height do retângulo delimitador alinhado aos eixos. Todos os ajustes seguem como JSON em params.
Extração de peças DXF
- As entidades fechadas
LWPOLYLINE,POLYLINE,ELLIPSEeSPLINEno nível superior, sem contorno envolvente, tornam-se peças. widtheheightsão medidas do retângulo alinhado aos eixos, arredondadas a inteiros emunit(mm por defeito). Ignoram-se peças abaixo de 1 unidade em qualquer dimensão.- Todas as peças recebem o material
material_id; por defeito, oidda primeira entrada dematerials. - Contornos interiores (furos, recortes, ranhuras) são ignorados. Só o contorno exterior interessa à otimização.
Campos do pedido (multipart)
fileobrigatório—Bytes do ficheiro DXF (R12–2018), com extensão .dxf obrigatória.paramsobrigatório—Parâmetros JSON (tabela abaixo): todos os campos de OptimizeRequest exceto parts, mais unit e material_id.Campos JSON de «params»
materialsobrigatório—Como em /api/optimize; é necessário pelo menos um material.stock_platesobrigatório—Como em /api/optimize; é necessário pelo menos um painel.optimize_typeobrigatório—"saw" ou "cnc" (como /api/optimize).unitopcional"mm""cm"material_idopcionalid do primeiro materialIdentificador de material para todas as peças DXF. Por defeito, o id da primeira entrada de materials.blade_widthopcional5Largura de corte em mm. Os imports aceitam 0, ao contrário do endpoint JSON.can_rotateopcionaltrueAplica-se a todas as peças DXF, pois o desenho não indica rotação por peça.trim_stock_plateopcional10Como em /api/optimize.allow_mixed_stock_sizesopcionaltrueComo em /api/optimize.pattern_directionopcional"none"Como em /api/optimize.performance_modeopcional"normal"Como em /api/optimize.random_seedopcional0Como em /api/optimize.Exemplo 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
}Exemplo de pedido (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 o endpoint de exportação 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"}'
# Mesmo padrão para /svg/from-dxf /dxf/from-dxf /csv/from-dxf /ptx/from-dxfEndpoints
Lê DXF, otimiza e devolve a disposição JSON completa com a estrutura de /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
}
}
]
}Lê DXF, otimiza e devolve um plano PDF, uma página por painel, por URL assinado.
{
"files": [
{
"name": "layout-1708433600000.pdf",
"url": "https://storage.example.com/pdf/1708433600000/layout-1708433600000.pdf"
}
]
}Lê DXF, otimiza e devolve um SVG por painel por URLs assinados.
{
"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"
}
]
}Lê DXF, otimiza e devolve uma disposição DXF por painel por URLs assinados.
{
"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"
}
]
}Lê DXF, otimiza e devolve uma única lista de corte CSV por URL assinado.
{
"files": [
{
"name": "layout-1708433600000.csv",
"url": "https://storage.example.com/csv/1708433600000/layout-1708433600000.csv"
}
]
}A exportação PTX está em fase beta e ainda não foi validada em máquinas reais. Verifique os ficheiros exportados na sua máquina antes de os utilizar em produção.
Lê DXF, otimiza e devolve ficheiros PTX para serras HOLZMA / HOMAG por URLs assinados.
{
"files": [
{
"name": "J1708433600000.PTX",
"url": "https://storage.example.com/ptx/1708433600000/J1708433600000.PTX"
}
]
}Pré-validação CNC
Antes do fabrico, o pré-validador CNC analisa um ficheiro DXF segundo os limites da máquina. Extrai contornos e operações interiores (furos, recortes, ranhuras) e deteta violações das regras geométricas.
PART_TOO_SMALLerroO retângulo delimitador é menor que part_min_width × part_min_height.PART_TOO_LARGEerroO retângulo delimitador excede part_max_width × part_max_height.OPERATION_OUTSIDE_PARTerroUm ou mais vértices de uma operação ficam fora da peça.OPERATION_INTERSECTS_EDGEerroAs arestas da operação cruzam o limite mesmo com vértices no interior.OPERATION_TOO_CLOSE_TO_EDGEerro / avisoA distância à borda é menor que min_edge_offset. Erro se < ½ limite; aviso se < limite.DRILL_DIAMETER_TOO_SMALLerroO diâmetro do furo é menor que drill_min_diameter.DRILL_DIAMETER_TOO_LARGEerroO diâmetro do furo excede drill_max_diameter.OPERATIONS_INTERSECTerroDuas operações na mesma face sobrepõem-se.OPERATIONS_TOO_CLOSEerro / avisoA distância entre superfícies de operações é menor que min_op_spacing. Erro se < ½ limite; aviso se < limite.Envie DXF como multipart/form-data. A resposta é um ValidationReport completo: um PartResult por peça com operações e violações.
Campos do pedido (multipart)
fileobrigatório—Bytes DXF. São suportadas quase todas as revisões binárias R12–2018.configopcionalvalores predefinidosObjeto ValidationConfig em JSON (tabela abaixo). Todos os campos são opcionais; os omitidos usam o valor predefinido.Campos de ValidationConfig
part_min_widthopcional50Largura mínima permitida da peça em mm.part_min_heightopcional50Altura mínima permitida da peça em mm.part_max_widthopcional2800Largura máxima permitida da peça em mm.part_max_heightopcional2070Altura máxima permitida da peça em mm.drill_min_diameteropcional2Diâmetro mínimo da broca em mm.drill_max_diameteropcional35Diâmetro máximo da broca em mm.min_edge_offsetopcional8Distância mínima (mm) de uma aresta de operação ao limite da peça.min_op_spacingopcional8Distância mínima entre superfícies de duas operações em mm.groove_aspect_ratioopcional3.0Um contorno interior fechado é uma ranhura, e não um recorte genérico, se o lado longo ≥ esta proporção × o lado curto.unitopcional"mm""cm"Exemplo de pedido (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"}'Exemplo de resposta
{
"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
}
]
}Principais campos da resposta:
valid—truesó se nenhuma peça tiver problemas de gravidade erro.summary— totais:total_parts,total_operations,errors,warnings.parts[]— um objeto por peça detetada com retângulo delimitador, operações e problemas.issues[].severity—"error"(bloqueante) ou"warning"(apenas informativo).
Predefinições CNC
Guarde predefinições ValidationConfig com nome para validações futuras. São privadas da sua conta.
Devolve todas as predefinições do utilizador 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"
}
]
}Cria uma predefinição com nome. Devolve 201 Created com a 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"
}Substitui nome e/ou configuração. O corpo tem a estrutura de POST. Devolve 200 OK com a entrada atualizada ou 404 se o ID não existe ou pertence a outro utilizador.
Elimina a predefinição permanentemente. Devolve 204 No Content se bem-sucedido ou 404 se não existe.
Respostas de erro
Todos os endpoints devolvem erros no mesmo invólucro JSON:
{ "message": "A part (800×600) does not fit any stock plate" }400— limite de peças excedido: a soma dequantitysupera o limite por pedido do plano. Também indica CSV inválido ou campo multipart ausente.401— token Bearer ausente, expirado ou revogado.422— uma peça não cabe em nenhum painel ou faltam painéis. A otimização é completa ou falha; nunca devolve disposição parcial. A mensagem identifica peça ou restrição. PTX também devolve 422 se a disposição não puder ser serrada.429— limite diário atingido. Reinicia à meia-noite UTC.500— erro interno do servidor, como falha no envio do ficheiro.