Saltar al contenido principal
En esta página▾

Engine API

Si solo cortas paneles, no necesitas esta página. El optimizador dentro de CutOptim ya hace todo lo que se describe aquí. La Engine API es el mismo motor sin ninguna pantalla acoplada, para cuando otro software necesita planes de corte sin que una persona abra la aplicación.

Todo lo que CutOptim hace en tu navegador parte de un mismo cálculo: dadas estas piezas y este material, ¿cuál es la mejor forma de cortarlas? La Engine API expone exactamente ese cálculo a través de internet, para que un programa distinto pueda plantear la pregunta y recibir la respuesta — sin navegador, sin clics, sin nadie con la sesión iniciada.

Esa es toda la idea. No es un optimizador nuevo, ni un optimizador mejor, ni un plan más grande. Es el mismo motor, accesible para el software en lugar de para una persona.


¿Esto es para mí?

Para la inmensa mayoría de los usuarios de CutOptim, la respuesta honesta es no. Si tu jornada de trabajo consiste en abrir CutOptim, introducir piezas y material, e imprimir o exportar el plan, la aplicación es el producto y esta página es irrelevante para ti.

La Engine API es para una situación: los planes de corte necesitan aparecer dentro de un software que ya usas, sin que nadie visite CutOptim. En la práctica eso significa una de dos personas:

  • Ya usas un software dentro del cual pertenece el plan de corte. Un ERP que guarda tus pedidos, una herramienta de presupuestos que fija precios a los trabajos, o el propio software de una máquina. En lugar de que un operario vuelva a teclear la misma lista de piezas en CutOptim, ese programa consulta el motor directamente y muestra el plan allí donde ya ocurre el trabajo.
  • Estás encargando que te construyan un software. Un desarrollador interno, una empresa de software local o el proveedor de tu máquina. La Engine API es aquello a lo que ellos se conectan.

Usar la Engine API implica que alguien escribe software contra ella. No hay interfaz, ni hoja de cálculo que rellenar ni nada que instalar — es un servicio para programas, y el trabajo lo hace quien escribe ese programa. Si nadie de tu parte va a programar, la aplicación es lo que quieres.

Si no tienes claro en qué lado de esa línea estás, una buena prueba: ¿podría aparecer el plan sin que nadie lo pida? Si es así, la API es relevante. Si siempre hay una persona que decide crear un plan de corte, la aplicación ya es la herramienta adecuada.


Qué hace

Tu software envía las mismas dos cosas que teclearías en la aplicación — una lista de piezas y una lista de material — en formato JSON. El motor devuelve una respuesta completa:

  • El plano completo. Cada pieza, colocada en un tablero o barra concretos, incluido si se giró.
  • Un plan de corte. No solo un dibujo de rectángulos: la secuencia real de cortes de guillotina, en orden, para que el plan pueda ejecutarse en una seccionadora.
  • Los números. Cuántos tableros o barras requiere el trabajo, el porcentaje de aprovechamiento, cuántos cortes hacen falta y el precio total del material utilizado. Para paneles también obtienes los dos recuentos honestos de cortes — líneas de corte, que fusiona los cortes que comparten un mismo ajuste de tope, y pasadas de sierra, que cuenta cada pasada — además de la longitud total serrada.
  • Opcionalmente, el dibujo. Pide include: ["svg","csv","dxf"] y la respuesta también lleva la distribución como un archivo listo para usar — un dibujo SVG 2D autónomo, un DXF R12/AC1009 o una lista de corte CSV — en línea en el JSON, sin almacenamiento y sin una segunda llamada. (SVG es solo 2D.) En las solicitudes 2D también puedes pedir labels (datos de etiqueta por pieza), planHash (una huella del plan), pdf (el PDF del plan de corte) y labelsPdf (el PDF de etiquetas): los PDF en base64, dibujados con el mismo código que la app.
  • Tus propios identificadores, devueltos. Adjunta un objeto meta — un número de artículo, una línea de pedido, una referencia de cliente — a cualquier pieza o fila de material, y vuelve sin cambios en cada pieza colocada y cada tablero o barra, para que el plan cuadre con tu propio sistema. Este es el campo que debes usar cuando quieras enviar todos tus tableros, etiquetar cada uno con tu propio código y leer de vuelta qué tablero eligió el optimizador: pon el código en stock[].meta y vuelve reflejado en sheets[].meta. Nunca afecta a la colocación. No uses el campo material para identificar: material es una partición estricta (una pieza solo se corta a partir de material del mismo tipo), así que etiquetar cada fila de material con un material y dejar las piezas sin etiquetar hace que todas las piezas vuelvan como unmatched y el resultado quede vacío.

Hay cuatro modos de optimización, todos correspondientes a la aplicación — uno para paneles 2D, uno para material lineal 1D como barras, perfiles y tubo, uno para madera, donde el material tiene una sección, y el anidado por forma real (POST /v1/optimize/nest), que encaja polígonos arbitrarios para corte por láser, plasma y chorro de agua (el modo Nesting de la aplicación). Cada endpoint de optimización tiene además un endpoint de validación gratuito que comprueba una solicitud sin resolverla (ver más abajo).

Endpoints

La URL base es https://api.cutoptim.com. Los endpoints de optimización y de uso llevan una clave en una cabecera Authorization: Bearer <key>; los endpoints de validación y de disponibilidad no necesitan clave.

Endpoint Qué hace
POST /v1/optimize/2d Optimización de paneles 2D
POST /v1/optimize/1d Optimización 1D / lineal — barras, perfiles, tubo
POST /v1/optimize/wood Optimización de madera — 1D con coincidencia de sección
POST /v1/optimize/nest Anidado de forma real — polígonos irregulares para láser, plasma y chorro de agua
POST /v1/validate/2d · /1d · /wood · /nest Validar una solicitud sin resolver — gratis, sin clave, sin cuota
GET /v1/jobs/{id} Sondear un trabajo asíncrono del motor max — solo tus propios trabajos, sin cuota
POST /v1/import/nest Lee los contornos de las piezas de un archivo SVG o DXF — requiere clave, no consume cuota
GET /v1/usage El uso y la cuota de la CUENTA para el mes en curso (todas las claves comparten una)
GET /v1/health Comprobación de disponibilidad — no necesita clave

La mayoría de las llamadas se responden directamente con el resultado terminado. La única excepción es el motor asíncrono max (ver Tres motores más abajo): un envío max devuelve un id de trabajo, y sondeas GET /v1/jobs/{id} hasta que el plan esté listo.

Los endpoints de validación toman el mismo cuerpo que el endpoint de optimización correspondiente y lo comprueban sin ejecutar el cálculo: una solicitud mal formada vuelve como un 400 que nombra el campo exacto que falla, y una bien formada devuelve valid: true más avisos de viabilidad (por ejemplo, una pieza que no cabe en ningún material). No cuestan nada y no necesitan clave, así que puedes validar tus cargas útiles mientras construyes la integración — antes incluso de tener una clave — y confirmar que una solicitud no será rechazada sin gastar una de tus llamadas mensuales.

Dirección de la veta en paneles

