API
Manda un archivo y una configuración, y te devolvemos el precio al momento: impresión 3D y corte láser de metacrilato. Es el mismo motor que calcula los precios en la web, así que si tienes tarifas acordadas salen aplicadas.
Empezar
Necesitas una cuenta y una clave. La clave se crea desde Cuenta → Claves de API y se enseña una sola vez: no la guardamos en claro, así que si la pierdes hay que revocarla y crear otra.
Todo va por HTTPS y responde JSON. Las peticiones con cuerpo lo esperan en JSON y con Content-Type: application/json; las que llevan archivo, en multipart.
Para comprobar que la clave funciona, cualquier endpoint sirve:
curl https://haztupieza.es/api/v1/orders \
-H "Authorization: Bearer htp_TU_CLAVE"Cotizar
Cotizar es gratis y no crea nada: ni cotización guardada, ni carrito, ni pedido. Se puede llamar en bucle mientras se ajustan medidas.
Con un archivo
POST/api/v1/quotes/file
La forma corta: subes la pieza y la medimos nosotros. Vale para impresión 3D y para corte láser; el proceso se deduce de la extensión.
Impresión 3D — un STL, un 3MF, un STEP:
curl https://haztupieza.es/api/v1/quotes/file \
-H "Authorization: Bearer htp_TU_CLAVE" \
-F "file=@soporte.stl" \
-F 'config={"materialId":"pla","colorId":"negro","qualityId":"standard","infillId":"i25","quantity":4,"supports":true,"leadTimeId":"standard"}'Corte láser — un SVG o un DXF. Las medidas salen del propio dibujo:
curl https://haztupieza.es/api/v1/quotes/file \
-H "Authorization: Bearer htp_TU_CLAVE" \
-F "file=@tapa.svg" \
-F 'config={"sheetId":"pmma-colada-incoloro-3","quantity":10,"leadTimeId":"standard"}'La respuesta trae lo que hemos medido, además del precio:
{
"ok": true,
"errors": [],
"total": 24.18,
"breakdown": {
"unitPrice": 6.045,
"lines": [
{ "id": "material", "label": "Material", "amount": 4.12 },
{ "id": "machine", "label": "Máquina", "amount": 11.4 },
{ "id": "finishing", "label": "Acabados", "amount": 4.9 }
],
"taxRate": 0.21,
"leadTimeDays": 3
},
"file": {
"name": "soporte.stl",
"mesh": {
"volumeCm3": 18.42,
"surfaceCm2": 96.3,
"boundingBoxMm": { "x": 62.4, "y": 41, "z": 18 },
"triangles": 24680,
"watertight": true,
"hash": "9f2c1a7b"
}
}
}Del archivo no guardamos nada. Se mide en memoria y se descarta. Si el formato no lo sabemos abrir —un SolidWorks, un Illustrator— la respuesta es 200 con «manualReview» a true y el motivo: eso lo cotiza una persona.
Con la geometría ya medida
POST/api/v1/quotes
Si ya tienes el volumen y la caja de la pieza —porque la mides tú, o porque las guardaste de una cotización anterior— puedes ahorrarte subir el archivo.
curl https://haztupieza.es/api/v1/quotes \
-H "Authorization: Bearer htp_TU_CLAVE" \
-H "Content-Type: application/json" \
-d '{
"process": "FDM_3D",
"label": "soporte.stl",
"config": {
"materialId": "pla",
"colorId": "negro",
"qualityId": "standard",
"infillId": "i25",
"quantity": 4,
"supports": true,
"leadTimeId": "standard"
},
"mesh": {
"volumeCm3": 18.42,
"surfaceCm2": 96.3,
"boundingBoxMm": {
"x": 62.4,
"y": 41,
"z": 18
},
"triangles": 24680,
"watertight": true,
"hash": "9f2c1a7b"
}
}'Un 200 no siempre es un sí. Cuando la pieza no se puede fabricar —esa plancha ya no se sirve, la medida no cabe en la máquina— la respuesta sigue siendo 200 con «ok» a false y el motivo en «errors». Es una respuesta, no un fallo: reintentarla daría exactamente lo mismo. Mira siempre «ok».
Corte láser, todos los campos
Sin archivo se puede pedir cualquier forma del catálogo. Este ejemplo lleva absolutamente todo lo que acepta el endpoint, con los valores por defecto puestos a la vista; casi nada es obligatorio.
curl https://haztupieza.es/api/v1/quotes \
-H "Authorization: Bearer htp_TU_CLAVE" \
-H "Content-Type: application/json" \
-d '{
"process": "LASER_ACRYLIC",
"label": "frontal",
"config": {
"sheetId": "pmma-colada-incoloro-3",
"shape": "ROUNDED_RECT",
"shapeId": "rounded-rect",
"shapeParams": {
"w": 300,
"h": 200,
"radius": 12
},
"widthMm": 300,
"heightMm": 200,
"cornerRadiusMm": 12,
"innerDiameterMm": 0,
"quantity": 10,
"cutouts": [
{
"id": "ventana",
"shapeId": "circle",
"params": {
"d": 22
},
"xMm": 60,
"yMm": 100,
"rotationDeg": 0,
"conservarPieza": true
},
{
"id": "ranura",
"shapeId": "stadium",
"params": {
"w": 40,
"h": 8
},
"xMm": 240,
"yMm": 100,
"rotationDeg": 90
},
{
"id": "rotulo",
"shapeId": "texto",
"params": {},
"texto": {
"texto": "SALIDA",
"tipografiaId": "stardos-stencil",
"alturaMm": 25
},
"xMm": 150,
"yMm": 100,
"rotationDeg": 0
}
],
"holes": {
"pattern": "CORNERS",
"diameterMm": 4,
"edgeDistanceMm": 10,
"count": 4,
"edgeCounts": [
2,
2,
2,
2
],
"rows": 0,
"columns": 0,
"centerDistanceMm": 0,
"points": []
},
"engraveAreaCm2": 0,
"leadTimeId": "express",
"vectorPendingReview": false,
"notes": "Cantos pulidos por la cara vista."
}
}'Solo son obligatorios estos: sheetId, shape, widthMm, heightMm, quantity, leadTimeId
shapeId: "texto" — corta el texto como contorno de la pieza, con la tipografía y la altura que le digas.
curl https://haztupieza.es/api/v1/quotes \
-H "Authorization: Bearer htp_TU_CLAVE" \
-H "Content-Type: application/json" \
-d '{
"process": "LASER_ACRYLIC",
"config": {
"sheetId": "pmma-colada-incoloro-3",
"shape": "CUSTOM",
"shapeId": "texto",
"texto": {
"texto": "ABIERTO",
"tipografiaId": "anton",
"alturaMm": 80
},
"widthMm": 400,
"heightMm": 80,
"quantity": 2,
"leadTimeId": "standard"
}
}'Impresión 3D, todos los campos
Lo mismo para FDM: el ejemplo largo, con lo opcional incluido.
curl https://haztupieza.es/api/v1/quotes/file \
-H "Authorization: Bearer htp_TU_CLAVE" \
-F "file=@pieza.3mf" \
-F 'config={"materialId":"pla","colorId":"negro","qualityId":"standard","infillId":"i25","quantity":4,"supports":true,"leadTimeId":"standard","finishIds":["sanding"],"extraColorIds":["rojo"],"plateId":"auto","nozzleId":"auto","pauses":[{"layer":40,"action":"Colocar 4 tuercas M3 en los alojamientos","inserts":[{"optionId":"tuerca-m3","quantity":4}]}],"notes":"La cara buena es la de arriba."}'Opciones
Los identificadores que aceptan «materialId», «sheetId» y compañía. Esta lista sale del mismo catálogo que usa el taller y cambia cuando cambia: no la copies, pídela.
Todo lo de abajo, en una sola llamada y siempre al día:
GET/api/v1/catalog
curl https://haztupieza.es/api/v1/catalog \
-H "Authorization: Bearer htp_TU_CLAVE"Y así está hoy:
Materiales (impresión 3D)
| Identificador | Nombre | Detalle |
|---|---|---|
| pla | PLA | PLA · 15 colores |
| pla-alta-resistencia | PLA alta resistencia | PLA · 9 colores |
| pla-mate | PLA Mate | PLA · 3 colores |
| pla-reciclado | PLA Reciclado | PLA · 3 colores |
| pla-seda | PLA Silk | PLA · 7 colores |
| pla-madera | PLA Madera | PLA · 3 colores |
| pla-marmol | PLA Marmol | PLA · 2 colores |
| pla-glitter | PLA Glitter | PLA · 4 colores |
| pla-fluorescente | PLA Fluorescente (glow in the dark) | PLA · 2 colores |
| pla-metalizado | PLA Metalizado | PLA · 4 colores |
| petg | PETG | PETG · 7 colores |
| abs | ABS-E | ABS · 5 colores |
| asa | ASA | ASA · 4 colores |
| tpu-95a | TPU 95A Flex | TPU · 5 colores |
| nylon-pa | Nylon PA | PA · 2 colores |
| hips | HIPS | HIPS · 2 colores |
Cada material trae sus colores en «colors». El id del color va en «colorId».
Calidades
| Identificador | Nombre | Detalle |
|---|---|---|
| draft | Borrador 0,28 mm | 0.28 mm |
| standard | Estándar 0,20 mm | 0.2 mm |
| fine | Fina 0,16 mm | 0.16 mm |
| ultra | Ultrafina 0,12 mm | 0.12 mm |
Rellenos
| Identificador | Nombre | Detalle |
|---|---|---|
| i15 | 15 % ligero | 15 % |
| i25 | 25 % estándar | 25 % |
| i40 | 40 % resistente | 40 % |
| i60 | 60 % robusto | 60 % |
| i100 | 100 % macizo | 100 % |
Planchas de metacrilato (corte láser)
| Identificador | Nombre | Detalle |
|---|---|---|
| pmma-colada-incoloro-3 | Metacrilato transparente 3 mm | 3 mm · 1000×600 mm |
| pmma-colada-incoloro-5 | Metacrilato transparente 5 mm | 5 mm · 1000×600 mm |
| pmma-colada-incoloro-6 | Metacrilato transparente 6 mm | 6 mm · 1000×600 mm |
| pmma-colada-incoloro-8 | Metacrilato transparente 8 mm | 8 mm · 1000×600 mm |
| pmma-colada-incoloro-10 | Metacrilato transparente 10 mm | 10 mm · 1000×600 mm |
| pmma-extrusion-incoloro-3 | Metacrilato extrusión transparente 3 mm | 3 mm · 1000×600 mm |
| pmma-extrusion-incoloro-5 | Metacrilato extrusión transparente 5 mm | 5 mm · 1000×600 mm |
| pmma-blanco-3 | Metacrilato opal 3 mm | 3 mm · 1000×600 mm |
| pmma-negro-3 | Metacrilato negro 3 mm | 3 mm · 1000×600 mm |
| pmma-tintado-3-rojo | Metacrilato tintado rojo 3 mm | 3 mm · 1000×600 mm |
| pmma-tintado-3-azul | Metacrilato tintado azul 3 mm | 3 mm · 1000×600 mm |
| pmma-tintado-3-verde | Metacrilato tintado verde 3 mm | 3 mm · 1000×600 mm |
| pmma-tintado-3-ambar | Metacrilato tintado ámbar 3 mm | 3 mm · 1000×600 mm |
| pmma-tintado-3-fume | Metacrilato tintado fumé 3 mm | 3 mm · 1000×600 mm |
| dm-3 | DM 3 mm | 3 mm · 800×400 mm |
| pmma-fluor-3-naranja | Metacrilato fluorescente naranja 3 mm | 3 mm · 1000×600 mm |
| pmma-fluor-3-rojo | Metacrilato fluorescente rojo 3 mm | 3 mm · 1000×600 mm |
| pmma-fluor-3-verde | Metacrilato fluorescente verde 3 mm | 3 mm · 1000×600 mm |
Formas del catálogo
| Identificador | Nombre | shapeParams |
|---|---|---|
| rect | Rectángulo | w, h |
| rect-bevel | Rectángulo achaflanado | w, h, bevel |
| rect-corner | Rectángulo con esquina cortada | w, h, cutW, cutH |
| rect-slant | Rectángulo con lado inclinado | w, hLeft, hRight |
| separador | Separador de estantería | w, h, frente |
| triangle | Triángulo | w, h |
| triangle-right | Triángulo rectángulo | w, h |
| triangle-right-mirror | Triángulo rectángulo invertido | w, h |
| trapezoid | Trapecio | wTop, wBottom, h |
| parallelogram | Paralelogramo | w, h, offset |
| hexagon | Hexágono | w, h |
| octagon | Octágono | w, h, bevel |
| polygon | Polígono regular | sides, d |
| rounded-rect | Rectángulo redondeado | w, h, radius |
| circle | Círculo | d |
| ring | Corona | d, inner |
| oval | Óvalo | w, h |
| stadium | Óvalo plano | w, h |
| semicircle | Semicírculo | d |
| quarter-circle | Cuarto de círculo | r |
| arch | Arco | w, h |
| barrel | Tonel | w, h, bulge |
| star | Estrella | points, d, inner |
| heart | Corazón | w, h |
| drop | Gota | w, h |
| arrow | Flecha | w, h, stem, head |
| kite | Cometa | w, h, cross |
| gem | Gema | w, h, crown, top |
«shapeId» elige la forma y «shapeParams» le pasa sus medidas, que son distintas en cada una. Con un archivo o con un rectángulo a medida no hace falta ninguna de las dos.
Patrones de agujeros
| Identificador | Nombre | Detalle |
|---|---|---|
| NONE | Sin agujeros | — |
| CORNERS | En las esquinas | diameterMm, edgeDistanceMm |
| PERIMETER | Repartidos por el borde | diameterMm, edgeDistanceMm, count o edgeCounts |
| RADIAL | En círculo | diameterMm, count, centerDistanceMm |
| GRID | En cuadrícula | diameterMm, rows, columns, centerDistanceMm |
| POINTS | En coordenadas concretas | diameterMm, points[{ xMm, yMm }] |
| CUSTOM | Los que traiga el archivo | — |
Plazos
| Identificador | Nombre | Detalle |
|---|---|---|
| standard | Estándar | 3 días laborables |
| express | Exprés 48 h | 2 días laborables |
| urgent | Urgente 24 h | 1 días laborables |
Formatos de archivo
Formatos que aceptamos, y lo que hacemos con cada uno:
| Identificador | Proceso | Detalle |
|---|---|---|
| .stl .obj .3mf .ply | FDM_3D | Se miden solas. Precio al momento. |
| .step .stp .iges .igs .brep | FDM_3D | Se teselan en el servidor. Precio al momento. |
| .sldprt .ipt .f3d .3dm .sat .x_t | FDM_3D | CAD propietario: lo cotiza una persona. |
| .svg .dxf | LASER_ACRYLIC | Se miden solas. Precio al momento. |
| .ai | LASER_ACRYLIC | Lo cotiza una persona. |
Pedidos
GET/api/v1/orders
Los cincuenta últimos, del más nuevo al más viejo, con su estado y su seguimiento.
GET/api/v1/orders/{code}
Uno concreto, con sus líneas y sus importes.
{
"order": {
"code": "HTP-3MQ8N-LY45L",
"status": "IN_PRODUCTION",
"total": 43.05,
"trackingCarrier": "MRW",
"trackingNumber": "0123456789",
"items": [
{ "label": "tapa.svg", "quantity": 10, "process": "LASER_ACRYLIC",
"unitPrice": 3.55, "total": 35.5 }
]
}
}Los estados posibles son: AWAITING_PAYMENT, PAID, IN_PRODUCTION, QUALITY_CHECK, READY_FOR_PICKUP, SHIPPED, DELIVERED, CANCELLED, REFUNDED
Límite de peticiones
60 peticiones por minuto y clave. Cada respuesta lleva cuántas te quedan, así que no hace falta chocarse con el techo para saber dónde está:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 42Al pasarte, un 429 con «Retry-After» en segundos. No es un castigo: cotizar monta la geometría de la pieza y consulta el almacén, y un bucle mal cerrado deja al resto sin servicio.
Cuando algo va mal
Siempre un JSON con «code» —estable, para poder decidir con él— y «error», que es el mensaje para leer.
401unauthorized— la clave falta, está mal o se revocó.404not_found— ese pedido no es tuyo. Contestamos lo mismo si no existe: lo contrario serviría para averiguar qué códigos hay.422invalid_request— la configuración no es válida. Viene con «details» campo por campo.429rate_limited— te has pasado del límite.
Para asistentes y agentes
Si estás integrando esto en un asistente: con la clave del cliente y un archivo se cotiza en una sola llamada, sin pasos previos y sin subir nada a ningún sitio antes.
Hay descripción legible por máquina en dos formatos:
- /openapi.json — el contrato completo, para generar un cliente o cargarlo como herramienta.
- /llms.txt — un resumen corto en texto plano, para meter en contexto.
Lo que todavía no se puede
Cerrar un pedido. Cotizar sí, comprar no. Para eso hay que acordar antes cómo se paga —contra factura, a crédito— y eso es una conversación, no un endpoint. Si te interesa, escríbenos y lo hablamos: está a un paso de estar hecho.
¿Te falta algo o algo no responde como aquí dice? Dínoslo. Contesta quien la ha escrito.