{"openapi":"3.1.0","info":{"title":"Promax Studio: API para IA","version":"1.0.0","description":"Desenha ambientes e móveis planejados no Promax Studio, com as mesmas regras da tela. Medidas sempre em mm. Toda chamada leva a chave da empresa (Authorization: Bearer pmxs_..., criada em Empresa > Integrações).\n\nComece aqui: 1) getCatalog: os modelos de móvel (catalogItem) com as medidas da empresa, os eletros e o guia de todos os comandos. 2) getProject (ou listProjects e createProject + createEnvironment): a revisão e as paredes, com id, comprimento e startCorner. 3) Monte o lote: cada móvel é addModule com catalogItem e placement { wallId, offset }; o item ocupa de offset a offset + largura a partir do canto de início da parede (visto de dentro, o startCorner da parede). 4) applyCommands com dryRun=true, leia avisos, ajustes e problemas de abertura. 5) applyCommands com baseRevision pra gravar. 6) Ajuste pendente: applyCommands com fix { key, index }. 7) getParts.\n\nErros têm um código estável e uma mensagem em português. Limites por chave e por empresa: 429 com Retry-After. Guia completo, com exemplos: https://promaxstudio.com.br/llms-full.txt"},"externalDocs":{"description":"Guia completo da API para IA (roteiro, exemplos, erros e limites).","url":"https://promaxstudio.com.br/llms-full.txt"},"servers":[{"url":"https://promaxstudio.com.br/api/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Chave da API criada em Empresa > Integrações (começa com pmxs_). Escopo leitura ou escrita."}},"responses":{"Error":{"description":"Erro: code estável pra máquina, message em português pra pessoa; index diz o comando do lote que falhou, path o campo do corpo.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"index":{"type":"integer"},"path":{"type":"string"}}}}},"example":{"error":{"code":"items_overlap","message":"O móvel B02 ocupa o mesmo lugar que o móvel B01."}}}}}},"schemas":{"WallPlacement":{"type":"object","required":["wallId","offset"],"description":"Onde o móvel ou a peça avulsa fica: numa parede, de offset a offset + largura, a partir do canto de início dela (o startCorner do resumo).","properties":{"wallId":{"type":"string","description":"O id da parede, do resumo do projeto (walls[].id)."},"offset":{"type":"number","description":"Do canto de início da parede até o lado do item mais perto dele. Em mm."},"elevation":{"type":"number","description":"Do piso até a base do item. Pode faltar: o servidor põe a do catálogo (aéreo: a altura padrão; balcão e torre: 0). Em mm."},"fromWall":{"type":"number","description":"Da parede até as costas do item (0 é encostado). Pode faltar (0). Em mm."}}},"Zone":{"type":"object","required":["kind"],"description":"Uma zona do móvel, de baixo pra cima. doors: height (null fica com o que sobra), leaves 1 ou 2, hingeSide left|right, shelves, handle none|bar|knob. drawers: height, count 1 a 6, handle. niche: height, shelves (é o lugar do eletro de embutir).","properties":{"kind":{"type":"string","enum":["doors","drawers","niche"]},"height":{"type":["number","null"]},"leaves":{"type":"integer","enum":[1,2]},"hingeSide":{"type":"string","enum":["left","right"]},"shelves":{"type":"integer"},"count":{"type":"integer"},"handle":{"type":"string","enum":["none","bar","knob"]}}},"ModuleInput":{"type":"object","required":["catalogItem","placement"],"description":"Móvel novo: o modelo do catálogo (getCatalog, modules[].template) com o lugar e só o que muda. id e number podem faltar (o servidor preenche); mande id quando um eletro do mesmo lote for no móvel.","properties":{"catalogItem":{"type":"string","enum":["base-doors","base-sink","base-drawers","base-corner","wall-doors","wall-corner","tall-oven","tall-pantry","fridge-panel"]},"placement":{"$ref":"#/components/schemas/WallPlacement"},"width":{"type":"number","description":"Largura, dentro dos limites do catálogo. Em mm."},"height":{"type":"number","description":"Altura. Em mm."},"depth":{"type":"number","description":"Profundidade. Em mm."},"zones":{"type":"array","items":{"$ref":"#/components/schemas/Zone"}},"blind":{"type":["object","null"],"description":"Canto cego do balcão e do aéreo de canto: side left|right (o lado encostado no canto) e width."},"name":{"type":"string"},"id":{"type":"string"}}},"ApplianceInput":{"type":"object","required":["kind","placement"],"description":"Eletro de exemplo, com as medidas do catálogo (não mudam). placement: piso { kind: floor, wallId, offset } pra geladeira e lava-louças; nicho { kind: niche, moduleId, zoneIndex } pro forno e o micro-ondas (na torre quente, zoneIndex 1 é o forno e 2 o micro-ondas); tampo { kind: countertop, moduleId, offset do centro a partir do lado esquerdo do balcão } pro cooktop e a cuba (o balcão precisa de tampo); parede { kind: wall, wallId, offset, elevation } pra coifa.","properties":{"kind":{"type":"string","enum":["fridge","cooktop","oven","microwave","hood","sink","dishwasher"]},"placement":{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["floor","niche","countertop","wall"]},"wallId":{"type":"string"},"offset":{"type":"number"},"elevation":{"type":"number"},"moduleId":{"type":"string"},"zoneIndex":{"type":"integer"}}},"doorHinge":{"type":"string","description":"Pra que lado a porta abre, visto de frente (left, right, top ou bottom); pode faltar."},"id":{"type":"string"}}},"CountertopInput":{"type":"object","required":["wallId","offset","length","depth","thickness","material"],"description":"Tampo de pedra em cima dos balcões, medido na parede como o móvel. thickness e material não têm padrão: pergunte se a pessoa não disse. No canto em L, um tampo vai até o canto e o da outra parede para na frente dele.","properties":{"wallId":{"type":"string"},"offset":{"type":"number","description":"Do canto de início da parede até a ponta do tampo. Em mm."},"length":{"type":"number","description":"Comprimento ao longo da parede. Em mm."},"depth":{"type":"number","description":"Da parede até a borda da frente (600 cobre o balcão de 560). Em mm."},"thickness":{"type":"number","description":"Espessura da pedra. Em mm."},"material":{"type":"string","description":"Nome da pedra, como Granito São Gabriel."},"name":{"type":"string"}}},"OpeningInput":{"type":"object","required":["kind","distanceFromStart"],"description":"Porta, janela ou passagem. As medidas que faltarem vêm dos padrões de desenho da empresa.","properties":{"kind":{"type":"string","enum":["door","window","passage"]},"distanceFromStart":{"type":"number","description":"Do canto de início da parede até o vão. Em mm."},"width":{"type":"number","description":"Largura. Em mm."},"height":{"type":"number","description":"Altura. Em mm."},"sillHeight":{"type":"number","description":"Peitoril (janela). Em mm."},"hingeSide":{"type":["string","null"],"enum":["start","end",null]},"openDirection":{"type":["string","null"],"enum":["inward","outward",null]}}},"Command":{"type":"object","required":["type"],"additionalProperties":true,"properties":{"type":{"type":"string","enum":["rename","setEnvironmentNotes","setCeilingHeight","drawWall","closeContour","moveVertex","setWallLength","setWallThickness","setWallHeight","removeWall","flipInteriorSide","addOpening","updateOpening","moveOpeningToWall","removeOpening","setStandards","addModule","updateModule","removeModule","addAppliance","updateAppliance","removeAppliance","addCountertop","updateCountertop","removeCountertop","addFinishPart","updateFinishPart","removeFinishPart"]},"module":{"$ref":"#/components/schemas/ModuleInput"},"appliance":{"$ref":"#/components/schemas/ApplianceInput"},"countertop":{"$ref":"#/components/schemas/CountertopInput"},"opening":{"$ref":"#/components/schemas/OpeningInput"},"finishPart":{"type":"object","description":"Peça avulsa (addFinishPart): kind (filler, finish_side, shelf, slatted_panel, free), placement como o do móvel e o que muda do modelo do catálogo."},"wallId":{"type":"string","description":"A parede do comando de parede ou de vão."},"length":{"type":"number","description":"setWallLength e drawWall: o comprimento da parede. Em mm."},"thickness":{"type":"number","description":"drawWall, closeContour e setWallThickness: a espessura da parede. Em mm."},"name":{"type":"string","description":"rename: o nome do ambiente."}},"description":"Um comando do motor. Os ids e números de item novo podem faltar (o servidor preenche), e o móvel, o eletro e a peça avulsa novos partem do modelo do catálogo (mande catalogItem ou kind, o lugar e só o que muda). O guia abaixo é o mesmo de getCatalog (commands).\nrename: Nome do ambiente. Campos: name.\nsetEnvironmentNotes: Anotações do ambiente (briefing), até 10 mil letras. Campos: notes.\nsetCeilingHeight: Pé direito em mm. Campos: ceilingHeight.\ndrawWall: Parede nova no fim da corrente. Campos: length, angle (graus), thickness; start {x, y} só na primeira parede; wallId e endVertexId opcionais.\ncloseContour: Fecha o ambiente ligando a última parede à primeira. Campos: thickness; wallId opcional.\nmoveVertex: Move um canto. Campos: vertexId, x, y.\nsetWallLength: Comprimento da parede (os ângulos ficam; a paralela acompanha). Corrigir medida da obra: o que deixar de caber vira ajuste pendente. Campos: wallId, length.\nsetWallThickness: Espessura da parede (cresce pra fora). Campos: wallId, thickness.\nsetWallHeight: Altura de uma parede. Campos: wallId, height (null herda o pé direito).\nremoveWall: Apaga a parede da ponta e o que está nela. Campos: wallId.\nflipInteriorSide: Lado de dentro (só com o ambiente aberto). Campos: interiorSide opcional (left|right): o lado que fica; sem ele, troca.\naddOpening: Porta, janela ou passagem. Medidas que faltarem vêm dos padrões de desenho da empresa. Campos: wallId, opening {kind door|window|passage, distanceFromStart, width, height, sillHeight, hingeSide start|end, openDirection inward|outward; id opcional}.\nupdateOpening: Muda um vão. Campos: wallId, openingId, changes {distanceFromStart, width, height, sillHeight, hingeSide, openDirection}.\nmoveOpeningToWall: Leva o vão pra outra parede. Campos: fromWallId, openingId, toWallId, distanceFromStart.\nremoveOpening: Apaga o vão. Campos: wallId, openingId.\nsetStandards: Padrão de construção do ambiente. Campos: standards (opcional: sem ele, o padrão da empresa).\naddModule: Móvel do catálogo, parametrizado. Ocupa de offset a offset + width ao longo da parede, a partir do canto de início (startCorner). A altura do piso (elevation) vem do catálogo: balcão e torre 0, aéreo a altura padrão do aéreo. Campos: module {catalogItem (de modules), placement {wallId, offset, elevation?, fromWall?}, e só o que muda do modelo: width, height, depth, zones, blind {side left|right, width}, name; id (pra usar no eletro do mesmo lote) e number opcionais}.\nupdateModule: Troca o móvel. Com as medidas travadas (sizeLocked), só muda o lugar (module_size_locked). Campos: module (o móvel inteiro, com o mesmo id e número: leia com getEnvironment).\nremoveModule: Apaga o móvel e os eletros dele. Campos: moduleId.\naddAppliance: Eletro de exemplo, com as medidas do catálogo (não mudam). Campos: appliance {kind (de appliances), placement: piso {kind: floor, wallId, offset} (geladeira, lava-louças); nicho {kind: niche, moduleId, zoneIndex} (forno e micro-ondas, numa zona niche, contada de baixo a partir de 0: na torre quente, 1 é o forno e 2 o micro-ondas); tampo {kind: countertop, moduleId, offset} (cooktop e cuba, com o centro a offset do lado esquerdo do balcão, que precisa de tampo em cima); parede {kind: wall, wallId, offset, elevation} (coifa); doorHinge opcional; id e number opcionais}.\nupdateAppliance: Muda o lugar e o lado da porta do eletro; as medidas não mudam (appliance_size_fixed). Campos: appliance (inteiro).\nremoveAppliance: Apaga o eletro. Campos: applianceId.\naddCountertop: Tampo de pedra em cima dos balcões, ao longo da parede (medido como o móvel). No canto em L, um tampo vai até o canto e o da outra parede para na frente dele. Campos: countertop {wallId, offset, length, depth (da parede até a frente: 600 cobre o balcão de 560), thickness e material (obrigatórios, sem padrão: pergunte se a pessoa não disse), name; id e number opcionais}.\nupdateCountertop: Troca o tampo. Campos: countertop (inteiro).\nremoveCountertop: Apaga o tampo. Campos: countertopId.\naddFinishPart: Peça avulsa (tamponamento, lateral, prateleira, ripado, livre). Campos: finishPart {kind, placement {wallId, offset, elevation?, fromWall?, orientation?}, e o que mudar do modelo: length, width, material, edges, corners, operations; id e number opcionais}.\nupdateFinishPart: Troca a peça avulsa. Campos: finishPart (inteira).\nremoveFinishPart: Apaga a peça avulsa. Campos: finishPartId.","examples":[{"type":"addModule","module":{"catalogItem":"base-doors","width":600,"placement":{"wallId":"parede-1","offset":0}}},{"type":"addAppliance","appliance":{"kind":"oven","placement":{"kind":"niche","moduleId":"torre","zoneIndex":1}}},{"type":"setWallLength","wallId":"parede-1","length":3950},{"type":"addOpening","wallId":"parede-2","opening":{"kind":"window","distanceFromStart":800,"width":1200}}]},"ProjectSummary":{"type":"object","additionalProperties":true,"description":"O projeto em resumo.","properties":{"code":{"type":"string"},"revision":{"type":"integer","description":"Vai em baseRevision ao gravar."},"environments":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"id":{"type":"string"},"code":{"type":"string","description":"AMB-01: o que vai no caminho das operações do ambiente."},"name":{"type":"string"},"placementHint":{"type":"string","description":"Como ler o offset neste ambiente, em português."},"walls":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"id":{"type":"string"},"label":{"type":"string","description":"parede 1, parede 2...: como a pessoa chama."},"length":{"type":"number","description":"Comprimento da face de dentro, em mm."},"startCorner":{"type":"string","enum":["left","right"],"description":"Visto de dentro, de frente pra parede, de que lado fica o canto de início (offset 0)."},"leftWallId":{"type":["string","null"]},"rightWallId":{"type":["string","null"]}}}},"items":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Móveis (B01 balcão, A01 aéreo, T01 torre, P01 painel), eletros (ELE-0001), tampos (TPO-0001) e peças avulsas (PEC-0001), com parede, offset e medidas."},"pendingAdjustments":{"type":"array","items":{"type":"object","additionalProperties":true}}}}},"nextNumbers":{"type":"object","additionalProperties":true}}},"ApplyResult":{"type":"object","additionalProperties":true,"description":"O resultado do lote: applied (false no dryRun), changed, revision, beforeAiVersion, o ambiente em resumo e o que conferir.","properties":{"applied":{"type":"boolean"},"changed":{"type":"boolean","description":"Na gravação: false quando o lote não mudou nada (nada gravado, a revisão, a versão e o registro ficam como estavam)."},"revision":{"type":"integer"},"beforeAiVersion":{"type":["integer","null"],"description":"O número da versão \"Antes da IA\" guardada antes desta gravação, quando houve."},"warnings":{"type":"array","items":{"type":"object"},"description":"Avisos (não seguram a produção)."},"adjustments":{"type":"array","description":"Ajustes pendentes (seguram a produção). Cada um tem key e fixes [{ index, kind, label }]: aplique com { fix: { key, index } }.","items":{"type":"object","additionalProperties":true}},"openingIssues":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Porta, gaveta ou eletro que bate ao abrir (não segura a produção). Cada um tem key e fixes [{ index, kind, label }], aplicados como os ajustes: { fix: { key, index } }. Só os 3 primeiros trazem fixes; os outros, null até os primeiros serem resolvidos."},"buildErrors":{"type":"array","items":{"type":"object"},"description":"Conta de peça que não fecha."},"productionBlocked":{"type":"boolean"},"repeated":{"type":"boolean","description":"true: a mesma Idempotency-Key já tinha gravado este pedido; a resposta traz só applied e a revisão que ele gravou (leia o ambiente pra ver o resultado)."}}}}},"paths":{"/me":{"get":{"operationId":"whoAmI","summary":"Confere a chave","description":"Mostra a empresa, o nome e o escopo (read ou write) da chave. Use pra testar a ligação.","responses":{"200":{"description":"A chave.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/catalog":{"get":{"operationId":"getCatalog","summary":"Catálogo e padrões da empresa","description":"Leia antes de desenhar. Modelos de móvel com as medidas e os limites da empresa, eletros (kind e onde ficam), peças avulsas, padrões de desenho e commands: o guia de todos os comandos com os campos.","responses":{"200":{"description":"O catálogo.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects":{"get":{"operationId":"listProjects","summary":"Lista os projetos","description":"Projetos da empresa, os mexidos por último primeiro, 30 por página. q procura pelo nome ou pelo código.","parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"q","in":"query","description":"Nome ou código do projeto.","schema":{"type":"string","maxLength":120}},{"name":"archived","in":"query","schema":{"type":"string","enum":["true","false"],"default":"false"}}],"responses":{"200":{"description":"Uma página de projetos (projects, total, page).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"createProject","summary":"Cria um projeto vazio","description":"Cria o projeto (chave de escrita), com a revisão 0. Depois crie um ambiente com createEnvironment e baseRevision 0.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string","maxLength":120}}},"example":{"name":"Cozinha da Joana"}}}},"responses":{"201":{"description":"O projeto, com o código e a revisão 0.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects/{code}":{"get":{"operationId":"getProject","summary":"Lê o projeto em resumo","description":"Revisão, ambientes, paredes (id, parede N, comprimento, startCorner e vizinhas), vãos, itens (código, parede, offset, medidas), ajustes pendentes e os próximos números. A revisão daqui vai em baseRevision ao gravar.","parameters":[{"name":"code","in":"path","required":true,"description":"Código do projeto, como PRJ-0001.","schema":{"type":"string","pattern":"^PRJ-\\d{4,9}$"}}],"responses":{"200":{"description":"O projeto em resumo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectSummary"}}}},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects/{code}/environments":{"post":{"operationId":"createEnvironment","summary":"Cria um ambiente no projeto","description":"Sala retangular (width e depth, as medidas de dentro; paredes no sentido anti-horário, parede 1 embaixo) ou vazia (pra desenhar com drawWall). Sai com o padrão de construção da empresa. Precisa de baseRevision.","parameters":[{"name":"code","in":"path","required":true,"description":"Código do projeto, como PRJ-0001.","schema":{"type":"string","pattern":"^PRJ-\\d{4,9}$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Opcional: um UUID novo por gravação. Mandado de novo com o mesmo pedido (a resposta se perdeu), devolve { applied: true, revision, repeated: true } com a revisão que já gravou; a mesma marca com outro pedido é 422 command_id_reused.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","baseRevision"],"additionalProperties":false,"properties":{"name":{"type":"string","maxLength":120},"type":{"type":"string","enum":["kitchen","bedroom","closet","bathroom","commercial","generic"],"default":"kitchen"},"width":{"type":"number","description":"Largura de dentro (paredes 1 e 3). Em mm."},"depth":{"type":"number","description":"Profundidade de dentro (paredes 2 e 4). Em mm."},"ceilingHeight":{"type":"number","description":"Pé direito; pode faltar (padrão da empresa). Em mm."},"wallThickness":{"type":"number","description":"Espessura das paredes; pode faltar (padrão da empresa). Em mm."},"baseRevision":{"type":"integer","description":"A revisão da última leitura (0 no projeto novo)."}}},"examples":{"retangular":{"summary":"Sala de 3,2 x 2,6 m","value":{"name":"Cozinha","type":"kitchen","width":3200,"depth":2600,"baseRevision":0}},"vazia":{"summary":"Sem paredes, pra desenhar com drawWall","value":{"name":"Área de serviço","type":"generic","baseRevision":1}}}}}},"responses":{"201":{"description":"O ambiente em resumo e a revisão nova.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects/{code}/environments/{environment}":{"get":{"operationId":"getEnvironment","summary":"Lê a intenção completa de um ambiente","description":"O ambiente inteiro (paredes, vãos, móveis com zonas, eletros, tampos, peças avulsas, padrão). Use quando for trocar um item com updateModule e parecidos: mande o item inteiro de volta.","parameters":[{"name":"code","in":"path","required":true,"description":"Código do projeto, como PRJ-0001.","schema":{"type":"string","pattern":"^PRJ-\\d{4,9}$"}},{"name":"environment","in":"path","required":true,"description":"Código do ambiente (AMB-01) ou o id dele, como a leitura do projeto devolve.","schema":{"type":"string"}}],"responses":{"200":{"description":"A revisão e o ambiente.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects/{code}/environments/{environment}/commands":{"post":{"operationId":"applyCommands","summary":"Aplica um lote de comandos","description":"Lote de até 550 comandos, tudo ou nada. Comece com dryRun=true (confere sem gravar). Gravar pede baseRevision; revisão velha é 409: leia de novo. fix aplica um conserto de ajuste pendente pela key e pelo index. Lote só de planta: até 50.","parameters":[{"name":"code","in":"path","required":true,"description":"Código do projeto, como PRJ-0001.","schema":{"type":"string","pattern":"^PRJ-\\d{4,9}$"}},{"name":"environment","in":"path","required":true,"description":"Código do ambiente (AMB-01) ou o id dele, como a leitura do projeto devolve.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Opcional: um UUID novo por gravação. Mandado de novo com o mesmo pedido (a resposta se perdeu), devolve { applied: true, revision, repeated: true } com a revisão que já gravou; a mesma marca com outro pedido é 422 command_id_reused.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"commands":{"type":"array","items":{"$ref":"#/components/schemas/Command"},"maxItems":550},"fix":{"type":"object","additionalProperties":false,"required":["key","index"],"properties":{"key":{"type":"string"},"index":{"type":"integer"}},"description":"Conserto de um ajuste pendente (adjustments) ou de um aviso de abertura (openingIssues): a key e o index do conserto, como a resposta anterior mostrou."},"dryRun":{"type":"boolean","default":false,"description":"true: confere e devolve o resultado sem gravar nada (serve com a chave de leitura)."},"baseRevision":{"type":"integer","description":"A revisão da última leitura. Obrigatória pra gravar."}}},"examples":{"cozinhaReta":{"summary":"Cozinha reta na parede 1","description":"Geladeira no canto da direita (offset 0, visto de dentro), depois pia de 80, gaveteiro de 60 e balcão de 40; aéreos em cima dos balcões; tampo de granito de 20 mm sobre os balcões e a cuba na pia.","value":{"dryRun":true,"commands":[{"type":"addAppliance","appliance":{"kind":"fridge","placement":{"kind":"floor","wallId":"parede-1","offset":0}}},{"type":"addModule","module":{"id":"pia","catalogItem":"base-sink","width":800,"placement":{"wallId":"parede-1","offset":700}}},{"type":"addModule","module":{"catalogItem":"base-drawers","width":600,"placement":{"wallId":"parede-1","offset":1500}}},{"type":"addModule","module":{"catalogItem":"base-doors","width":400,"placement":{"wallId":"parede-1","offset":2100}}},{"type":"addModule","module":{"catalogItem":"wall-doors","width":800,"placement":{"wallId":"parede-1","offset":700}}},{"type":"addModule","module":{"catalogItem":"wall-doors","width":600,"placement":{"wallId":"parede-1","offset":1500}}},{"type":"addModule","module":{"catalogItem":"wall-doors","width":400,"placement":{"wallId":"parede-1","offset":2100}}},{"type":"addCountertop","countertop":{"wallId":"parede-1","offset":700,"length":1800,"depth":600,"thickness":20,"material":"Granito"}},{"type":"addAppliance","appliance":{"kind":"sink","placement":{"kind":"countertop","moduleId":"pia","offset":400}}}]}},"gravar":{"summary":"Gravar o que o dryRun conferiu","value":{"baseRevision":1,"commands":[{"type":"addModule","module":{"catalogItem":"base-drawers","width":600,"placement":{"wallId":"parede-1","offset":1500}}}]}},"medidaDaObra":{"summary":"A parede mediu menos na obra","value":{"baseRevision":2,"commands":[{"type":"setWallLength","wallId":"parede-1","length":3950}]}},"conserto":{"summary":"Aplicar um conserto listado em adjustments","value":{"baseRevision":3,"fix":{"key":"<key do ajuste>","index":0}}}}}}},"responses":{"200":{"description":"applied, revision, o ambiente em resumo, avisos, ajustes pendentes (com consertos), problemas de abertura de porta e gaveta e erros de peça.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects/{code}/environments/{environment}/parts":{"get":{"operationId":"getParts","summary":"Lista de peças, ferragens e compras","description":"Peças (medidas prontas e de corte, material, fita), ferragens, compras (tampos com recortes e eletros), fita em metros e chapa em m². Com ajuste pendente responde 409 production_blocked.","parameters":[{"name":"code","in":"path","required":true,"description":"Código do projeto, como PRJ-0001.","schema":{"type":"string","pattern":"^PRJ-\\d{4,9}$"}},{"name":"environment","in":"path","required":true,"description":"Código do ambiente (AMB-01) ou o id dele, como a leitura do projeto devolve.","schema":{"type":"string"}}],"responses":{"200":{"description":"As saídas de produção do ambiente.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects/{code}/environments/{environment}/parts/dxf":{"get":{"operationId":"getPartDxf","summary":"DXF de uma peça","description":"O DXF de uma peça em texto, nas camadas que o Promax CNC lê. part é o código da lista de peças (B01 LAT-E, PEC-0001).","parameters":[{"name":"code","in":"path","required":true,"description":"Código do projeto, como PRJ-0001.","schema":{"type":"string","pattern":"^PRJ-\\d{4,9}$"}},{"name":"environment","in":"path","required":true,"description":"Código do ambiente (AMB-01) ou o id dele, como a leitura do projeto devolve.","schema":{"type":"string"}},{"name":"part","in":"query","required":true,"description":"Código da peça na lista de peças.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"fileName e text.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}}}}