El contrachapado y los tableros chapados tienen veta, y una pieza vista debe cortarse con la veta en el sentido correcto. En POST /v1/optimize/2d, envía grain en una fila de material ("w" o "h", el lado del tablero a lo largo del cual corre la veta) y grain en una pieza (el lado de la pieza a lo largo del cual debe correr). Cada una de esas piezas se coloca con su veta a lo largo de la de su tablero: girada 90° cuando es lo que hace falta (rotated: true en la colocación, como en cualquier giro), y rotatable se ignora para ella. Una pieza sin grain sigue girando libremente, también en una fila de material sin grain (MDF, melamina); una pieza CON grain mantiene también en esa fila la orientación que le dan las filas con veta — material separa los tableros con veta de los lisos. Una pieza que solo cabría girada 90° contra la veta aparece en unplaced con el tamaño enviado, una línea de warnings la nombra y POST /v1/validate/2d lo avisa antes de gastar una llamada.

En una misma solicitud pueden convivir filas de material cuya veta corre en direcciones distintas (un 2440 × 1220 con "w" y un 1220 × 2440 con "h"), y cada tablero vuelve en la orientación de su propia fila, con grain devuelto en sheets[]. Con material, una pieza solo queda sujeta a una veta cuando su propio material tiene un tablero con veta. Si la solicitud no incluye ningún material con veta, el grain de una pieza no tiene efecto, y una línea en warnings lo indica. options.trim y un options.firstCut forzado se aplican a cada tablero en la orientación de su propia fila, también en una fila cuya veta corre en el otro sentido. El modo Dirección de la veta de la app de CutOptim ejecuta el mismo código. (Desde el 2 de octubre de 2026.)

Coincidencia de veta en paneles (conjuntos)

La dirección de veta mantiene la veta de cada pieza en el sentido correcto. Algunos frentes necesitan más: un frente de cajón sobre dos puertas cuyo dibujo continúe de uno a otro, como si las tres piezas siguieran siendo un mismo tablero. En POST /v1/optimize/2d, da un id a esas filas de piezas y nómbralas en matchedSets:

{
  "parts": [
    { "id": "DF", "name": "Drawer front", "w": 48.125, "h": 6 },
    { "id": "DOOR", "name": "Door", "w": 24, "h": 30, "qty": 2 },
    { "name": "Shelf", "w": 22.5, "h": 11.25, "qty": 4 }
  ],
  "stock": [{ "w": 96, "h": 48, "qty": 2, "grain": "w" }],
  "options": { "kerf": 0.125 },
  "matchedSets": [
    { "id": "base-1", "name": "Base cabinet fronts", "grain": "w",
      "layout": { "dir": "rows", "lines": [["DF"], ["DOOR", "DOOR"]] } }
  ]
}
  • Qué es un conjunto. layout.lines enumera los miembros por parts[].id. Con dir: "rows" cada línea es una fila de miembros uno junto a otro y las filas se apilan de arriba abajo, así que [["DF"], ["DOOR", "DOOR"]] es un frente de cajón sobre dos puertas; con "cols" cada línea es una columna y las columnas van una junto a otra. Una pieza puede aparecer más de una vez en un mismo conjunto (Door, Door), pero solo puede pertenecer a un conjunto. qty (por defecto 1) es cuántas instancias necesitas —tres muebles iguales son qty: 3— y el qty propio de las piezas debe cubrir todas las instancias. Un conjunto tiene al menos 2 y como máximo 24 miembros, y una solicitud admite como máximo 50 conjuntos.
  • Cómo se corta. El conjunto pasa por el optimizador como un solo rectángulo —el bloque— y vuelve como sus miembros, separados exactamente por un kerf, de una misma pieza de tablero. El grain del conjunto ("w" o "h", a lo largo del ancho o del alto del bloque) decide la dirección de todos los miembros; el grain propio de un miembro no se usa dentro del conjunto, y un warning nombra a cualquier miembro al que sustituye. Sin grain en el conjunto, el bloque puede girar cuando todos los miembros son rotatable. installGap es la holgura entre los miembros en el mueble (por defecto: el kerf); en el tablero siguen separados por un kerf.
  • Qué devuelve. Cada miembro colocado lleva matchedSet: el id del conjunto, qué instance y su position en orden de lectura en el frente del mueble —de arriba abajo y de izquierda a derecha, desde 1—, más un hint como "left" o "right" cuando no hay ambigüedad. La respuesta añade un resumen matchedSets, una entrada por conjunto: su letter (A, B … en el orden de la solicitud), cuántas instancias se cortaron como un bloque (asBlock), divididas o sin colocar, el tamaño del bloque y los warnings del conjunto. Cuando un bloque no cabe en ningún tablero, onMiss: "split" (el valor por defecto) coloca los miembros uno a uno con un warning, y onMiss: "unplaced" los enumera en unplaced.
  • Avisos, no errores. Una medida que no cuadra es un aviso del conjunto, no un rechazo. Cada línea empieza con su código —align: (las líneas no quedan enrasadas), gap: (el kerf es más ancho que installGap), grain:, split:, unplaced:, unmatched: (no hay stock del material del conjunto), priority: y grainGroup:—, y align y gap se juzgan a 1/64 de tu unidad o un cuarto de kerf, lo que sea menor. Un conjunto que no puede disponerse en absoluto —un id de miembro que ninguna pieza lleva, un id referenciado en dos piezas, menos de dos miembros, demasiadas pocas piezas para qty— es un 400 que nombra el campo exacto, antes de que se cobre una llamada.
  • parts[].id es seguro de enviar. Solo se comprueba un id al que se refiere un conjunto (una cadena imprimible no vacía de como máximo 64 caracteres, o un entero, en exactamente una pieza). Cualquier otro id se ignora, sea cual sea su contenido, así que tus números de artículo del ERP pueden quedarse en las filas. Y no cambia nada para una solicitud sin conjuntos: solo un array matchedSets no vacío activa la función —ausente, null, [] o cualquier valor que no sea un array se responde exactamente como antes—.
  • Exportaciones. Con conjuntos, csv gana las columnas Set y Position al final, svg imprime el código de posición (A1, A2 …) en las etiquetas de las piezas y dibuja el marco de cada conjunto en un grupo matched-sets aparte —options.setOutlines: false omite ese grupo—, y dxf lleva el código de posición en la capa LABELS. pdf y labelsPdf no marcan los conjuntos: dibujan los miembros como piezas normales, y warnings lo dice; las marcas del conjunto están en sheets[].parts[].matchedSet, csv y svg.
  • Motores y endpoints. Los motores heuristic y balanced disponen conjuntos (balanced no ordena por priority, así que con respectStock un conjunto puede perder su sitio allí, con un warning priority:). El motor max rechaza un matchedSets no vacío con un 400 cuyo details.unsupported lo nombra, antes de que se cobre una llamada; uno vacío es un trabajo max ordinario. matchedSets y parts[].id son solo 2D: los endpoints 1D, wood y nest los ignoran.
  • grainGroup está obsoleto. Se sigue aceptando y funciona exactamente como antes: las piezas que comparten un grupo se mantienen en un mismo tablero. Nunca las colocó una junto a otra, así que no da una veta continua entre ellas; para eso, usa matchedSets.

La función Coincidencia de veta de la app de CutOptim dispone los conjuntos con el mismo núcleo.

Por qué la madera tiene su propio endpoint

