{"openapi":"3.1.0","info":{"title":"HazTuPieza","version":"1.0.0","summary":"Cotizar impresión 3D y corte láser de metacrilato desde tu sistema.","description":"Taller de fabricación bajo pedido en Sevilla. Manda un archivo (STL, 3MF, STEP, SVG, DXF) con la clave de API del cliente y devuelve el precio al momento. Cotizar no crea nada y el archivo no se guarda. Documentación: https://haztupieza.es/desarrolladores","contact":{"url":"https://haztupieza.es/ayuda"}},"servers":[{"url":"https://haztupieza.es"}],"security":[{"bearerAuth":[]}],"paths":{"/api/v1/quotes/file":{"post":{"operationId":"quoteFile","summary":"Cotizar un archivo","description":"Sube la pieza y la medimos nosotros. Es la forma corta y la única que no necesita conocer la geometría de antemano. El proceso se deduce de la extensión.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file","config"],"properties":{"file":{"type":"string","format":"binary","description":"Formatos: .stl .obj .3mf .ply .step .stp .iges .igs .brep .sldprt .ipt .f3d .3dm .sat .x_t .svg .dxf .ai"},"config":{"type":"string","description":"La configuración, en JSON. Sus campos son los de PrintingConfig o LaserConfig según el proceso. En láser, widthMm y heightMm salen del archivo si no se mandan."},"process":{"type":"string","enum":["FDM_3D","LASER_ACRYLIC"]},"label":{"type":"string","maxLength":160}}}}}},"responses":{"200":{"description":"El precio y su desglose.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"401":{"description":"Clave no válida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Petición mal formada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/quotes":{"post":{"operationId":"quote","summary":"Cotizar con la geometría ya medida","description":"Para quien ya tiene el volumen y la caja de la pieza y no necesita subir el archivo.","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","title":"Impresión 3D","required":["process","config","mesh"],"properties":{"process":{"const":"FDM_3D"},"config":{"$ref":"#/components/schemas/PrintingConfig"},"mesh":{"$ref":"#/components/schemas/MeshStats"},"label":{"type":"string","maxLength":160}}},{"type":"object","title":"Corte láser","required":["process","config"],"properties":{"process":{"const":"LASER_ACRYLIC"},"config":{"$ref":"#/components/schemas/LaserConfig"},"label":{"type":"string","maxLength":160}}}]}}}},"responses":{"200":{"description":"El precio y su desglose.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"401":{"description":"Clave no válida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Configuración no válida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/catalog":{"get":{"operationId":"catalog","summary":"Valores válidos de cada parámetro","description":"Materiales, colores, impresoras, calidades, rellenos, acabados, camas, boquillas, insertos, planchas, formas, tipografías, plazos y formatos, tal y como están hoy. Pídelo en vez de suponerlos: cambian cuando cambia el taller.","responses":{"200":{"description":"El catálogo vigente.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Clave no válida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/orders":{"get":{"operationId":"listOrders","summary":"Los pedidos del cliente","description":"Los cincuenta últimos, del más nuevo al más viejo.","responses":{"200":{"description":"Lista de pedidos.","content":{"application/json":{"schema":{"type":"object","properties":{"orders":{"type":"array","items":{"$ref":"#/components/schemas/Order"}}}}}}},"401":{"description":"Clave no válida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/orders/{code}":{"get":{"operationId":"getOrder","summary":"Un pedido concreto","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string"},"example":"HTP-3MQ8N-LY45L"}],"responses":{"200":{"description":"El pedido.","content":{"application/json":{"schema":{"type":"object","properties":{"order":{"$ref":"#/components/schemas/Order"}}}}}},"401":{"description":"Clave no válida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Ese pedido no es tuyo, o no existe: se contesta lo mismo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Authorization: Bearer htp_… La clave se crea en https://haztupieza.es/cuenta/api y se enseña una sola vez."}},"schemas":{"PrintingConfig":{"type":"object","required":["materialId","colorId","qualityId","infillId","quantity","supports","leadTimeId"],"properties":{"materialId":{"type":"string"},"colorId":{"type":"string"},"extraColorIds":{"type":"array","maxItems":3,"items":{"type":"string"}},"qualityId":{"type":"string","enum":["draft","standard","fine","ultra"]},"infillId":{"type":"string","enum":["i15","i25","i40","i60","i100"]},"quantity":{"type":"integer","minimum":1,"maximum":2000},"supports":{"type":"boolean"},"finishIds":{"type":"array","maxItems":8,"items":{"type":"string"}},"plateId":{"type":"string","description":"\"auto\" deja que lo elija el taller."},"nozzleId":{"type":"string","description":"\"auto\" deja que lo elija el taller."},"pauses":{"type":"array","maxItems":30,"description":"Paradas para meter algo dentro de la pieza.","items":{"type":"object","required":["layer","action"],"properties":{"layer":{"type":"integer","minimum":1,"maximum":20000},"action":{"type":"string","minLength":3,"maxLength":500},"inserts":{"type":"array","maxItems":20,"items":{"type":"object","required":["optionId","quantity"],"properties":{"optionId":{"type":"string"},"quantity":{"type":"integer","minimum":1}}}}}}},"leadTimeId":{"type":"string","enum":["standard","express","urgent"]},"notes":{"type":"string","maxLength":1000}}},"LaserConfig":{"type":"object","required":["sheetId","shape","widthMm","heightMm","quantity","leadTimeId"],"properties":{"sheetId":{"type":"string","description":"Plancha de metacrilato. Ids en GET /api/v1/catalog."},"shape":{"type":"string","enum":["RECT","ROUNDED_RECT","CIRCLE","RING","CUSTOM"],"description":"Tipo de contorno. Con archivo o con forma del catálogo, CUSTOM."},"shapeId":{"type":"string","description":"Forma del catálogo paramétrico. Ids en GET /api/v1/catalog."},"shapeParams":{"type":"object","additionalProperties":{"type":"number"},"description":"Medidas de esa forma. Cada forma pide sus propias claves."},"texto":{"type":"object","description":"Solo con shapeId \"texto\": el texto se corta como contorno.","required":["texto","tipografiaId","alturaMm"],"properties":{"texto":{"type":"string"},"tipografiaId":{"type":"string"},"alturaMm":{"type":"number"}}},"widthMm":{"type":"number","minimum":5,"maximum":1200},"heightMm":{"type":"number","minimum":5,"maximum":1200},"cornerRadiusMm":{"type":"number","minimum":0,"maximum":500,"default":0},"innerDiameterMm":{"type":"number","minimum":0,"maximum":1200,"default":0,"description":"Solo con shape RING."},"quantity":{"type":"integer","minimum":1,"maximum":5000},"cutouts":{"type":"array","maxItems":24,"description":"Vaciados interiores, cada uno con su forma y su posición.","items":{"type":"object","required":["id","shapeId","params","xMm","yMm"],"properties":{"id":{"type":"string"},"shapeId":{"type":"string","description":"Forma del catálogo, o \"texto\" para vaciar un rótulo."},"params":{"type":"object","additionalProperties":{"type":"number"},"description":"Medidas de esa forma. Con shapeId \"texto\" va vacío: manda el campo texto."},"texto":{"type":"object","description":"Solo con shapeId \"texto\": las letras se quitan de la pieza. Solo tipografías de plantilla (stencil: true en GET /api/v1/catalog): con otra, las contras de las letras se caerían dentro de la máquina y el vaciado no se hace.","required":["texto","tipografiaId","alturaMm"],"properties":{"texto":{"type":"string"},"tipografiaId":{"type":"string"},"alturaMm":{"type":"number"}}},"xMm":{"type":"number"},"yMm":{"type":"number"},"rotationDeg":{"type":"number","default":0},"conservarPieza":{"type":"boolean","default":false,"description":"La pieza que sale del recorte va en el pedido, encajada en su hueco, en vez de tirarse. Sin coste de material. Solo en recortes con forma (no texto), cerrados dentro de la pieza y de al menos 10 mm por lado. Los agujeros y recortes que caigan dentro de él son de esa pieza."}}}},"holes":{"type":"object","description":"Taladros. El patrón decide qué campos hacen falta.","properties":{"pattern":{"type":"string","enum":["NONE","CORNERS","PERIMETER","RADIAL","GRID","POINTS","CUSTOM"],"default":"NONE"},"diameterMm":{"type":"number","minimum":0,"maximum":200,"default":0},"edgeDistanceMm":{"type":"number","minimum":0,"maximum":600,"default":0},"count":{"type":"integer","minimum":0,"maximum":200,"default":0},"edgeCounts":{"type":"array","maxItems":24,"items":{"type":"integer"}},"rows":{"type":"integer","minimum":0,"maximum":50,"default":0},"columns":{"type":"integer","minimum":0,"maximum":50,"default":0},"centerDistanceMm":{"type":"number","minimum":0,"maximum":600,"default":0},"points":{"type":"array","maxItems":200,"items":{"type":"object","required":["xMm","yMm"],"properties":{"xMm":{"type":"number"},"yMm":{"type":"number"}}}}}},"engraveAreaCm2":{"type":"number","minimum":0,"maximum":6000,"default":0,"description":"Superficie a grabar. Se ignora en las planchas de extrusión, que no se graban."},"leadTimeId":{"type":"string","enum":["standard","express","urgent"]},"notes":{"type":"string","maxLength":1000}}},"MeshStats":{"type":"object","required":["volumeCm3","surfaceCm2","boundingBoxMm","triangles","watertight","hash"],"properties":{"volumeCm3":{"type":"number"},"surfaceCm2":{"type":"number"},"boundingBoxMm":{"type":"object","required":["x","y","z"],"properties":{"x":{"type":"number"},"y":{"type":"number"},"z":{"type":"number"}}},"triangles":{"type":"integer"},"watertight":{"type":"boolean"},"hash":{"type":"string"}}},"QuoteResponse":{"type":"object","properties":{"ok":{"type":"boolean","description":"false cuando la pieza no se puede fabricar. El HTTP sigue siendo 200."},"errors":{"type":"array","items":{"type":"string"}},"total":{"type":["number","null"]},"breakdown":{"type":["object","null"],"additionalProperties":true},"manualReview":{"type":"boolean","description":"El formato no se puede medir: lo cotiza una persona."},"file":{"type":"object","additionalProperties":true}}},"Error":{"type":"object","required":["code","error"],"properties":{"code":{"type":"string","enum":["unauthorized","not_found","invalid_request","rate_limited"]},"error":{"type":"string"},"details":{"type":"object","additionalProperties":true}}},"Order":{"type":"object","properties":{"code":{"type":"string"},"status":{"type":"string","enum":["AWAITING_PAYMENT","PAID","IN_PRODUCTION","QUALITY_CHECK","READY_FOR_PICKUP","SHIPPED","DELIVERED","CANCELLED","REFUNDED"]},"total":{"type":"number"},"trackingCarrier":{"type":["string","null"]},"trackingNumber":{"type":["string","null"]},"items":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"quantity":{"type":"integer"},"process":{"type":"string"},"unitPrice":{"type":"number"},"total":{"type":"number"}}}}}}}}}