El material lineal conoce una sola dimensión, su longitud, así que cualquier barra puede servir para cualquier pieza. La madera no funciona así: una pieza de 50×150 no puede salir de una barra de 50×100, por mucha longitud que le quede. Por eso el endpoint de madera toma los dos lados de la sección en cada pieza y cada fila de material, divide el trabajo por sección, empareja cada sección con su propio material y devuelve las secciones por separado — cada una con sus propias barras y sus propios totales, junto a las cifras del trabajo completo.

Dos detalles que conviene conocer antes de integrarlo:

  • Los dos lados de la sección pueden enviarse en cualquier orden. 50×100 y 100×50 son la misma barra girada, así que se emparejan como una sola sección. Eso significa que una diferencia en cómo se hayan introducido tus datos no puede hacer que desaparezca material.
  • “No hay material de esta sección” y “no cupo” se informan por separado. Lo primero es un aviso de material faltante, lo segundo es un problema de capacidad, y tienen soluciones distintas — así que mezclarlos en una sola lista haría que tu usuario buscara en el sitio equivocado.

Podrías aproximar esto con varias llamadas 1d propias, agrupando tú mismo las piezas. Costaría una petición de tu cuota por sección en lugar de una por trabajo, dejaría la coincidencia de material en tu código y produciría un total del trabajo que tendrías que ensamblar tú mismo — uno que no coincidiría necesariamente con lo que la aplicación de CutOptim muestra para el mismo trabajo.


Piezas desde un archivo CAD

El endpoint de nesting no acepta solo coordenadas. Una pieza puede llevar en su lugar un source — un documento SVG o DXF — y el servidor extrae de él su contorno y los agujeros que contenga. Es el mismo lector que usa la app cuando sueltas un dibujo sobre su modo Nesting, así que una biblioteca de piezas que ya existe como archivos CAD no hay que reescribirla antes en listas de coordenadas.

El archivo sustituye solo la geometría. Cantidad, material, rotaciones permitidas y tus propios metadatos siguen siendo campos normales de la fila de la pieza, igual que cuando envías coordenadas. Un archivo describe una pieza; cuando un mismo dibujo contiene varios componentes separados, POST /v1/import/nest lo divide antes en filas listas para usar — y esa llamada requiere una clave pero no consume una solicitud de tu cuota mensual.

No se almacena nada. El archivo existe únicamente como la propia solicitud: se lee en memoria y desaparece en el momento en que se escribe la respuesta. No queda copia en disco ni en una base de datos, nada acaba en un registro y después no hay nada que borrar. Con las unidades hacemos lo mismo — un DXF puede declarar milímetros o pulgadas y nosotros informamos de lo que dijo, pero las coordenadas nunca se convierten, porque ningún valor de esta API lleva unidad.

La misma respuesta cada vez

El motor es determinista: la misma entrada siempre produce la misma salida. No hay aleatoriedad ni reloj dentro del algoritmo.

Esto suena académico pero es la razón práctica para construir sobre él. Significa que los resultados pueden cachearse — si ya preguntaste por este mismo trabajo exacto, puedes reutilizar la respuesta con seguridad en lugar de preguntar de nuevo. También significa que la integración puede probarse: un plan puede compararse con un resultado conocido como bueno, y una diferencia es una diferencia real, no ruido. Un software que le da un precio a un cliente el lunes le dará el mismo precio el viernes.

Hay una excepción opcional, y lo indica: el motor max de anidado (más abajo) dedica un presupuesto de tiempo fijo a buscar, así que hasta dónde llega depende de cuánto trabajo entre en ese tiempo. Sus respuestas llevan deterministic: false. Todos los demás motores — incluido el predeterminado de anidado, lbf — son deterministas.

Reintentar con seguridad. Si se corta la conexión, no sabe si la solicitud llegó. Envíe una cabecera Idempotency-Key —un valor que usted elige para cada trabajo— y reintente con la misma clave: durante 24 horas, la misma solicitud devuelve la respuesta guardada, marcada con Idempotency-Replayed: true, y no se cobra otra vez. Un trabajo max tampoco se encola dos veces. La clave demo pública ignora esta cabecera. (Desde 2026-10-15.)

Webhooks para trabajos asíncronos. En lugar de consultar GET /v1/jobs/{id}, registre un endpoint (una URL https://) en su panel y reciba un POST firmado — job.succeeded o job.failed — cuando termine un trabajo max asíncrono. Compruebe la cabecera CutOptim-Signature con el secreto recibido, responda en 10 segundos y lea el plan con GET /v1/jobs/{id}. Una entrega fallida se reintenta: 8 intentos en 24 horas. (Desde 2026-10-19.)

SDK oficiales. Clientes de código abierto para TypeScript, Python y PHP — npm install @cutoptim/engine, pip install cutoptim, composer require cutoptim/engine — con peticiones tipadas, reintentos que nunca se cobran dos veces (cada llamada lleva un Idempotency-Key), una ayuda para esperar los trabajos asíncronos y verificación de webhooks. Código en GitHub; detalles en la guía de SDK (en inglés).

Servidor MCP para asistentes de IA. Claude Code, Cursor, VS Code y Claude Desktop pueden llamar al motor como herramientas a través del servidor Model Context Protocol alojado en https://api.cutoptim.com/mcp, con la misma clave de API (Authorization: Bearer …) y la misma cuota: una llamada a una herramienta es una llamada a la API, y las herramientas validate_* son gratuitas. También se ejecuta en local con el paquete npx -y @cutoptim/mcp (clave en CUTOPTIM_API_KEY), y el MCP Registry oficial lo lista como io.github.cutoptim/engine. Las configuraciones de cada cliente están en la guía MCP (en inglés).


Tres motores

La API ofrece a elegir entre motores. Los dos primeros se ejecutan de forma síncrona; el tercero es asíncrono. La diferencia no es de calidad — es un compromiso entre velocidad, si el resultado puede cortarse en una seccionadora y cuánto se acerca al mínimo teórico.

  • heuristic es el predeterminado y el mismo que usa la aplicación. Produce planos de guillotina: mayor aprovechamiento, todos los planos cortables en una seccionadora, y siempre un plan de corte completo. Síncrono.
  • balanced es opcional. Usa anidado libre en su lugar, que es drásticamente más rápido en trabajos muy grandes — medido en aproximadamente 25× más rápido en un trabajo de 2.000 piezas — a costa de un aprovechamiento algo menor. La pega importante: sus planos a menudo no pueden cortarse de borde a borde, así que para esos no devuelve ningún plan de corte. Síncrono.
  • max es opcional, para paneles 2D (y, por separado, para el anidado de forma real — ver más abajo). En 2D es una búsqueda en árbol del lado del servidor que alcanza el óptimo probado en muchos más trabajos que el predeterminado, y sus planos siguen siendo cortables con guillotina. El coste es tiempo: un cálculo max tarda de segundos a un minuto, así que no responde en la propia respuesta. En su lugar, POST /v1/optimize/2d con engine: "max" devuelve un id de trabajo, y sondeas GET /v1/jobs/{id} hasta que esté listo. Sigue siendo determinista. Recurre a él cuando un trabajo grande y valioso merezca la espera por los últimos tableros. Modela un solo formato de stock a tamaño completo de tablero, con disponibilidad ilimitada, así que una solicitud que además lleve un segundo formato de stock, trim por lado, stock limitado (respectStock), materiales, grupos de veta o un matchedSets no vacío se rechaza de antemano con un 400 que nombra exactamente lo que no puede hacer — antes de que se cobre una llamada. Envía esos trabajos a heuristic, que los modela todos.

Anidado: lbf y max

El anidado de forma real tiene sus propios dos motores. lbf es el predeterminado: instantáneo, síncrono y determinista. max es opcional y asíncrono, exactamente igual que el max de 2D — POST /v1/optimize/nest con engine: "max" devuelve un id de trabajo, y sondeas GET /v1/jobs/{id}.

El max de anidado ejecuta primero la pasada de lbf, así que siempre tiene una respuesta válida en la mano. Luego dedica un presupuesto de tiempo (options.timeBudgetMs, 60 segundos por defecto, entre 10 y 180) a buscar una distribución con menos tableros, llenando un tablero cada vez. Nunca devuelve más tableros que lbf: cuando la búsqueda no encuentra ninguna mejora, obtienes la distribución de lbf y un aviso que lo dice. Como la búsqueda tiene un tiempo limitado, sus respuestas llevan deterministic: false. Acepta varios tamaños de tablero por material y respectStock, y clasifica su resultado con la misma regla que lbf (más abajo): sustituye el plan de lbf solo cuando es mejor — nunca solo porque tenga menos tableros. Un tablero poligonal o las zonas de exclusión, que su búsqueda por bandas no puede modelar, los sirve la pasada de lbf dentro del trabajo, con un aviso — nunca se rechazan. El nombre antiguo sparrow se acepta como alias de max.

Las piezas rectangulares obtienen una cuadrícula exacta (desde el 2026-09-28). lbf encuentra las posiciones por muestreo, y eso casi nunca da con una cuadrícula sin holgura: tres piezas de 500 mm a lo ancho de un tablero de 1500 mm con espaciado cero encajan exactamente, y una búsqueda por muestreo coloca dos. Por eso los dos motores prueban también dos alternativas y se quedan con la que mejor clasifica según la misma regla: las piezas restringidas a los ángulos rectos que permiten, y los rectángulos envolventes de las piezas colocados por un empaquetador exacto de rectángulos (rectángulos que no se solapan no pueden contener piezas que se solapen, así que es válido para cualquier contorno). En caso de empate — mismos tableros, misma área de tablero — gana el plan que llena sus tableros en orden, del primero al último, y después el que tiene menos piezas giradas fuera de los ángulos rectos. No hay nada que activar, y por esa clasificación un resultado solo puede mejorar; un plan que los rectángulos llevan al menor número de tableros que permite el área de las piezas hace además que max responda al instante en lugar de seguir buscando.

Un trabajo de unas pocas docenas de piezas suele necesitar unos 15 segundos de presupuesto (timeBudgetMs: 15000); el trabajo termina aproximadamente entre uno y dos segundos después del presupuesto, más el tiempo que pase en la cola. Sondea GET /v1/jobs/{id} cada dos o tres segundos — sondear no cuesta cuota. Ningún presupuesto puede prometer un número de tableros concreto.

Anidado: margen en el borde, tamaños de tablero y lo que costó cada tablero

  • Margen en el borde. options.minSeparation es el espaciado entre piezas, y por sí solo también se aplica en el borde del tablero. options.edgeClearance fija el borde por separado — por ejemplo 5 entre piezas y 0 o 10 en el borde. Si lo omites, el borde conserva minSeparation, exactamente como antes. Funciona en los dos motores, necesita tableros rectangulares (w y h), y las zonas de exclusión conservan minSeparation igual que las piezas. Un tablero poligonal, o un valor que no deje espacio en el tablero, se rechaza con un 400 antes de que se cobre una llamada.
  • Elegir un tamaño de tablero. Cuando un material tiene dos o más filas de material, lbf las prueba en tu orden, cada tamaño por su cuenta y en un orden de más barato primero, y se queda con la mejor — así el resultado deja de depender del orden en que listes las filas. La clasificación es: el mayor número de piezas de corte obligatorio colocadas (ver más abajo), luego más piezas colocadas, luego la menor área total de tablero (material), luego el menor número de tableros. Con options.minimizeCost clasifica por precio total en su lugar (price, o cost para una fila sin precio) — pero solo cuando todas las filas de ese material llevan uno; si no, recae en el área y lo indica en warnings.
  • Mezclar tamaños. Después, cada tablero — empezando por el menos lleno — se vuelve a anidar por su cuenta sobre las filas más baratas o más pequeñas, y se sustituye cuando el plan completo clasifica mejor. Así los tamaños pueden mezclarse dentro de un mismo material: normalmente dos tableros grandes y uno más pequeño al final, donde el último tablero, ahora medio vacío, antes era uno grande. Con options.respectStock, ninguna fila se usa más veces que su qty. El motor max aplica la misma clasificación.
  • Piezas de corte obligatorio. parts[].priority: true marca una pieza que debe cortarse sí o sí. Importa con options.respectStock — un suministro limitado, donde no todas las piezas pueden caber: las piezas de corte obligatorio se colocan entonces primero, así que una pieza normal nunca ocupa el espacio de tablero que necesita una pieza de corte obligatorio, y cada clasificación anterior prioriza el plan que conserva más de ellas, incluso si coloca menos piezas en total. Los dos motores lo respetan (max conserva la distribución de lbf siempre que algo quede sin colocar). Sin respectStock, todas las piezas que caben se colocan de todos modos, así que la marca no cambia nada. Una pieza de corte obligatorio que no cabe en ningún tablero sigue apareciendo en unplaced. (Desde el 22 de septiembre de 2026 — antes, el motor de anidado aceptaba el campo pero lo ignoraba.)
  • Un stock limitado en el que no cabe todo. Con options.respectStock, cuando el plan aún deja piezas sin colocar, el motor además llena las hojas una a una con los rectángulos envolventes de las piezas — cada una lo más llena posible, y una pieza que solo cabe en un tamaño de hoja va allí primero (un lateral alto en la única hoja grande, no en una tira de retal). Ese plan solo se adopta si coloca más piezas (primero las obligatorias) o usa menos material; un trabajo en el que cabe todo vuelve exactamente como antes. Respeta las rotaciones permitidas de cada pieza, minSeparation y edgeClearance. (Desde el 2026-10-14.)
  • Lo que costó cada tablero. Cada tablero lleva stock — el índice de la fila de material de la solicitud desde la que se cortó — y la respuesta añade stockUsage: una entrada por cada fila de material usada, con su número de tableros, precio total y densidad. La unidad es la fila de material, no el tamaño: dos filas con las mismas dimensiones pero un precio o meta distinto son dos entradas.
  • Longitud de corte y perforaciones. Cada tablero lleva cutLength — el perímetro sumado de los contornos de sus piezas colocadas y sus agujeros, en tu unidad — y pierces, uno por cada contorno cerrado; metrics totaliza ambos. Es la longitud geométrica del contorno: sin corte por línea común, entradas de corte ni microuniones — tu CAM las añade.
  • Área usada, para facturar por tablero parcial. Cada tablero lleva usedWidth y usedHeight — el punto más lejano al que llega cualquier pieza colocada desde la esquina de origen del tablero, en tu unidad, sobre el tablero real (con edgeClearance se incluye el margen al borde) — y usedArea, su producto; stockUsage[].usedArea lo totaliza por fila de material. Eso es lo que necesita un ERP para cobrar un corte horizontal (usedHeight × ancho del tablero), uno vertical (usedWidth × alto del tablero) o la caja envolvente (usedArea) en lugar del tablero completo — la regla de facturación sigue siendo tuya. Para que esos números sean pequeños, los dos motores compactan por defecto el tablero menos lleno de cada material: sus piezas se vuelven a anidar sobre el mismo tablero con subconjuntos de rotación de lo que cada pieza permite — 0/180, 0/90/180/270 y una sola orientación para todas las copias, intersectado con un allowedRotations discreto, nunca un ángulo nuevo — y se conserva la disposición con la menor área usada. Con engine: "max", ese tablero lo vuelve a colocar después también la propia búsqueda — a lo largo de la altura del tablero y, si el plan tiene un solo tablero, también a lo largo de su anchura — y se conserva, con la misma regla, la disposición más ajustada. El número de tableros, los tamaños, el precio y las piezas colocadas nunca cambian; options.compact: false devuelve la disposición sin compactar. Si facturas una franja en vez de la caja envolvente, fija options.compactFor según corresponda: "horizontal" conserva la disposición con la menor usedHeight (una franja que cruza todo el ancho del tablero), "vertical" la de menor usedWidth (una franja que cruza todo el alto del tablero); el valor por defecto "box" conserva la menor usedArea. Los modos de franja también prueban cada copia girada un cuarto de vuelta (90° o 270°) donde allowedRotations lo permita. Lo pequeña que llegue a ser el área usada depende de las piezas. (Desde el 22 de septiembre de 2026.)

balanced no significa “mejores resultados”. Es más rápido y aprovecha algo menos, y cuando su plano no es cortable con guillotina no hay ningún plan de corte que entregar a un operario de sierra. Elígelo solo cuando la velocidad en un trabajo muy grande importe más que un plan listo para la sierra. Si tienes dudas, quédate con el predeterminado.


Límites

Cada petición está acotada, para que un trabajo desbocado falle con claridad en lugar de quedarse colgado:

Límite Valor
Piezas por petición 2.000
Filas de material por petición 50
Tamaño del cuerpo de la petición 1 MB
Tamaño del cuerpo de la solicitud — rutas nest que pueden llevar un dibujo 10 MB
Claves activas por cuenta 10
Llamadas validate sin clave por dirección 120 / minuto
Claves API desconocidas por dirección 30 / minuto — después 429 durante el resto del minuto
Espera por un hueco de cálculo libre (rutas síncronas) unos 8 s — después 429, sin cargo
Trabajos max en queued/running por cuenta 5
Presupuesto de búsqueda del motor max de anidado por trabajo 10–180 s (60 s por defecto)
Conservación de Idempotency-Key 24 horas
Endpoints de webhook por cuenta 5
Intentos de entrega de webhook 8 en 24 horas

Obtener acceso

Empieza en la página de la Engine API. La Engine API se factura por separado de los planes de la aplicación, y ninguna mejora de plan la activa.

  1. Pruébala, luego suscríbete — o pregunta. Puedes llamar a la API antes de pagar: los botones Ejecutar este ejemplo de la referencia de la API usan una clave de demostración pública, y cualquier cuenta con la sesión iniciada puede crear claves de prueba gratuitas en el panel (su propio cupo mensual reducido, nunca se facturan, sin suscripción). Cuando estés listo, suscribirte en la página de la Engine API es la vía más rápida — el plan de entrada, Studio, empieza con una prueba gratuita, y el acceso llega a tu cuenta por sí solo. Si prefieres describir primero tu integración, o necesitas un volumen por encima del plan estándar, ponte en contacto en su lugar y di qué quieres conectar y aproximadamente cuántos planes de corte al mes necesitará.
  2. El acceso aparece en tu cuenta. Nada más de tu cuenta cambia.
  3. Crea una clave. La tarjeta de claves de API está en tu panel para toda cuenta con la sesión iniciada: sin suscripción crea claves de prueba, con acceso a la API también claves live. Tú mismo creas, nombras y eliminas claves ahí.
  4. Copia la clave de inmediato. La clave completa se muestra exactamente una vez, en el momento en que la creas.

Una clave se muestra solo una vez. CutOptim almacena únicamente un hash sha256 de ella, nunca la clave en sí — así que no puede volver a leerse después, ni por ti ni por nosotros. Cópiala directamente en la configuración de tu software cuando la crees. Si pierdes una clave, elimínala y crea una nueva; si una clave llega a quedar expuesta, elimínala y las llamadas dejan de funcionar de inmediato.

Trata una clave como una contraseña: pertenece a la configuración de tu software, no a un correo, una hoja de cálculo o una captura de pantalla.

Qué hace la tarjeta de claves de API de tu panel

Cuatro controles, y vale la pena ser preciso sobre qué cambia cada uno — especialmente el último, que la gente espera que toque la facturación y no lo hace.

  • Plan, Cambiar y Facturación. Muestra en qué plan está la cuenta (Studio o Scale). Cambiar a Scale (o Cambiar a Studio) cambia el plan tras una confirmación, y la cuota mensual de la cuenta cambia de inmediato. Facturación abre tu configuración de facturación, donde actualizas la tarjeta, ves las facturas o cancelas.
  • Crear clave. Genera una clave nueva y la muestra una vez, ahí mismo. Le pones un nombre (ERP integration, staging) únicamente para poder distinguir tus claves más adelante. Hasta 10 claves activas por cuenta. Las claves de prueba se crean igual y se cuentan aparte: tienen su propio cupo mensual reducido y nunca se facturan.
  • La barra de uso. Dos números: el total de tu cuenta para el mes natural frente a la cuota mensual, y por clave, cuánto ha gastado esa clave. La cifra por clave está para responder qué integración se está comiendo el cupo — no es un presupuesto aparte.
  • Revocar. Deja esa clave concreta sin funcionar, a partir de la siguiente llamada. La fila permanece visible para que no se pierda su historial.

Revocar una clave no tiene nada que ver con tu suscripción. No cancela nada, no reembolsa nada y no libera cuota — el plan sigue en marcha y el cupo sigue vigente, simplemente dejas de tener esa clave en particular. Revoca cuando una clave haya quedado expuesta o cuando se retire una integración. Para dejar de pagar, cancela la suscripción en su lugar; el acceso continúa entonces hasta el final del periodo que ya pagaste, y después de eso incluso las claves existentes dejan de funcionar.

Una cuota para la cuenta, no una por clave

Cada clave activa de tu cuenta consume del mismo cupo mensual. Crear una segunda clave no crea una segunda cuota — las claves existen para que puedas separar staging de producción, dar a cada integración su propia credencial y revocar una sin molestar a las demás.

GET /v1/usage informa de la posición de la cuenta (used, limit, remaining), de modo que responde a la pregunta que realmente tienes — cuánto queda antes de que las llamadas empiecen a fallar — con independencia de con qué clave preguntaste. Cuando se agota el cupo, todas las claves devuelven 402, no solo la que lo gastó.


Planes, precio y cuota

La Engine API se factura por separado de los planes de la aplicación, de forma mensual, en EUR, con dos planes:

Plan En qué se diferencian
Studio El plan de entrada, con una prueba gratuita
Scale Una cuota mensual de peticiones mayor, sin prueba — se llega a él cambiando desde Studio

Todo lo demás es igual en los dos: los mismos motores, los cuatro modos, todas las opciones, las mismas respuestas. Cada petición cuenta igual — un trabajo de anidado cuesta una petición, exactamente igual que uno de 2D o de 1D.

  • Tope estricto, sin excesos. Cuando se agota la cuota mensual, las llamadas devuelven 402 hasta que se restablece el primer día del mes siguiente. No hay factura sorpresa.
  • Dos correos, para que el tope no te sorprenda. Enviamos un correo a la cuenta al llegar al 90 % de la cuota y otro cuando se agota.
  • El cambio de plan es un solo botón en la tarjeta de claves de API de tu panel (Cambiar a Scale / Cambiar a Studio); la nueva cuota se aplica de inmediato. Una mejora se cobra al instante por el resto del periodo; una bajada no se reembolsa y el precio más bajo se aplica desde la próxima renovación. El cambio está disponible al terminar la prueba.
  • Los volúmenes mayores que el plan Scale se presupuestan de forma individual — ponte en contacto.

Los precios y cuotas actuales están indicados en la página de la Engine API — esa página los lee de nuestra configuración de precios, así que siempre es la cifra exacta.

Para el detalle técnico — la forma exacta de la petición y la respuesta, todas las opciones, todos los códigos de error y cómo funciona el versionado — consulta la referencia de la API.


Componentes de código abierto

Los motores de CutOptim se apoyan en bibliotecas de código abierto, usadas sin modificar en nuestros servidores:

  • jagua-rs — el motor geométrico de colisiones detrás del anidado de forma real (MPL-2.0).
  • sparrow — la búsqueda detrás del motor max de anidado (MIT, KU Leuven).
  • PackingSolver — la búsqueda en árbol detrás del motor max de 2D (MIT).

Todo lo demás que hay a su alrededor — la API, la correspondencia entre el contrato y estos motores, los empaquetadores rectangulares y la propia aplicación — es código propio de CutOptim.


Qué no cambia esto

Vale la pena decirlo con claridad, porque es fácil malinterpretar la Engine API como un cambio en el producto:

  • El optimizador de la aplicación no cambia. Sigue ejecutándose en tu navegador, exactamente igual que antes.
  • Gratis, Pro y Taller no se ven afectados. Siguen incluyendo el optimizador integrado, con los mismos límites que antes. Nada se movió detrás de la API.
  • Nada de lo que hagas en la aplicación consume peticiones de la API. La cuota mensual de la API solo se toca con las llamadas que hace tu propio software.

La Engine API es una adición para quienes integran CutOptim en otro software. Si ese no eres tú, nada ha cambiado.

FAQ

¿Qué diferencia hay entre los planes Studio y Scale?
Solo el número de solicitudes al mes y la prueba. Los dos planes ejecutan los mismos motores, los cuatro modos y todas las opciones, y cada solicitud cuenta igual — un trabajo de anidado cuesta una solicitud, exactamente igual que uno de 2D. Studio es el plan de entrada y incluye una prueba gratuita; Scale tiene una cuota mensual mayor y no tiene prueba, porque se llega a él cambiando desde Studio. Los precios y cuotas actuales están en la página de la Engine API.
¿Puedo cambiar entre Studio y Scale?
Sí, una vez terminada la prueba y cobrado el primer pago, con el botón Cambiar a Scale (o Cambiar a Studio) de la tarjeta de claves de API de tu panel. La nueva cuota mensual se aplica a tu cuenta de inmediato. Una mejora se cobra al instante por el resto del periodo de facturación; una bajada no se reembolsa y el precio más bajo se aplica desde la próxima renovación.
¿Puedo probar la API antes de pagar?
Sí, de dos maneras. La referencia de la API tiene botones Ejecutar este ejemplo que usan una clave de demostración pública, sin ninguna cuenta — solo trabajos pequeños. Y cualquier cuenta de CutOptim con la sesión iniciada puede crear claves de prueba en el panel: tienen su propio cupo mensual reducido, nunca se facturan y no necesitan suscripción, así que puedes construir toda la integración antes de comprar. Después, Studio empieza con una prueba gratuita.
¿Me avisarán antes de que se agote mi cuota mensual?
Sí. Enviamos un correo a la cuenta al llegar al 90 % de la cuota mensual y otro cuando se agota. Después, las llamadas devuelven 402 hasta que la cuota se restablece el primer día del mes siguiente — o de inmediato si cambias al plan mayor.
¿Necesito la Engine API?
Casi con toda seguridad, no. Si cortas paneles o barras abriendo CutOptim en tu navegador, la aplicación ya hace todo lo que hace la API — la API es el mismo motor sin ninguna pantalla acoplada. Existe para una sola situación: que otro software necesite planes de corte sin que una persona abra la aplicación. Si nadie va a programar contra CutOptim, puedes ignorarla.
¿Para quién es realmente la Engine API?
Para dos tipos de cliente: quien ya usa un software dentro del cual debería vivir el plan de corte — un ERP, una herramienta de presupuestos o de entrada de pedidos, el propio software de una máquina — y quien está encargando que le construyan ese software, mediante un desarrollador interno o una agencia. En ambos casos el trabajo lo hace quien escribe ese software, no tú desde la interfaz de CutOptim.
¿Cómo obtengo acceso a la Engine API?
Puedes suscribirte en la página de la Engine API — incluye un periodo de prueba, y el acceso llega a tu cuenta por sí solo en cuanto lo haces. Esa es la vía más rápida. Si prefieres describir primero tu integración, o necesitas un volumen por encima del plan estándar, ponte en contacto en su lugar. En cualquier caso, después tú mismo creas las claves live en la tarjeta de claves de API de tu panel. La Engine API se factura por separado de los planes de la aplicación y ninguna mejora de plan la activa.
¿La Engine API puede cortar madera, o solo paneles y barras?
Los cuatro modos que tiene la aplicación: tableros, barras, madera y nesting true-shape. El endpoint de madera tiene en cuenta la sección: tanto las piezas como el material llevan los dos lados de la sección, de modo que una pieza de 50×150 solo se corta a partir de material de 50×150. El trabajo se divide por sección y cada sección se devuelve con sus propias barras y totales, y la demanda cuya sección no tiene material alguno se informa por separado de las piezas que sí tenían material y no cupieron.
¿La Engine API cambia mi plan Gratis, Pro o Taller?
No. La Engine API es un complemento aparte y no cambia nada de los planes normales. El optimizador dentro de la aplicación no cambia, sigue ejecutándose en tu navegador, y sigue incluido en Gratis, Pro y Taller exactamente igual que antes. Nada de lo que hagas en la aplicación empieza a consumir peticiones de la API.
¿Hay un SDK o una biblioteca cliente para la Engine API?
Sí. Hay SDK oficiales de código abierto para TypeScript (npm @cutoptim/engine), Python (PyPI cutoptim) y PHP (Composer cutoptim/engine) — código en github.com/cutoptim, guía en /engine/reference/guides/sdks. Son opcionales: la API sigue siendo HTTPS puro con JSON, que cualquier lenguaje puede invocar sin un paquete de CutOptim. Para los trabajos asíncronos hay webhooks: registre un endpoint en su panel y reciba un POST firmado cuando termine un trabajo max, en lugar de consultar. La mayoría de las llamadas se responden directamente con el resultado terminado; la única excepción es el motor asíncrono max — para paneles 2D y para el anidado de forma real — donde POST /v1/optimize/2d o /v1/optimize/nest con engine "max" devuelve un id de trabajo que sondeas con GET /v1/jobs/{id} hasta que el resultado esté listo.
¿El motor balanced es mejor que el predeterminado?
No — es un compromiso, no una mejora. El motor heurístico predeterminado ofrece el mayor aprovechamiento y todos los planos que produce pueden cortarse en una seccionadora, así que siempre devuelve un plan de corte. El motor balanced es mucho más rápido en trabajos muy grandes pero aprovecha algo menos, y sus planos a menudo no pueden cortarse de borde a borde, por lo que no devuelve ningún plan de corte. Úsalo solo cuando la velocidad en un trabajo grande importe más que un plan listo para la sierra.
¿Qué pasa si revoco una clave de API — me devuelven el dinero?
No, y tampoco cancela nada. Revocar deja esa clave concreta sin funcionar, a partir de la siguiente llamada; tu suscripción sigue en marcha y la cuota mensual sigue vigente. Revoca una clave cuando haya quedado expuesta o cuando se retire una integración, y luego crea un reemplazo. Para dejar de pagar, cancelas la suscripción en su lugar — el acceso continúa entonces hasta el final del periodo que ya has pagado, y después de eso incluso las claves existentes dejan de funcionar.
¿Crear más claves de API me da más peticiones?
No. La cuota mensual pertenece a la cuenta, y cada clave activa consume del mismo cupo — una segunda clave no añade una segunda cuota. Las claves existen para que puedas separar staging de producción, dar a cada integración su propia credencial y revocar una sin molestar a las demás. Cuando se agota el cupo, todas las claves devuelven 402, no solo la que lo gastó. GET /v1/usage informa de la posición de la cuenta, con cualquier clave que preguntes.
¿Por qué mi clave de API solo se muestra una vez?
Porque CutOptim nunca almacena la clave en sí — solo un hash sha256 de ella. Eso significa que nadie, ni siquiera nosotros, puede volver a leer tu clave desde la base de datos, así que solo puede mostrarse en el momento en que se crea. Cópiala de inmediato en la configuración de tu software; si la pierdes, elimina la clave y crea una nueva.
¿Puede la Engine API devolver un dibujo, no solo coordenadas?
Sí. Añade include: ["svg","csv","dxf"] a una solicitud de optimización y la respuesta lleva la distribución como un archivo listo para usar, en línea en el JSON: un dibujo SVG 2D autónomo, un DXF R12/AC1009 en las capas STOCK/PARTS/LABELS, o una lista de corte CSV. No hay almacenamiento ni una segunda llamada. SVG es solo 2D; una solicitud 1D o de madera devuelve en su lugar una advertencia. También puedes adjuntar un objeto meta (el número de artículo de tu ERP, el id de línea de pedido o la referencia del cliente) a cualquier pieza o fila de material, y vuelve literalmente en la salida para que el plan cuadre con tu sistema. Ese es además el campo con el que identificar tableros: pon tu código en stock[].meta y vuelve reflejado en sheets[].meta, de modo que sabes qué tablero eligió el optimizador, y nunca afecta a la colocación. No uses el campo material para identificar — material es una partición estricta (una pieza solo se corta a partir de material del mismo tipo), así que etiquetar cada fila de material y dejar las piezas sin etiquetar hace que todas vuelvan como unmatched y el resultado quede vacío.
¿Puedo comprobar una solicitud sin gastar una de mis llamadas mensuales?
Sí. POST /v1/validate/2d, /v1/validate/1d, /v1/validate/wood o /v1/validate/nest toma el mismo cuerpo que el endpoint de optimización correspondiente y lo comprueba sin resolver — gratis, sin clave de API y sin gastar cuota. Una solicitud mal formada vuelve como un 400 que nombra el campo exacto que falla, y una bien formada devuelve valid: true más avisos de viabilidad (como una pieza que no cabe en ningún material). Úsalo para validar tus cargas útiles mientras construyes la integración, antes incluso de tener una clave.
¿Qué ocurre con un archivo SVG o DXF que envío a la API?
No queda nada de él. El archivo viaja como cuerpo de la solicitud, se lee en memoria para obtener el contorno de la pieza y desaparece en cuanto se escribe la respuesta — sin copia en disco, sin copia en base de datos, sin línea de registro que lo contenga, así que después no hay nada que borrar ni periodo de conservación por el que preguntar. Es la misma ausencia de estado que mantiene el resto de la API: tampoco guardamos tus planes de corte más tiempo que la solicitud que los produjo.
¿El anidado de forma real también tiene un motor max?
Sí. POST /v1/optimize/nest con engine "max" es asíncrono como el max de 2D: la llamada responde 202 con un id de trabajo y sondeas GET /v1/jobs/{id}. Primero ejecuta la pasada instantánea de lbf y luego dedica un presupuesto de tiempo — 60 segundos por defecto, de 10 a 180 mediante options.timeBudgetMs — buscando una distribución con menos tableros, llenando un tablero cada vez. Nunca devuelve más tableros de los que daría lbf; cuando no encuentra ninguno, obtienes la distribución de lbf y un aviso que lo dice. Como la búsqueda tiene un tiempo limitado, sus respuestas llevan deterministic: false. Acepta varios tamaños de tablero por material y respectStock, y conserva su propio resultado solo cuando clasifica mejor que el plan de lbf (por precio con options.minimizeCost, o si no por área de tablero). Un tablero poligonal o las zonas de exclusión, que su búsqueda no puede modelar, los sirve la pasada de lbf dentro del propio trabajo con un aviso — nunca se rechazan.
¿Por qué las piezas rectangulares del anidado volvían inclinadas o en un tablero de más?
Antes del 2026-09-28 podía ocurrir: el motor de anidado lbf encuentra las posiciones por muestreo, así que con rotación libre podía girar una pieza casi rectangular una fracción de grado, y rara vez encontraba una cuadrícula sin holgura, como tres piezas de 500 mm a lo ancho de un tablero de 1500 mm con espaciado cero. Ahora los dos motores de anidado prueban también las piezas en los ángulos rectos que permiten y colocan los rectángulos envolventes de las piezas con un empaquetador exacto de rectángulos, y se quedan con el plan que mejor clasifica; en caso de empate gana el plan que llena sus tableros en orden, del primero al último, y después el que tiene menos piezas inclinadas. No necesitas cambiar tu solicitud. Si tus piezas nunca deben salirse de los ángulos rectos, envía allowedRotations: [0, 90, 180, 270] como hasta ahora.
¿Puedo fijar el margen en el borde del tablero por separado del espaciado entre piezas?
Sí. options.minSeparation es el espaciado entre piezas, y por sí solo también se aplica en el borde del tablero. Añade options.edgeClearance para fijar el borde por separado — por ejemplo 5 entre piezas y 0 o 10 en el borde. Funciona en los dos motores de anidado, y si lo omites el borde conserva minSeparation exactamente como antes. Necesita tableros rectangulares (w y h): con un tablero poligonal, o con un valor que no deje espacio en el tablero, la solicitud se rechaza con un 400 antes de que se cobre una llamada. Las zonas de exclusión conservan minSeparation, igual que las piezas.
¿Cómo elige el anidado entre varios tamaños de tablero?
Cuando un material tiene dos o más filas de material, el motor lbf las prueba en tu orden, cada tamaño por su cuenta y en un orden de más barato primero, y se queda con la mejor — así el resultado deja de depender de qué fila listes primero. Clasifica por el mayor número de piezas de corte obligatorio colocadas (piezas marcadas con priority, lo que importa con options.respectStock), luego por más piezas colocadas, luego por la menor área total de tablero; con options.minimizeCost clasifica por precio total en su lugar (price, o cost cuando una fila no tiene precio), siempre que todas las filas de ese material tengan uno. Después, cada tablero — empezando por el menos lleno — se vuelve a anidar por su cuenta sobre las filas más baratas o más pequeñas, y se sustituye cuando el plan completo clasifica mejor — así los tamaños pueden mezclarse dentro de un material: normalmente dos tableros grandes y uno más pequeño al final. Con options.respectStock ninguna fila se usa más veces que su qty. La respuesta indica de qué fila procede cada tablero (sheets[].stock) y totaliza los tableros, el precio y la densidad por fila (stockUsage). El motor max aplica la misma clasificación.
¿Puedo marcar piezas de anidado como de corte obligatorio?
Sí: parts[].priority: true. Importa cuando el suministro de tablero está limitado (options.respectStock), porque entonces no todas las piezas caben: las piezas de corte obligatorio se colocan primero, así que una pieza normal nunca ocupa el espacio de tablero que necesita una pieza de corte obligatorio, y cada comparación de planes prioriza el plan que conserva más de ellas. Los dos motores de anidado lo respetan. Sin respectStock, todas las piezas que caben se colocan de todos modos, así que la marca no cambia nada. Una pieza de corte obligatorio que no cabe en ningún tablero sigue apareciendo en unplaced. (Antes del 22 de septiembre de 2026 el motor de anidado aceptaba este campo, pero no actuaba en consecuencia.)
¿La respuesta del anidado incluye la longitud de corte?
Sí. Cada tablero lleva cutLength — el perímetro sumado de los contornos exteriores y los agujeros de sus piezas colocadas, en tu unidad — y pierces, uno por cada contorno cerrado (el contorno de cada pieza más uno por cada agujero); metrics totaliza ambos para todo el trabajo. Es la longitud geométrica del contorno: no incluye el corte por línea común, las entradas y salidas de corte ni las microuniones, porque el CAM de tu máquina las añade — así que es una base sólida para el tiempo de máquina y los consumibles, no la trayectoria de herramienta final.
¿Puedo cobrar solo por la parte de un tablero que usa un anidado?
La API te da los números; la regla de facturación sigue siendo tuya. Cada tablero lleva usedWidth y usedHeight — el punto más lejano al que llega cualquier pieza colocada, medido desde la esquina de origen del tablero, en tu unidad — y usedArea, su producto; stockUsage[].usedArea lo totaliza por fila de material. Un corte horizontal es usedHeight × el ancho del tablero, uno vertical usedWidth × el alto del tablero, y una caja envolvente es usedArea. Los dos motores de anidado también compactan por defecto el tablero menos lleno de cada material: sus piezas se vuelven a anidar sobre el mismo tablero con subconjuntos de rotación de lo que cada pieza permite (0/180, 0/90/180/270, una sola orientación para todas las copias — nunca un ángulo nuevo), y se conserva la disposición con la menor área usada. El número de tableros, el precio y las piezas colocadas nunca cambian. options.compact: false devuelve la disposición sin compactar. Si facturas una franja en vez de la caja envolvente, fija options.compactFor a "horizontal" (la menor altura usada, para una franja que cruza todo el ancho del tablero) o "vertical" (el menor ancho usado, para una franja que cruza todo el alto del tablero); el valor por defecto "box" minimiza el área usada. Lo pequeña que llegue a ser el área usada depende de las piezas, así que no puede prometerse por adelantado ninguna fracción de tablero.
¿Cuánto presupuesto de tiempo debo dar al motor max de anidado?
El trabajo termina entre uno y dos segundos después de su presupuesto, más el tiempo que espere en la cola. Para un trabajo de unas pocas docenas de piezas, 15 segundos (options.timeBudgetMs: 15000) suele bastar; el valor por defecto es 60 segundos y el rango va de 10 a 180. Un presupuesto mayor da a la búsqueda más oportunidades de ahorrar un tablero, pero ningún presupuesto puede prometer un número de tableros concreto — eso depende de las piezas y del espaciado. Sondea GET /v1/jobs/{id} cada dos o tres segundos; sondear no cuesta cuota.
¿Puede la API respetar la dirección de la veta de una pieza?
Sí. En POST /v1/optimize/2d, da a una fila de material grain: "w" o "h" (el lado del tablero a lo largo del cual corre la veta) y a una pieza grain: "w" o "h" (el lado de la pieza a lo largo del cual debe correr). Cada una de esas piezas se coloca con su veta a lo largo de la de su tablero, girada 90° cuando hace falta (rotated: true), y rotatable se ignora para ella. Se pueden mezclar filas de material cuya veta corre en direcciones distintas. Con material, solo cuentan los tableros del propio material de la pieza. Cada tablero devuelve el grain de su fila. Si ninguna fila de material tiene veta, el grain de una pieza no tiene efecto y warnings lo indica. Los tres motores 2D lo admiten (max con su habitual fila de material única).
¿Puede la API cortar frentes que combinan para que la veta continúe de una pieza a la siguiente?
Sí, en POST /v1/optimize/2d. Da un id a las filas de piezas y nómbralas en matchedSets: para un frente de cajón sobre dos puertas, una disposición con dir rows y las líneas [DF] y [DOOR, DOOR]. El conjunto se corta una pieza junto a otra de un mismo tablero, separadas exactamente por un kerf, y la veta del conjunto decide la dirección de todos sus miembros. Cada miembro colocado vuelve con matchedSet (el id del conjunto, la instancia y su posición), y la respuesta añade un resumen matchedSets cuyos warnings dicen, por ejemplo, cuándo las medidas no cuadran. Los motores heuristic y balanced disponen conjuntos; el motor max rechaza un matchedSets no vacío con un 400 antes de cobrar una llamada. Las exportaciones pdf y labelsPdf dibujan los miembros como piezas normales, y la respuesta lo avisa; csv, svg y dxf marcan los conjuntos. Sin un array matchedSets no vacío no cambia nada, y parts[].id solo se comprueba en las filas que un conjunto nombra.
¿Sigue admitiéndose grainGroup?
Sí. grainGroup está obsoleto pero se sigue aceptando, y funciona exactamente como antes: las piezas que comparten un grupo se mantienen en un mismo tablero. Nunca las colocó una junto a otra, así que no da una veta continua entre ellas; para frentes cuyo dibujo debe continuar, usa matchedSets. El motor max rechaza grainGroup, como siempre.

Última actualización: 13 de octubre de 2026