{"openapi":"3.0.0","paths":{"/materials/boards/cross-sync":{"post":{"description":"🇧🇷\n\nFaz cada central de destino ficar com as mesmas chapas da central de origem: chapas que o destino não tinha passam a existir nele, e as que ele já tinha recebem os dados da origem, como código interno e status ativo/inativo.\n\nPreço e estoque só são copiados com `syncPrice: true` e `syncStock: true`. Com `false`, o destino mantém o preço e o estoque que já tinha, e chapas novas no destino ficam com preço e estoque 0.\n\nCom `syncActive: true`, chapas que existem no destino mas não na origem são desativadas no destino. Com `false`, ficam como estão.\n\n`sourceCompanyInternalCode` precisa ser a central do cabeçalho `x-company-internal-code`, e cada código em `targetCompanyInternalCodes` precisa ser de uma central vinculada à mesma api key; se não for, responde 403 e nada é copiado.\n\nA cópia roda em segundo plano: a resposta 202 só confirma que ela foi agendada, e não há rota que informe a conclusão. Para conferir o resultado, liste as chapas com `GET /materials/boards` enviando o código da central de destino em `x-company-internal-code`.\n\nLimite: 1 requisição a cada 5 segundos.\n\n---\n\n🇪🇸\n\nHace que cada central de destino quede con los mismos tableros que la central de origen: los tableros que el destino no tenía se crean en él, y los que ya tenía reciben los datos de la central de origen, como el código interno y el estado activo/inactivo.\n\nEl precio y el stock solo se copian con `syncPrice: true` y `syncStock: true`. Con `false`, el destino conserva el precio y el stock que ya tenía, y los tableros nuevos en el destino quedan con precio y stock 0.\n\nCon `syncActive: true`, los tableros que existen en el destino pero no en el origen se desactivan en el destino. Con `false`, quedan como están.\n\n`sourceCompanyInternalCode` debe ser la central del encabezado `x-company-internal-code`, y cada código en `targetCompanyInternalCodes` debe ser de una central vinculada a la misma api key; si no lo es, responde 403 y no se copia nada.\n\nLa copia se ejecuta en segundo plano: la respuesta 202 solo confirma que fue programada, y no hay una ruta que informe su conclusión. Para verificar el resultado, liste los tableros con `GET /materials/boards` enviando el código de la central de destino en `x-company-internal-code`.\n\nLímite: 1 solicitud cada 5 segundos.\n\n---\n\n🇺🇸\n\nMakes each destination service center end up with the same boards as the source service center: boards the destination didn't have are created in it, and the ones it already had receive the source's data, such as internal code and active/inactive status.\n\nPrice and stock are copied only with `syncPrice: true` and `syncStock: true`. With `false`, the destination keeps the price and stock it already had, and boards new to the destination get price and stock 0.\n\nWith `syncActive: true`, boards that exist in the destination but not in the source are deactivated in the destination. With `false`, they are left as they are.\n\n`sourceCompanyInternalCode` must be the service center in the `x-company-internal-code` header, and each code in `targetCompanyInternalCodes` must belong to a service center linked to the same api key; otherwise, it responds with 403 and nothing is copied.\n\nThe copy runs in the background: the 202 response only confirms that it was scheduled, and no route reports when it finishes. To check the result, list the boards with `GET /materials/boards` sending the destination service center's code in `x-company-internal-code`.\n\nLimit: 1 request every 5 seconds.","operationId":"crossSyncBoards","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossSyncRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"🇧🇷 Central de origem ou de destino sem vínculo com a api key · 🇪🇸 Central de origen o de destino sin vínculo con la api key · 🇺🇸 Source or destination service center not linked to the api key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossSyncResponse"}}}}},"summary":"🇧🇷 Copia as chapas de uma central para outras · 🇪🇸 Copia los tableros de una central a otras · 🇺🇸 Copies boards from one service center to others","tags":["Boards"]}},"/materials/boards":{"get":{"description":"🇧🇷\n\nRetorna as chapas (painéis de MDF, MDP e similares de onde as peças são cortadas) da central autenticada que têm código interno, o código que identifica cada item no seu sistema. Chapas sem código interno não aparecem. Para buscar uma chapa específica, use `GET /materials/boards/{internalCode}`.\n\nPara paginar, envie em `offset` o valor de `meta.next` da resposta anterior; `meta.next` nulo indica a última página. Limite: 1 requisição a cada 5 segundos.\n\n---\n\n🇪🇸\n\nDevuelve los tableros (paneles de MDF, MDP y similares de los que se cortan las piezas) de la central autenticada que tienen código interno, el código que identifica cada ítem en su sistema. Los tableros sin código interno no aparecen. Para buscar un tablero específico, use `GET /materials/boards/{internalCode}`.\n\nPara paginar, envíe en `offset` el valor de `meta.next` de la respuesta anterior; `meta.next` nulo indica la última página. Límite: 1 solicitud cada 5 segundos.\n\n---\n\n🇺🇸\n\nReturns the authenticated service center's boards (MDF, MDP and similar panels the parts are cut from) that have an internal code, the code that identifies each item in your system. Boards without an internal code are not included. To fetch a specific board, use `GET /materials/boards/{internalCode}`.\n\nTo paginate, send in `offset` the `meta.next` value from the previous response; a null `meta.next` means the last page. Limit: 1 request every 5 seconds.","operationId":"listBoards","parameters":[{"name":"limit","required":false,"in":"query","description":"Número máximo de chapas a serem retornadas","schema":{"maximum":500,"exclusiveMinimum":true,"default":500,"type":"integer","minimum":0}},{"name":"offset","required":false,"in":"query","description":"Número de chapas a serem ignoradas antes de começar a retornar os resultados","schema":{"minimum":0,"maximum":9007199254740991,"default":0,"type":"integer"}},{"name":"internal_code","required":false,"in":"query","description":"Código interno específico para buscar uma única chapa","schema":{"type":"string"}}],"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListBoardsResponse"}}}}},"summary":"🇧🇷 Lista as chapas da central · 🇪🇸 Lista los tableros de la central · 🇺🇸 Lists the service center's boards","tags":["Boards"]},"put":{"description":"🇧🇷\n\nAtualiza de uma vez as chapas da central identificadas pelo `internal_code` de cada item. Só os campos enviados mudam; os outros ficam como estão. `PUT` e `PATCH` fazem a mesma coisa.\n\nO corpo pode ser uma lista de chapas, um objeto `{ \"resource\": [...] }` ou uma chapa só.\n\nCada item precisa ter `internal_code`; se faltar em algum, a requisição inteira é recusada com 400 e nada é alterado. Itens cujo `internal_code` não existe na central são ignorados sem erro, e a resposta lista só os códigos atualizados: compare com o que foi enviado para saber quais ficaram de fora.\n\nLimite: 1 requisição a cada 5 segundos.\n\n---\n\n🇪🇸\n\nActualiza de una vez los tableros de la central identificados por el `internal_code` de cada ítem. Solo cambian los campos enviados; los demás quedan como están. `PUT` y `PATCH` hacen lo mismo.\n\nEl cuerpo puede ser una lista de tableros, un objeto `{ \"resource\": [...] }` o un solo tablero.\n\nCada ítem debe tener `internal_code`; si falta en alguno, toda la solicitud se rechaza con 400 y no se modifica nada. Los ítems cuyo `internal_code` no existe en la central se ignoran sin error, y la respuesta lista solo los códigos actualizados: compárela con lo que envió para saber cuáles quedaron fuera.\n\nLímite: 1 solicitud cada 5 segundos.\n\n---\n\n🇺🇸\n\nUpdates, in a single call, the service center's boards identified by each item's `internal_code`. Only the fields sent change; the others are left as they are. `PUT` and `PATCH` do the same thing.\n\nThe body can be a list of boards, a `{ \"resource\": [...] }` object, or a single board.\n\nEvery item must have `internal_code`; if any item lacks it, the whole request is rejected with 400 and nothing is changed. Items whose `internal_code` doesn't exist in the service center are ignored without an error, and the response lists only the updated codes: compare it with what you sent to find out which ones were left out.\n\nLimit: 1 request every 5 seconds.","operationId":"updateBoards","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUpdateBoardsRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ValidationErrorResponse"},{"$ref":"#/components/schemas/LegacyValidationErrorResponse"}]}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUpdateBoardsResponse"}}}}},"summary":"🇧🇷 Atualiza várias chapas · 🇪🇸 Actualiza varios tableros · 🇺🇸 Updates multiple boards","tags":["Boards"]},"patch":{"description":"🇧🇷\n\nAtualiza de uma vez as chapas da central identificadas pelo `internal_code` de cada item. Só os campos enviados mudam; os outros ficam como estão. `PUT` e `PATCH` fazem a mesma coisa.\n\nO corpo pode ser uma lista de chapas, um objeto `{ \"resource\": [...] }` ou uma chapa só.\n\nCada item precisa ter `internal_code`; se faltar em algum, a requisição inteira é recusada com 400 e nada é alterado. Itens cujo `internal_code` não existe na central são ignorados sem erro, e a resposta lista só os códigos atualizados: compare com o que foi enviado para saber quais ficaram de fora.\n\nLimite: 1 requisição a cada 5 segundos.\n\n---\n\n🇪🇸\n\nActualiza de una vez los tableros de la central identificados por el `internal_code` de cada ítem. Solo cambian los campos enviados; los demás quedan como están. `PUT` y `PATCH` hacen lo mismo.\n\nEl cuerpo puede ser una lista de tableros, un objeto `{ \"resource\": [...] }` o un solo tablero.\n\nCada ítem debe tener `internal_code`; si falta en alguno, toda la solicitud se rechaza con 400 y no se modifica nada. Los ítems cuyo `internal_code` no existe en la central se ignoran sin error, y la respuesta lista solo los códigos actualizados: compárela con lo que envió para saber cuáles quedaron fuera.\n\nLímite: 1 solicitud cada 5 segundos.\n\n---\n\n🇺🇸\n\nUpdates, in a single call, the service center's boards identified by each item's `internal_code`. Only the fields sent change; the others are left as they are. `PUT` and `PATCH` do the same thing.\n\nThe body can be a list of boards, a `{ \"resource\": [...] }` object, or a single board.\n\nEvery item must have `internal_code`; if any item lacks it, the whole request is rejected with 400 and nothing is changed. Items whose `internal_code` doesn't exist in the service center are ignored without an error, and the response lists only the updated codes: compare it with what you sent to find out which ones were left out.\n\nLimit: 1 request every 5 seconds.","operationId":"patchBoards","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUpdateBoardsRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ValidationErrorResponse"},{"$ref":"#/components/schemas/LegacyValidationErrorResponse"}]}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUpdateBoardsResponse"}}}}},"summary":"🇧🇷 Atualiza várias chapas · 🇪🇸 Actualiza varios tableros · 🇺🇸 Updates multiple boards","tags":["Boards"]}},"/materials/boards/{internalCode}":{"get":{"description":"🇧🇷\n\nRetorna a chapa da central com o código interno informado na URL. Responde 404 quando a central não tem uma chapa com esse código.\n\n---\n\n🇪🇸\n\nDevuelve el tablero de la central con el código interno indicado en la URL. Responde 404 cuando la central no tiene un tablero con ese código.\n\n---\n\n🇺🇸\n\nReturns the service center's board with the internal code given in the URL. Responds with 404 when the service center has no board with that code.","operationId":"getBoard","parameters":[{"name":"internalCode","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"🇧🇷 Chapa não encontrada na central · 🇪🇸 Tablero no encontrado en la central · 🇺🇸 Board not found in the service center","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBoardResponse"}}}}},"summary":"🇧🇷 Consulta uma chapa · 🇪🇸 Consulta un tablero · 🇺🇸 Gets a board","tags":["Boards"]},"put":{"description":"🇧🇷\n\nAtualiza a chapa da central com o código interno informado na URL. Só os campos enviados mudam; os outros ficam como estão. `PUT` e `PATCH` fazem a mesma coisa.\n\nSe o corpo também trouxer `internal_code`, vale o do corpo: a chapa atualizada é a que tem esse código, e não a da URL.\n\nResponde 404 quando a central não tem uma chapa com esse código.\n\n---\n\n🇪🇸\n\nActualiza el tablero de la central con el código interno indicado en la URL. Solo cambian los campos enviados; los demás quedan como están. `PUT` y `PATCH` hacen lo mismo.\n\nSi el cuerpo también trae `internal_code`, prevalece el del cuerpo: el tablero actualizado es el que tiene ese código, y no el de la URL.\n\nResponde 404 cuando la central no tiene un tablero con ese código.\n\n---\n\n🇺🇸\n\nUpdates the service center's board with the internal code given in the URL. Only the fields sent change; the others are left as they are. `PUT` and `PATCH` do the same thing.\n\nIf the body also includes `internal_code`, the one in the body wins: the board updated is the one with that code, not the one in the URL.\n\nResponds with 404 when the service center has no board with that code.","operationId":"updateBoard","parameters":[{"name":"internalCode","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBoardRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"🇧🇷 Chapa não encontrada na central · 🇪🇸 Tablero no encontrado en la central · 🇺🇸 Board not found in the service center","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBoardResponse"}}}}},"summary":"🇧🇷 Atualiza uma chapa · 🇪🇸 Actualiza un tablero · 🇺🇸 Updates a board","tags":["Boards"]},"patch":{"description":"🇧🇷\n\nAtualiza a chapa da central com o código interno informado na URL. Só os campos enviados mudam; os outros ficam como estão. `PUT` e `PATCH` fazem a mesma coisa.\n\nSe o corpo também trouxer `internal_code`, vale o do corpo: a chapa atualizada é a que tem esse código, e não a da URL.\n\nResponde 404 quando a central não tem uma chapa com esse código.\n\n---\n\n🇪🇸\n\nActualiza el tablero de la central con el código interno indicado en la URL. Solo cambian los campos enviados; los demás quedan como están. `PUT` y `PATCH` hacen lo mismo.\n\nSi el cuerpo también trae `internal_code`, prevalece el del cuerpo: el tablero actualizado es el que tiene ese código, y no el de la URL.\n\nResponde 404 cuando la central no tiene un tablero con ese código.\n\n---\n\n🇺🇸\n\nUpdates the service center's board with the internal code given in the URL. Only the fields sent change; the others are left as they are. `PUT` and `PATCH` do the same thing.\n\nIf the body also includes `internal_code`, the one in the body wins: the board updated is the one with that code, not the one in the URL.\n\nResponds with 404 when the service center has no board with that code.","operationId":"patchBoard","parameters":[{"name":"internalCode","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBoardRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"🇧🇷 Chapa não encontrada na central · 🇪🇸 Tablero no encontrado en la central · 🇺🇸 Board not found in the service center","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBoardResponse"}}}}},"summary":"🇧🇷 Atualiza uma chapa · 🇪🇸 Actualiza un tablero · 🇺🇸 Updates a board","tags":["Boards"]}},"/materials/components/cross-sync":{"post":{"description":"🇧🇷\n\nFaz cada central de destino ficar com os mesmos componentes da central de origem: componentes que o destino não tinha passam a existir nele, e os que ele já tinha recebem os dados da origem, como código interno e status ativo/inativo.\n\nPreço e estoque só são copiados com `syncPrice: true` e `syncStock: true`. Com `false`, o destino mantém o preço e o estoque que já tinha, e componentes novos no destino ficam com preço e estoque 0.\n\nCom `syncActive: true`, componentes que existem no destino mas não na origem são desativados no destino. Com `false`, ficam como estão.\n\n`sourceCompanyInternalCode` precisa ser a central do cabeçalho `x-company-internal-code`, e cada código em `targetCompanyInternalCodes` precisa ser de uma central vinculada à mesma api key; se não for, responde 403 e nada é copiado.\n\nA cópia roda em segundo plano: a resposta 202 só confirma que ela foi agendada, e não há rota que informe a conclusão. Para conferir o resultado, liste os componentes com `GET /materials/components` enviando o código da central de destino em `x-company-internal-code`.\n\nLimite: 1 requisição a cada 5 segundos.\n\n---\n\n🇪🇸\n\nHace que cada central de destino quede con los mismos componentes que la central de origen: los componentes que el destino no tenía se crean en él, y los que ya tenía reciben los datos de la central de origen, como el código interno y el estado activo/inactivo.\n\nEl precio y el stock solo se copian con `syncPrice: true` y `syncStock: true`. Con `false`, el destino conserva el precio y el stock que ya tenía, y los componentes nuevos en el destino quedan con precio y stock 0.\n\nCon `syncActive: true`, los componentes que existen en el destino pero no en el origen se desactivan en el destino. Con `false`, quedan como están.\n\n`sourceCompanyInternalCode` debe ser la central del encabezado `x-company-internal-code`, y cada código en `targetCompanyInternalCodes` debe ser de una central vinculada a la misma api key; si no lo es, responde 403 y no se copia nada.\n\nLa copia se ejecuta en segundo plano: la respuesta 202 solo confirma que fue programada, y no hay una ruta que informe su conclusión. Para verificar el resultado, liste los componentes con `GET /materials/components` enviando el código de la central de destino en `x-company-internal-code`.\n\nLímite: 1 solicitud cada 5 segundos.\n\n---\n\n🇺🇸\n\nMakes each destination service center end up with the same hardware components as the source service center: hardware components the destination didn't have are created in it, and the ones it already had receive the source's data, such as internal code and active/inactive status.\n\nPrice and stock are copied only with `syncPrice: true` and `syncStock: true`. With `false`, the destination keeps the price and stock it already had, and hardware components new to the destination get price and stock 0.\n\nWith `syncActive: true`, hardware components that exist in the destination but not in the source are deactivated in the destination. With `false`, they are left as they are.\n\n`sourceCompanyInternalCode` must be the service center in the `x-company-internal-code` header, and each code in `targetCompanyInternalCodes` must belong to a service center linked to the same api key; otherwise, it responds with 403 and nothing is copied.\n\nThe copy runs in the background: the 202 response only confirms that it was scheduled, and no route reports when it finishes. To check the result, list the hardware components with `GET /materials/components` sending the destination service center's code in `x-company-internal-code`.\n\nLimit: 1 request every 5 seconds.","operationId":"crossSyncComponents","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossSyncRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"🇧🇷 Central de origem ou de destino sem vínculo com a api key · 🇪🇸 Central de origen o de destino sin vínculo con la api key · 🇺🇸 Source or destination service center not linked to the api key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossSyncResponse"}}}}},"summary":"🇧🇷 Copia os componentes de uma central para outras · 🇪🇸 Copia los componentes de una central a otras · 🇺🇸 Copies hardware components from one service center to others","tags":["Components"]}},"/materials/components":{"get":{"description":"🇧🇷\n\nRetorna os componentes (ferragens e acessórios, como dobradiças, corrediças e puxadores) da central autenticada que têm código interno, o código que identifica cada item no seu sistema. Componentes sem código interno não aparecem. Para buscar um componente específico, use `GET /materials/components/{internalCode}`.\n\nPara paginar, envie em `offset` o valor de `meta.next` da resposta anterior; `meta.next` nulo indica a última página. Limite: 1 requisição a cada 5 segundos.\n\n---\n\n🇪🇸\n\nDevuelve los componentes (herrajes y accesorios, como bisagras, correderas y tiradores) de la central autenticada que tienen código interno, el código que identifica cada ítem en su sistema. Los componentes sin código interno no aparecen. Para buscar un componente específico, use `GET /materials/components/{internalCode}`.\n\nPara paginar, envíe en `offset` el valor de `meta.next` de la respuesta anterior; `meta.next` nulo indica la última página. Límite: 1 solicitud cada 5 segundos.\n\n---\n\n🇺🇸\n\nReturns the authenticated service center's hardware components (fittings and accessories, such as hinges, drawer slides and handles) that have an internal code, the code that identifies each item in your system. Hardware components without an internal code are not included. To fetch a specific hardware component, use `GET /materials/components/{internalCode}`.\n\nTo paginate, send in `offset` the `meta.next` value from the previous response; a null `meta.next` means the last page. Limit: 1 request every 5 seconds.","operationId":"listComponents","parameters":[{"name":"limit","required":false,"in":"query","description":"Número máximo de componentes a serem retornados","schema":{"maximum":500,"exclusiveMinimum":true,"default":500,"type":"integer","minimum":0}},{"name":"offset","required":false,"in":"query","description":"Número de componentes a serem ignorados antes de começar a retornar os resultados","schema":{"minimum":0,"maximum":9007199254740991,"default":0,"type":"integer"}},{"name":"internal_code","required":false,"in":"query","description":"Código interno específico para buscar um único componente","schema":{"type":"string"}}],"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListComponentsResponse"}}}}},"summary":"🇧🇷 Lista os componentes da central · 🇪🇸 Lista los componentes de la central · 🇺🇸 Lists the service center's hardware components","tags":["Components"]},"put":{"description":"🇧🇷\n\nAtualiza de uma vez os componentes da central identificados pelo `internal_code` de cada item. Só os campos enviados mudam; os outros ficam como estão. `PUT` e `PATCH` fazem a mesma coisa.\n\nO corpo pode ser uma lista de componentes, um objeto `{ \"resource\": [...] }` ou um componente só.\n\nCada item precisa ter `internal_code`; se faltar em algum, a requisição inteira é recusada com 400 e nada é alterado. Itens cujo `internal_code` não existe na central são ignorados sem erro, e a resposta lista só os códigos atualizados: compare com o que foi enviado para saber quais ficaram de fora.\n\nLimite: 1 requisição a cada 5 segundos.\n\n---\n\n🇪🇸\n\nActualiza de una vez los componentes de la central identificados por el `internal_code` de cada ítem. Solo cambian los campos enviados; los demás quedan como están. `PUT` y `PATCH` hacen lo mismo.\n\nEl cuerpo puede ser una lista de componentes, un objeto `{ \"resource\": [...] }` o un solo componente.\n\nCada ítem debe tener `internal_code`; si falta en alguno, toda la solicitud se rechaza con 400 y no se modifica nada. Los ítems cuyo `internal_code` no existe en la central se ignoran sin error, y la respuesta lista solo los códigos actualizados: compárela con lo que envió para saber cuáles quedaron fuera.\n\nLímite: 1 solicitud cada 5 segundos.\n\n---\n\n🇺🇸\n\nUpdates, in a single call, the service center's hardware components identified by each item's `internal_code`. Only the fields sent change; the others are left as they are. `PUT` and `PATCH` do the same thing.\n\nThe body can be a list of hardware components, a `{ \"resource\": [...] }` object, or a single hardware component.\n\nEvery item must have `internal_code`; if any item lacks it, the whole request is rejected with 400 and nothing is changed. Items whose `internal_code` doesn't exist in the service center are ignored without an error, and the response lists only the updated codes: compare it with what you sent to find out which ones were left out.\n\nLimit: 1 request every 5 seconds.","operationId":"updateComponents","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUpdateComponentsRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ValidationErrorResponse"},{"$ref":"#/components/schemas/LegacyValidationErrorResponse"}]}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUpdateComponentsResponse"}}}}},"summary":"🇧🇷 Atualiza vários componentes · 🇪🇸 Actualiza varios componentes · 🇺🇸 Updates multiple hardware components","tags":["Components"]},"patch":{"description":"🇧🇷\n\nAtualiza de uma vez os componentes da central identificados pelo `internal_code` de cada item. Só os campos enviados mudam; os outros ficam como estão. `PUT` e `PATCH` fazem a mesma coisa.\n\nO corpo pode ser uma lista de componentes, um objeto `{ \"resource\": [...] }` ou um componente só.\n\nCada item precisa ter `internal_code`; se faltar em algum, a requisição inteira é recusada com 400 e nada é alterado. Itens cujo `internal_code` não existe na central são ignorados sem erro, e a resposta lista só os códigos atualizados: compare com o que foi enviado para saber quais ficaram de fora.\n\nLimite: 1 requisição a cada 5 segundos.\n\n---\n\n🇪🇸\n\nActualiza de una vez los componentes de la central identificados por el `internal_code` de cada ítem. Solo cambian los campos enviados; los demás quedan como están. `PUT` y `PATCH` hacen lo mismo.\n\nEl cuerpo puede ser una lista de componentes, un objeto `{ \"resource\": [...] }` o un solo componente.\n\nCada ítem debe tener `internal_code`; si falta en alguno, toda la solicitud se rechaza con 400 y no se modifica nada. Los ítems cuyo `internal_code` no existe en la central se ignoran sin error, y la respuesta lista solo los códigos actualizados: compárela con lo que envió para saber cuáles quedaron fuera.\n\nLímite: 1 solicitud cada 5 segundos.\n\n---\n\n🇺🇸\n\nUpdates, in a single call, the service center's hardware components identified by each item's `internal_code`. Only the fields sent change; the others are left as they are. `PUT` and `PATCH` do the same thing.\n\nThe body can be a list of hardware components, a `{ \"resource\": [...] }` object, or a single hardware component.\n\nEvery item must have `internal_code`; if any item lacks it, the whole request is rejected with 400 and nothing is changed. Items whose `internal_code` doesn't exist in the service center are ignored without an error, and the response lists only the updated codes: compare it with what you sent to find out which ones were left out.\n\nLimit: 1 request every 5 seconds.","operationId":"patchComponents","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUpdateComponentsRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ValidationErrorResponse"},{"$ref":"#/components/schemas/LegacyValidationErrorResponse"}]}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUpdateComponentsResponse"}}}}},"summary":"🇧🇷 Atualiza vários componentes · 🇪🇸 Actualiza varios componentes · 🇺🇸 Updates multiple hardware components","tags":["Components"]}},"/materials/components/{internalCode}":{"get":{"description":"🇧🇷\n\nRetorna o componente da central com o código interno informado na URL. Responde 404 quando a central não tem um componente com esse código.\n\n---\n\n🇪🇸\n\nDevuelve el componente de la central con el código interno indicado en la URL. Responde 404 cuando la central no tiene un componente con ese código.\n\n---\n\n🇺🇸\n\nReturns the service center's hardware component with the internal code given in the URL. Responds with 404 when the service center has no hardware component with that code.","operationId":"getComponent","parameters":[{"name":"internalCode","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"🇧🇷 Componente não encontrado na central · 🇪🇸 Componente no encontrado en la central · 🇺🇸 Hardware component not found in the service center","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetComponentResponse"}}}}},"summary":"🇧🇷 Consulta um componente · 🇪🇸 Consulta un componente · 🇺🇸 Gets a hardware component","tags":["Components"]},"put":{"description":"🇧🇷\n\nAtualiza o componente da central com o código interno informado na URL. Só os campos enviados mudam; os outros ficam como estão. `PUT` e `PATCH` fazem a mesma coisa.\n\nSe o corpo também trouxer `internal_code`, vale o do corpo: o componente atualizado é o que tem esse código, e não o da URL.\n\nResponde 404 quando a central não tem um componente com esse código.\n\n---\n\n🇪🇸\n\nActualiza el componente de la central con el código interno indicado en la URL. Solo cambian los campos enviados; los demás quedan como están. `PUT` y `PATCH` hacen lo mismo.\n\nSi el cuerpo también trae `internal_code`, prevalece el del cuerpo: el componente actualizado es el que tiene ese código, y no el de la URL.\n\nResponde 404 cuando la central no tiene un componente con ese código.\n\n---\n\n🇺🇸\n\nUpdates the service center's hardware component with the internal code given in the URL. Only the fields sent change; the others are left as they are. `PUT` and `PATCH` do the same thing.\n\nIf the body also includes `internal_code`, the one in the body wins: the hardware component updated is the one with that code, not the one in the URL.\n\nResponds with 404 when the service center has no hardware component with that code.","operationId":"updateComponent","parameters":[{"name":"internalCode","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateComponentRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"🇧🇷 Componente não encontrado na central · 🇪🇸 Componente no encontrado en la central · 🇺🇸 Hardware component not found in the service center","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateComponentResponse"}}}}},"summary":"🇧🇷 Atualiza um componente · 🇪🇸 Actualiza un componente · 🇺🇸 Updates a hardware component","tags":["Components"]},"patch":{"description":"🇧🇷\n\nAtualiza o componente da central com o código interno informado na URL. Só os campos enviados mudam; os outros ficam como estão. `PUT` e `PATCH` fazem a mesma coisa.\n\nSe o corpo também trouxer `internal_code`, vale o do corpo: o componente atualizado é o que tem esse código, e não o da URL.\n\nResponde 404 quando a central não tem um componente com esse código.\n\n---\n\n🇪🇸\n\nActualiza el componente de la central con el código interno indicado en la URL. Solo cambian los campos enviados; los demás quedan como están. `PUT` y `PATCH` hacen lo mismo.\n\nSi el cuerpo también trae `internal_code`, prevalece el del cuerpo: el componente actualizado es el que tiene ese código, y no el de la URL.\n\nResponde 404 cuando la central no tiene un componente con ese código.\n\n---\n\n🇺🇸\n\nUpdates the service center's hardware component with the internal code given in the URL. Only the fields sent change; the others are left as they are. `PUT` and `PATCH` do the same thing.\n\nIf the body also includes `internal_code`, the one in the body wins: the hardware component updated is the one with that code, not the one in the URL.\n\nResponds with 404 when the service center has no hardware component with that code.","operationId":"patchComponent","parameters":[{"name":"internalCode","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateComponentRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"🇧🇷 Componente não encontrado na central · 🇪🇸 Componente no encontrado en la central · 🇺🇸 Hardware component not found in the service center","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateComponentResponse"}}}}},"summary":"🇧🇷 Atualiza um componente · 🇪🇸 Actualiza un componente · 🇺🇸 Updates a hardware component","tags":["Components"]}},"/materials/edges/cross-sync":{"post":{"description":"🇧🇷\n\nFaz cada central de destino ficar com as mesmas fitas de borda da central de origem: fitas de borda que o destino não tinha passam a existir nele, e as que ele já tinha recebem os dados da origem, como código interno e status ativo/inativo.\n\nPreço e estoque só são copiados com `syncPrice: true` e `syncStock: true`. Com `false`, o destino mantém o preço e o estoque que já tinha, e fitas de borda novas no destino ficam com preço e estoque 0.\n\nCom `syncActive: true`, fitas de borda que existem no destino mas não na origem são desativadas no destino. Com `false`, ficam como estão.\n\n`sourceCompanyInternalCode` precisa ser a central do cabeçalho `x-company-internal-code`, e cada código em `targetCompanyInternalCodes` precisa ser de uma central vinculada à mesma api key; se não for, responde 403 e nada é copiado.\n\nA cópia roda em segundo plano: a resposta 202 só confirma que ela foi agendada, e não há rota que informe a conclusão. Para conferir o resultado, liste as fitas de borda com `GET /materials/edges` enviando o código da central de destino em `x-company-internal-code`.\n\nLimite: 1 requisição a cada 5 segundos.\n\n---\n\n🇪🇸\n\nHace que cada central de destino quede con los mismos tapacantos que la central de origen: los tapacantos que el destino no tenía se crean en él, y los que ya tenía reciben los datos de la central de origen, como el código interno y el estado activo/inactivo.\n\nEl precio y el stock solo se copian con `syncPrice: true` y `syncStock: true`. Con `false`, el destino conserva el precio y el stock que ya tenía, y los tapacantos nuevos en el destino quedan con precio y stock 0.\n\nCon `syncActive: true`, los tapacantos que existen en el destino pero no en el origen se desactivan en el destino. Con `false`, quedan como están.\n\n`sourceCompanyInternalCode` debe ser la central del encabezado `x-company-internal-code`, y cada código en `targetCompanyInternalCodes` debe ser de una central vinculada a la misma api key; si no lo es, responde 403 y no se copia nada.\n\nLa copia se ejecuta en segundo plano: la respuesta 202 solo confirma que fue programada, y no hay una ruta que informe su conclusión. Para verificar el resultado, liste los tapacantos con `GET /materials/edges` enviando el código de la central de destino en `x-company-internal-code`.\n\nLímite: 1 solicitud cada 5 segundos.\n\n---\n\n🇺🇸\n\nMakes each destination service center end up with the same edge banding items as the source service center: edge banding items the destination didn't have are created in it, and the ones it already had receive the source's data, such as internal code and active/inactive status.\n\nPrice and stock are copied only with `syncPrice: true` and `syncStock: true`. With `false`, the destination keeps the price and stock it already had, and edge banding items new to the destination get price and stock 0.\n\nWith `syncActive: true`, edge banding items that exist in the destination but not in the source are deactivated in the destination. With `false`, they are left as they are.\n\n`sourceCompanyInternalCode` must be the service center in the `x-company-internal-code` header, and each code in `targetCompanyInternalCodes` must belong to a service center linked to the same api key; otherwise, it responds with 403 and nothing is copied.\n\nThe copy runs in the background: the 202 response only confirms that it was scheduled, and no route reports when it finishes. To check the result, list the edge banding items with `GET /materials/edges` sending the destination service center's code in `x-company-internal-code`.\n\nLimit: 1 request every 5 seconds.","operationId":"crossSyncEdges","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossSyncRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"🇧🇷 Central de origem ou de destino sem vínculo com a api key · 🇪🇸 Central de origen o de destino sin vínculo con la api key · 🇺🇸 Source or destination service center not linked to the api key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossSyncResponse"}}}}},"summary":"🇧🇷 Copia as fitas de borda de uma central para outras · 🇪🇸 Copia los tapacantos de una central a otras · 🇺🇸 Copies edge banding from one service center to others","tags":["Edges"]}},"/materials/edges":{"get":{"description":"🇧🇷\n\nRetorna as fitas de borda (fitas que revestem as bordas das peças cortadas) da central autenticada que têm código interno, o código que identifica cada item no seu sistema. Fitas de borda sem código interno não aparecem. Para buscar uma fita de borda específica, use `GET /materials/edges/{internalCode}`.\n\nPara paginar, envie em `offset` o valor de `meta.next` da resposta anterior; `meta.next` nulo indica a última página. Limite: 1 requisição a cada 5 segundos.\n\n---\n\n🇪🇸\n\nDevuelve los tapacantos (cintas que recubren los cantos de las piezas cortadas) de la central autenticada que tienen código interno, el código que identifica cada ítem en su sistema. Los tapacantos sin código interno no aparecen. Para buscar un tapacanto específico, use `GET /materials/edges/{internalCode}`.\n\nPara paginar, envíe en `offset` el valor de `meta.next` de la respuesta anterior; `meta.next` nulo indica la última página. Límite: 1 solicitud cada 5 segundos.\n\n---\n\n🇺🇸\n\nReturns the authenticated service center's edge banding items (strips that cover the edges of the cut parts) that have an internal code, the code that identifies each item in your system. Edge banding items without an internal code are not included. To fetch a specific edge banding item, use `GET /materials/edges/{internalCode}`.\n\nTo paginate, send in `offset` the `meta.next` value from the previous response; a null `meta.next` means the last page. Limit: 1 request every 5 seconds.","operationId":"listEdges","parameters":[{"name":"limit","required":false,"in":"query","description":"Número máximo de fitas a serem retornadas","schema":{"maximum":500,"exclusiveMinimum":true,"default":500,"type":"integer","minimum":0}},{"name":"offset","required":false,"in":"query","description":"Número de fitas a serem ignoradas antes de começar a retornar os resultados","schema":{"minimum":0,"maximum":9007199254740991,"default":0,"type":"integer"}},{"name":"internal_code","required":false,"in":"query","description":"Código interno específico para buscar uma única fita","schema":{"type":"string"}}],"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEdgesResponse"}}}}},"summary":"🇧🇷 Lista as fitas de borda da central · 🇪🇸 Lista los tapacantos de la central · 🇺🇸 Lists the service center's edge banding","tags":["Edges"]},"put":{"description":"🇧🇷\n\nAtualiza de uma vez as fitas de borda da central identificadas pelo `internal_code` de cada item. Só os campos enviados mudam; os outros ficam como estão. `PUT` e `PATCH` fazem a mesma coisa.\n\nO corpo pode ser uma lista de fitas de borda, um objeto `{ \"resource\": [...] }` ou uma fita de borda só.\n\nCada item precisa ter `internal_code`; se faltar em algum, a requisição inteira é recusada com 400 e nada é alterado. Itens cujo `internal_code` não existe na central são ignorados sem erro, e a resposta lista só os códigos atualizados: compare com o que foi enviado para saber quais ficaram de fora.\n\nLimite: 1 requisição a cada 5 segundos.\n\n---\n\n🇪🇸\n\nActualiza de una vez los tapacantos de la central identificados por el `internal_code` de cada ítem. Solo cambian los campos enviados; los demás quedan como están. `PUT` y `PATCH` hacen lo mismo.\n\nEl cuerpo puede ser una lista de tapacantos, un objeto `{ \"resource\": [...] }` o un solo tapacanto.\n\nCada ítem debe tener `internal_code`; si falta en alguno, toda la solicitud se rechaza con 400 y no se modifica nada. Los ítems cuyo `internal_code` no existe en la central se ignoran sin error, y la respuesta lista solo los códigos actualizados: compárela con lo que envió para saber cuáles quedaron fuera.\n\nLímite: 1 solicitud cada 5 segundos.\n\n---\n\n🇺🇸\n\nUpdates, in a single call, the service center's edge banding items identified by each item's `internal_code`. Only the fields sent change; the others are left as they are. `PUT` and `PATCH` do the same thing.\n\nThe body can be a list of edge banding items, a `{ \"resource\": [...] }` object, or a single edge banding item.\n\nEvery item must have `internal_code`; if any item lacks it, the whole request is rejected with 400 and nothing is changed. Items whose `internal_code` doesn't exist in the service center are ignored without an error, and the response lists only the updated codes: compare it with what you sent to find out which ones were left out.\n\nLimit: 1 request every 5 seconds.","operationId":"updateEdges","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUpdateEdgesRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ValidationErrorResponse"},{"$ref":"#/components/schemas/LegacyValidationErrorResponse"}]}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUpdateEdgesResponse"}}}}},"summary":"🇧🇷 Atualiza várias fitas de borda · 🇪🇸 Actualiza varios tapacantos · 🇺🇸 Updates multiple edge banding items","tags":["Edges"]},"patch":{"description":"🇧🇷\n\nAtualiza de uma vez as fitas de borda da central identificadas pelo `internal_code` de cada item. Só os campos enviados mudam; os outros ficam como estão. `PUT` e `PATCH` fazem a mesma coisa.\n\nO corpo pode ser uma lista de fitas de borda, um objeto `{ \"resource\": [...] }` ou uma fita de borda só.\n\nCada item precisa ter `internal_code`; se faltar em algum, a requisição inteira é recusada com 400 e nada é alterado. Itens cujo `internal_code` não existe na central são ignorados sem erro, e a resposta lista só os códigos atualizados: compare com o que foi enviado para saber quais ficaram de fora.\n\nLimite: 1 requisição a cada 5 segundos.\n\n---\n\n🇪🇸\n\nActualiza de una vez los tapacantos de la central identificados por el `internal_code` de cada ítem. Solo cambian los campos enviados; los demás quedan como están. `PUT` y `PATCH` hacen lo mismo.\n\nEl cuerpo puede ser una lista de tapacantos, un objeto `{ \"resource\": [...] }` o un solo tapacanto.\n\nCada ítem debe tener `internal_code`; si falta en alguno, toda la solicitud se rechaza con 400 y no se modifica nada. Los ítems cuyo `internal_code` no existe en la central se ignoran sin error, y la respuesta lista solo los códigos actualizados: compárela con lo que envió para saber cuáles quedaron fuera.\n\nLímite: 1 solicitud cada 5 segundos.\n\n---\n\n🇺🇸\n\nUpdates, in a single call, the service center's edge banding items identified by each item's `internal_code`. Only the fields sent change; the others are left as they are. `PUT` and `PATCH` do the same thing.\n\nThe body can be a list of edge banding items, a `{ \"resource\": [...] }` object, or a single edge banding item.\n\nEvery item must have `internal_code`; if any item lacks it, the whole request is rejected with 400 and nothing is changed. Items whose `internal_code` doesn't exist in the service center are ignored without an error, and the response lists only the updated codes: compare it with what you sent to find out which ones were left out.\n\nLimit: 1 request every 5 seconds.","operationId":"patchEdges","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUpdateEdgesRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ValidationErrorResponse"},{"$ref":"#/components/schemas/LegacyValidationErrorResponse"}]}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUpdateEdgesResponse"}}}}},"summary":"🇧🇷 Atualiza várias fitas de borda · 🇪🇸 Actualiza varios tapacantos · 🇺🇸 Updates multiple edge banding items","tags":["Edges"]}},"/materials/edges/{internalCode}":{"get":{"description":"🇧🇷\n\nRetorna a fita de borda da central com o código interno informado na URL. Responde 404 quando a central não tem uma fita de borda com esse código.\n\n---\n\n🇪🇸\n\nDevuelve el tapacanto de la central con el código interno indicado en la URL. Responde 404 cuando la central no tiene un tapacanto con ese código.\n\n---\n\n🇺🇸\n\nReturns the service center's edge banding item with the internal code given in the URL. Responds with 404 when the service center has no edge banding item with that code.","operationId":"getEdge","parameters":[{"name":"internalCode","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"🇧🇷 Fita de borda não encontrada na central · 🇪🇸 Tapacanto no encontrado en la central · 🇺🇸 Edge banding item not found in the service center","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetEdgeResponse"}}}}},"summary":"🇧🇷 Consulta uma fita de borda · 🇪🇸 Consulta un tapacanto · 🇺🇸 Gets an edge banding item","tags":["Edges"]},"put":{"description":"🇧🇷\n\nAtualiza a fita de borda da central com o código interno informado na URL. Só os campos enviados mudam; os outros ficam como estão. `PUT` e `PATCH` fazem a mesma coisa.\n\nSe o corpo também trouxer `internal_code`, vale o do corpo: a fita de borda atualizada é a que tem esse código, e não a da URL.\n\nResponde 404 quando a central não tem uma fita de borda com esse código.\n\n---\n\n🇪🇸\n\nActualiza el tapacanto de la central con el código interno indicado en la URL. Solo cambian los campos enviados; los demás quedan como están. `PUT` y `PATCH` hacen lo mismo.\n\nSi el cuerpo también trae `internal_code`, prevalece el del cuerpo: el tapacanto actualizado es el que tiene ese código, y no el de la URL.\n\nResponde 404 cuando la central no tiene un tapacanto con ese código.\n\n---\n\n🇺🇸\n\nUpdates the service center's edge banding item with the internal code given in the URL. Only the fields sent change; the others are left as they are. `PUT` and `PATCH` do the same thing.\n\nIf the body also includes `internal_code`, the one in the body wins: the edge banding item updated is the one with that code, not the one in the URL.\n\nResponds with 404 when the service center has no edge banding item with that code.","operationId":"updateEdge","parameters":[{"name":"internalCode","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEdgeRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"🇧🇷 Fita de borda não encontrada na central · 🇪🇸 Tapacanto no encontrado en la central · 🇺🇸 Edge banding item not found in the service center","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEdgeResponse"}}}}},"summary":"🇧🇷 Atualiza uma fita de borda · 🇪🇸 Actualiza un tapacanto · 🇺🇸 Updates an edge banding item","tags":["Edges"]},"patch":{"description":"🇧🇷\n\nAtualiza a fita de borda da central com o código interno informado na URL. Só os campos enviados mudam; os outros ficam como estão. `PUT` e `PATCH` fazem a mesma coisa.\n\nSe o corpo também trouxer `internal_code`, vale o do corpo: a fita de borda atualizada é a que tem esse código, e não a da URL.\n\nResponde 404 quando a central não tem uma fita de borda com esse código.\n\n---\n\n🇪🇸\n\nActualiza el tapacanto de la central con el código interno indicado en la URL. Solo cambian los campos enviados; los demás quedan como están. `PUT` y `PATCH` hacen lo mismo.\n\nSi el cuerpo también trae `internal_code`, prevalece el del cuerpo: el tapacanto actualizado es el que tiene ese código, y no el de la URL.\n\nResponde 404 cuando la central no tiene un tapacanto con ese código.\n\n---\n\n🇺🇸\n\nUpdates the service center's edge banding item with the internal code given in the URL. Only the fields sent change; the others are left as they are. `PUT` and `PATCH` do the same thing.\n\nIf the body also includes `internal_code`, the one in the body wins: the edge banding item updated is the one with that code, not the one in the URL.\n\nResponds with 404 when the service center has no edge banding item with that code.","operationId":"patchEdge","parameters":[{"name":"internalCode","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEdgeRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"🇧🇷 Fita de borda não encontrada na central · 🇪🇸 Tapacanto no encontrado en la central · 🇺🇸 Edge banding item not found in the service center","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEdgeResponse"}}}}},"summary":"🇧🇷 Atualiza uma fita de borda · 🇪🇸 Actualiza un tapacanto · 🇺🇸 Updates an edge banding item","tags":["Edges"]}},"/services":{"get":{"description":"🇧🇷\n\nUm serviço é um pedido de peças de móveis cortadas sob medida, feito no Cortecloud por um marceneiro (ou por um vendedor em nome dele) à central. Corresponde a um pedido no seu ERP.\n\nRetorna id, código interno, status e datas de cada serviço; para o conteúdo completo, use `GET /services/{id}`.\n\nPor padrão, traz os serviços em todos os status abaixo; use `status` para restringir:\n- `4`: orçamento gerado, aguardando aprovação do cliente;\n- `25`: aguardando pagamento online;\n- `6`: aprovado pelo cliente;\n- `7`: enviado para produção;\n- `9`: produzido.\n\nOutros códigos em `status` são recusados com 400.\n\n`internal_code=null` traz só os serviços ainda sem código interno; para buscar pedidos novos para o ERP, combine com `status=6`. `date_start` e `date_end` filtram pela data da última alteração do serviço.\n\nPara paginar, envie em `offset` o valor de `meta.next` da resposta anterior; `meta.next` nulo indica a última página. Limite: 1 requisição a cada 5 segundos.\n\n---\n\n🇪🇸\n\nUn servicio es un pedido de piezas de muebles cortadas a medida, hecho en Cortecloud por un carpintero (o por un vendedor en su nombre) a la central. Corresponde a un pedido en su ERP.\n\nDevuelve id, código interno, estado y fechas de cada servicio; para el contenido completo, use `GET /services/{id}`.\n\nPor defecto, trae los servicios en todos los estados de abajo; use `status` para restringir:\n- `4`: presupuesto generado, esperando la aprobación del cliente;\n- `25`: esperando pago en línea;\n- `6`: aprobado por el cliente;\n- `7`: enviado a producción;\n- `9`: producido.\n\nOtros códigos en `status` se rechazan con 400.\n\n`internal_code=null` trae solo los servicios que todavía no tienen código interno; para buscar pedidos nuevos para el ERP, combínelo con `status=6`. `date_start` y `date_end` filtran por la fecha de la última modificación del servicio.\n\nPara paginar, envíe en `offset` el valor de `meta.next` de la respuesta anterior; `meta.next` nulo indica la última página. Límite: 1 solicitud cada 5 segundos.\n\n---\n\n🇺🇸\n\nA service is an order for custom-cut furniture parts, placed on Cortecloud with the service center by a carpenter (or by a salesperson on their behalf). It corresponds to an order in your ERP.\n\nReturns the id, internal code, status and dates of each service; for the full content, use `GET /services/{id}`.\n\nBy default, it returns services in all the statuses below; use `status` to narrow it down:\n- `4`: quote generated, awaiting customer approval;\n- `25`: awaiting online payment;\n- `6`: approved by the customer;\n- `7`: sent to production;\n- `9`: produced.\n\nOther codes in `status` are rejected with 400.\n\n`internal_code=null` returns only services that don't have an internal code yet; to find new orders for the ERP, combine it with `status=6`. `date_start` and `date_end` filter by the date of the service's last change.\n\nTo paginate, send in `offset` the `meta.next` value from the previous response; a null `meta.next` means the last page. Limit: 1 request every 5 seconds.","operationId":"listServices","parameters":[{"name":"limit","required":false,"in":"query","description":"Número máximo de serviços a serem retornados","schema":{"maximum":500,"exclusiveMinimum":true,"default":500,"type":"integer","minimum":0}},{"name":"offset","required":false,"in":"query","description":"Número de serviços a serem ignorados antes de começar a retornar os resultados","schema":{"minimum":0,"maximum":9007199254740991,"default":0,"type":"integer"}},{"name":"internal_code","required":false,"in":"query","description":"Código interno do serviço a ser filtrado (use \"null\" para filtrar serviços sem código interno)","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","description":"Status dos serviços a serem retornados (separados por vírgula)","schema":{"minLength":1,"default":"4,6,7,9,25","type":"string"}},{"name":"date_start","required":false,"in":"query","description":"Data de início do período para filtrar os serviços","schema":{"type":"string"}},{"name":"date_end","required":false,"in":"query","description":"Data de fim do período para filtrar os serviços","schema":{"type":"string"}}],"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListServicesResponse"}}}}},"summary":"🇧🇷 Lista os serviços da central · 🇪🇸 Lista los servicios de la central · 🇺🇸 Lists the service center's services","tags":["Services"]}},"/services/{id}":{"get":{"description":"🇧🇷\n\nRetorna o conteúdo completo do serviço: status e histórico, datas de cada etapa da produção, valores de mão de obra (corte, aplicação de fita, usinagem, embalagem e frete), materiais consumidos e a lista de peças.\n\nO histórico inclui só as mudanças para orçamento gerado (4), aprovado (6), enviado para produção (7) e produzido (9).\n\nResponde 404 quando o serviço não é encontrado.\n\n---\n\n🇪🇸\n\nDevuelve el contenido completo del servicio: estado e historial, fechas de cada etapa de la producción, valores de mano de obra (corte, aplicación de tapacanto, mecanizado, embalaje y flete), materiales consumidos y la lista de piezas.\n\nEl historial incluye solo los cambios a presupuesto generado (4), aprobado (6), enviado a producción (7) y producido (9).\n\nResponde 404 cuando no se encuentra el servicio.\n\n---\n\n🇺🇸\n\nReturns the full content of the service: status and history, dates of each production stage, labor charges (cutting, edge banding, machining, packing and shipping), materials consumed, and the list of parts.\n\nThe history includes only changes to quote generated (4), approved (6), sent to production (7) and produced (9).\n\nResponds with 404 when the service is not found.","operationId":"getService","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"🇧🇷 Serviço não encontrado · 🇪🇸 Servicio no encontrado · 🇺🇸 Service not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetServiceResponse"}}}}},"summary":"🇧🇷 Consulta um serviço · 🇪🇸 Consulta un servicio · 🇺🇸 Gets a service","tags":["Services"]},"put":{"description":"🇧🇷\n\nGrava em `internal_code` o código que identifica o serviço no seu sistema, normalmente o número do pedido gerado no ERP. É o único campo alterável e é obrigatório no corpo; aceita texto ou número, e `null` apaga o código. `PUT` e `PATCH` fazem a mesma coisa.\n\nSó é aceito com o serviço em orçamento gerado (4), aguardando pagamento online (25), aprovado (6), enviado para produção (7) ou produzido (9). Com o serviço em outro status, ou sem `internal_code` no corpo, responde 500 com o motivo na mensagem; nesse caso, repetir a mesma chamada não muda o resultado.\n\n---\n\n🇪🇸\n\nGuarda en `internal_code` el código que identifica el servicio en su sistema, normalmente el número del pedido generado en el ERP. Es el único campo modificable y es obligatorio en el cuerpo; acepta texto o número, y `null` borra el código. `PUT` y `PATCH` hacen lo mismo.\n\nSolo se acepta con el servicio en presupuesto generado (4), esperando pago en línea (25), aprobado (6), enviado a producción (7) o producido (9). Con el servicio en otro estado, o sin `internal_code` en el cuerpo, responde 500 con el motivo en el mensaje; en ese caso, repetir la misma llamada no cambia el resultado.\n\n---\n\n🇺🇸\n\nStores in `internal_code` the code that identifies the service in your system, usually the order number generated in the ERP. It is the only field that can be changed, and it is required in the body; it accepts text or a number, and `null` clears the code. `PUT` and `PATCH` do the same thing.\n\nOnly accepted when the service is in quote generated (4), awaiting online payment (25), approved (6), sent to production (7) or produced (9). With the service in any other status, or without `internal_code` in the body, it responds with 500 and the reason in the message; in that case, repeating the same call doesn't change the result.","operationId":"updateService","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateServiceRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"🇧🇷 Status do serviço não permite a alteração, ou falta `internal_code` no corpo · 🇪🇸 El estado del servicio no permite el cambio, o falta `internal_code` en el cuerpo · 🇺🇸 Service status does not allow the change, or `internal_code` is missing from the body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateServiceResponse"}}}}},"summary":"🇧🇷 Associa o código do pedido do ERP a um serviço · 🇪🇸 Asocia el código del pedido del ERP a un servicio · 🇺🇸 Links the ERP order code to a service","tags":["Services"]},"patch":{"description":"🇧🇷\n\nGrava em `internal_code` o código que identifica o serviço no seu sistema, normalmente o número do pedido gerado no ERP. É o único campo alterável e é obrigatório no corpo; aceita texto ou número, e `null` apaga o código. `PUT` e `PATCH` fazem a mesma coisa.\n\nSó é aceito com o serviço em orçamento gerado (4), aguardando pagamento online (25), aprovado (6), enviado para produção (7) ou produzido (9). Com o serviço em outro status, ou sem `internal_code` no corpo, responde 500 com o motivo na mensagem; nesse caso, repetir a mesma chamada não muda o resultado.\n\n---\n\n🇪🇸\n\nGuarda en `internal_code` el código que identifica el servicio en su sistema, normalmente el número del pedido generado en el ERP. Es el único campo modificable y es obligatorio en el cuerpo; acepta texto o número, y `null` borra el código. `PUT` y `PATCH` hacen lo mismo.\n\nSolo se acepta con el servicio en presupuesto generado (4), esperando pago en línea (25), aprobado (6), enviado a producción (7) o producido (9). Con el servicio en otro estado, o sin `internal_code` en el cuerpo, responde 500 con el motivo en el mensaje; en ese caso, repetir la misma llamada no cambia el resultado.\n\n---\n\n🇺🇸\n\nStores in `internal_code` the code that identifies the service in your system, usually the order number generated in the ERP. It is the only field that can be changed, and it is required in the body; it accepts text or a number, and `null` clears the code. `PUT` and `PATCH` do the same thing.\n\nOnly accepted when the service is in quote generated (4), awaiting online payment (25), approved (6), sent to production (7) or produced (9). With the service in any other status, or without `internal_code` in the body, it responds with 500 and the reason in the message; in that case, repeating the same call doesn't change the result.","operationId":"patchService","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateServiceRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"🇧🇷 Status do serviço não permite a alteração, ou falta `internal_code` no corpo · 🇪🇸 El estado del servicio no permite el cambio, o falta `internal_code` en el cuerpo · 🇺🇸 Service status does not allow the change, or `internal_code` is missing from the body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateServiceResponse"}}}}},"summary":"🇧🇷 Associa o código do pedido do ERP a um serviço · 🇪🇸 Asocia el código del pedido del ERP a un servicio · 🇺🇸 Links the ERP order code to a service","tags":["Services"]}},"/services/{id}/production":{"post":{"description":"🇧🇷\n\nEnvia o serviço para a produção da central e registra como responsável o vendedor (funcionário da central) com o e-mail informado. O efeito é o mesmo de o vendedor aprovar o serviço para produção no Cortecloud. Use com serviços aprovados (6).\n\nO e-mail precisa ser de um vendedor ativo na central autenticada; se não for, responde 422.\n\nA resposta 202 confirma que o envio foi aceito; a produção processa o serviço em seguida. Acompanhe por `GET /services/{id}` até `status.code` chegar a `7` (enviado para produção). Nesse intervalo, `status.code` pode trazer um código intermediário fora da tabela de status.\n\nSe o envio for recusado, por exemplo por saldo insuficiente, responde 502 com o motivo na mensagem.\n\n---\n\n🇪🇸\n\nEnvía el servicio a la producción de la central y registra como responsable al vendedor (empleado de la central) con el correo electrónico indicado. El efecto es el mismo que si el vendedor aprobara el servicio para producción en Cortecloud. Úsela con servicios aprobados (6).\n\nEl correo electrónico debe ser de un vendedor activo en la central autenticada; si no lo es, responde 422.\n\nLa respuesta 202 confirma que el envío fue aceptado; la producción procesa el servicio a continuación. Siga el avance con `GET /services/{id}` hasta que `status.code` llegue a `7` (enviado a producción). En ese intervalo, `status.code` puede traer un código intermedio que no está en la tabla de estados.\n\nSi el envío es rechazado, por ejemplo por saldo insuficiente, responde 502 con el motivo en el mensaje.\n\n---\n\n🇺🇸\n\nSends the service to the service center's production and records the salesperson (a service center employee) with the given email as responsible. The effect is the same as the salesperson approving the service for production in Cortecloud. Use it with approved services (6).\n\nThe email must belong to an active salesperson in the authenticated service center; otherwise, it responds with 422.\n\nThe 202 response confirms that the submission was accepted; production processes the service right after. Track it with `GET /services/{id}` until `status.code` reaches `7` (sent to production). In the meantime, `status.code` may show an intermediate code that is not in the status table.\n\nIf the submission is rejected, for example due to insufficient balance, it responds with 502 and the reason in the message.","operationId":"sendServiceToProduction","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendToProductionRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"🇧🇷 E-mail não é de um vendedor ativo na central · 🇪🇸 El correo no es de un vendedor activo en la central · 🇺🇸 Email does not belong to an active salesperson in the service center","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"🇧🇷 Envio para produção recusado · 🇪🇸 Envío a producción rechazado · 🇺🇸 Submission to production rejected","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/PrivateApiErrorResponse"},{"$ref":"#/components/schemas/ErrorResponse"}]}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendToProductionResponse"}}}}},"summary":"🇧🇷 Envia um serviço para produção · 🇪🇸 Envía un servicio a producción · 🇺🇸 Sends a service to production","tags":["Services"]}},"/payment/cancel-checkout":{"post":{"description":"🇧🇷\n\nChame quando o pagamento falhar ou for abandonado no seu checkout. O serviço volta de aguardando pagamento online (25) para orçamento gerado (4), e a URL de checkout registrada é apagada; o cliente pode tentar pagar de novo.\n\nSó é aceito com o serviço aguardando pagamento online (25); em outro status, responde 409.\n\n---\n\n🇪🇸\n\nLlámelo cuando el pago falle o sea abandonado en su checkout. El servicio vuelve de esperando pago en línea (25) a presupuesto generado (4), y la URL de checkout registrada se borra; el cliente puede intentar pagar de nuevo.\n\nSolo se acepta con el servicio esperando pago en línea (25); en otro estado, responde 409.\n\n---\n\n🇺🇸\n\nCall it when the payment fails or is abandoned in your checkout. The service goes back from awaiting online payment (25) to quote generated (4), and the registered checkout URL is cleared; the customer can try to pay again.\n\nOnly accepted when the service is awaiting online payment (25); in any other status, it responds with 409.","operationId":"cancelCheckout","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelCheckoutRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"🇧🇷 Serviço não está aguardando pagamento online (25) · 🇪🇸 El servicio no está esperando pago en línea (25) · 🇺🇸 Service is not awaiting online payment (25)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelCheckoutResponse"}}}}},"summary":"🇧🇷 Cancela o pagamento online de um serviço · 🇪🇸 Cancela el pago en línea de un servicio · 🇺🇸 Cancels a service's online payment","tags":["Payment"]}},"/payment/finish-checkout":{"post":{"description":"🇧🇷\n\nChame quando o pagamento for confirmado no seu checkout. O serviço passa de aguardando pagamento online (25) para aprovado (6) e pode seguir para produção. `paymentId` fica registrado como o identificador desse pagamento.\n\nGuarde o `paymentId`: ele é exigido para desfazer a aprovação em `POST /payment/return-service`.\n\nSó é aceito com o serviço aguardando pagamento online (25); em outro status, responde 409.\n\n---\n\n🇪🇸\n\nLlámelo cuando el pago se confirme en su checkout. El servicio pasa de esperando pago en línea (25) a aprobado (6) y puede seguir a producción. `paymentId` queda registrado como el identificador de ese pago.\n\nGuarde el `paymentId`: se exige para deshacer la aprobación en `POST /payment/return-service`.\n\nSolo se acepta con el servicio esperando pago en línea (25); en otro estado, responde 409.\n\n---\n\n🇺🇸\n\nCall it when the payment is confirmed in your checkout. The service moves from awaiting online payment (25) to approved (6) and can proceed to production. `paymentId` is recorded as the identifier of that payment.\n\nKeep the `paymentId`: it is required to undo the approval with `POST /payment/return-service`.\n\nOnly accepted when the service is awaiting online payment (25); in any other status, it responds with 409.","operationId":"finishCheckout","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinishCheckoutRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"🇧🇷 Serviço não está aguardando pagamento online (25) · 🇪🇸 El servicio no está esperando pago en línea (25) · 🇺🇸 Service is not awaiting online payment (25)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinishCheckoutResponse"}}}}},"summary":"🇧🇷 Confirma o pagamento de um serviço · 🇪🇸 Confirma el pago de un servicio · 🇺🇸 Confirms a service's payment","tags":["Payment"]}},"/payment/return-service":{"post":{"description":"🇧🇷\n\nChame quando um pagamento já confirmado precisar ser revertido, por exemplo num estorno. O serviço volta de aprovado (6) para orçamento gerado (4), e o pagamento e a URL de checkout registrados são apagados.\n\nSó é aceito com o serviço aprovado e com o mesmo `paymentId` enviado em `POST /payment/finish-checkout`; se não, responde 409.\n\n---\n\n🇪🇸\n\nLlámelo cuando un pago ya confirmado deba revertirse, por ejemplo en un reembolso. El servicio vuelve de aprobado (6) a presupuesto generado (4), y el pago y la URL de checkout registrados se borran.\n\nSolo se acepta con el servicio aprobado y con el mismo `paymentId` enviado en `POST /payment/finish-checkout`; si no, responde 409.\n\n---\n\n🇺🇸\n\nCall it when an already confirmed payment needs to be reversed, for example in a refund. The service goes back from approved (6) to quote generated (4), and the registered payment and checkout URL are cleared.\n\nOnly accepted when the service is approved and with the same `paymentId` sent in `POST /payment/finish-checkout`; otherwise, it responds with 409.","operationId":"returnService","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnServiceRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"🇧🇷 Serviço não está aprovado (6) ou `paymentId` não confere · 🇪🇸 El servicio no está aprobado (6) o el `paymentId` no coincide · 🇺🇸 Service is not approved (6) or `paymentId` does not match","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnServiceResponse"}}}}},"summary":"🇧🇷 Desfaz a aprovação de um serviço pago · 🇪🇸 Deshace la aprobación de un servicio pagado · 🇺🇸 Undoes the approval of a paid service","tags":["Payment"]}},"/payment/checkout-url":{"post":{"description":"🇧🇷\n\nRegistra a URL do checkout que o seu sistema gerou para o serviço. O Cortecloud redireciona o cliente para essa URL.\n\nFaz parte do pagamento online: quando o cliente escolhe pagar online, o serviço passa para aguardando pagamento online (25) e o Cortecloud chama, com o id do serviço, o endpoint de checkout cadastrado para a central (o cadastro é feito pelo suporte). O seu sistema gera o checkout e registra a URL por esta rota.\n\nSó é aceito com o serviço aguardando pagamento online (25); em outro status, responde 409.\n\n---\n\n🇪🇸\n\nRegistra la URL del checkout que su sistema generó para el servicio. Cortecloud redirige al cliente a esa URL.\n\nForma parte del pago en línea: cuando el cliente elige pagar en línea, el servicio pasa a esperando pago en línea (25) y Cortecloud llama, con el id del servicio, al endpoint de checkout registrado para la central (el registro lo hace el soporte). Su sistema genera el checkout y registra la URL mediante esta ruta.\n\nSolo se acepta con el servicio esperando pago en línea (25); en otro estado, responde 409.\n\n---\n\n🇺🇸\n\nRegisters the URL of the checkout your system created for the service. Cortecloud redirects the customer to that URL.\n\nPart of online payment: when the customer chooses to pay online, the service moves to awaiting online payment (25) and Cortecloud calls, with the service id, the checkout endpoint registered for the service center (registration is done by support). Your system creates the checkout and registers its URL through this route.\n\nOnly accepted when the service is awaiting online payment (25); in any other status, it responds with 409.","operationId":"saveCheckoutUrl","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutUrlRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"🇧🇷 Serviço não está aguardando pagamento online (25) · 🇪🇸 El servicio no está esperando pago en línea (25) · 🇺🇸 Service is not awaiting online payment (25)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutUrlResponse"}}}}},"summary":"🇧🇷 Registra a URL de pagamento de um serviço · 🇪🇸 Registra la URL de pago de un servicio · 🇺🇸 Registers a service's payment URL","tags":["Payment"]}},"/embed/quick-service":{"post":{"description":"🇧🇷\n\nDevolve uma URL que abre o Cortecloud já autenticado como o vendedor informado (funcionário da central que atende o cliente), na tela de cadastro de um novo serviço para o marceneiro informado (o cliente) e para a linha de produção indicada (onde as peças serão produzidas).\n\nAntes de gerar a URL, a rota cadastra o vendedor na central e o marceneiro no Cortecloud, caso ainda não existam, e vincula o marceneiro à central com o código `carpenterInternalCode`. Repetir a chamada com os mesmos dados não duplica cadastros. Se o marceneiro já tem vínculo ativo com a central, o código interno desse vínculo é mantido. Se o e-mail do vendedor é de um vendedor de outra central, ele passa para esta central e perde o vínculo com a anterior.\n\nA URL vale para um único acesso e expira em 60 segundos: gere-a no momento em que o vendedor for abri-la e entregue-a só a ele, pois ela dá acesso à conta dele.\n\n`companyInternalCode` precisa ser igual ao cabeçalho `x-company-internal-code`; se não for, responde 401. Responde 409 quando `sellerEmail` ou `carpenterEmail` já pertence a um usuário de outro perfil (por exemplo, o e-mail do vendedor é de um marceneiro).\n\n---\n\n🇪🇸\n\nDevuelve una URL que abre Cortecloud ya autenticado como el vendedor indicado (empleado de la central que atiende al cliente), en la pantalla de registro de un nuevo servicio para el carpintero indicado (el cliente) y para la línea de producción indicada (donde se producirán las piezas).\n\nAntes de generar la URL, la ruta registra al vendedor en la central y al carpintero en Cortecloud, si todavía no existen, y vincula al carpintero con la central con el código `carpenterInternalCode`. Repetir la llamada con los mismos datos no duplica registros. Si el carpintero ya tiene un vínculo activo con la central, se mantiene el código interno de ese vínculo. Si el correo electrónico del vendedor es de un vendedor de otra central, pasa a esta central y pierde el vínculo con la anterior.\n\nLa URL sirve para un único acceso y expira en 60 segundos: genérela en el momento en que el vendedor vaya a abrirla y entréguesela solo a él, ya que da acceso a su cuenta.\n\n`companyInternalCode` debe ser igual al encabezado `x-company-internal-code`; si no lo es, responde 401. Responde 409 cuando `sellerEmail` o `carpenterEmail` ya pertenece a un usuario de otro perfil (por ejemplo, el correo electrónico del vendedor es de un carpintero).\n\n---\n\n🇺🇸\n\nReturns a URL that opens Cortecloud already authenticated as the given salesperson (the service center employee who serves the customer), on the new service screen for the given carpenter (the customer) and for the given production line (where the parts will be produced).\n\nBefore generating the URL, the route registers the salesperson in the service center and the carpenter in Cortecloud, if they don't exist yet, and links the carpenter to the service center with the code `carpenterInternalCode`. Repeating the call with the same data doesn't create duplicate records. If the carpenter already has an active link with the service center, that link's internal code is kept. If the salesperson's email belongs to a salesperson of another service center, they are moved to this service center and lose the link with the previous one.\n\nThe URL is valid for a single access and expires in 60 seconds: generate it at the moment the salesperson is going to open it and give it only to them, since it grants access to their account.\n\n`companyInternalCode` must match the `x-company-internal-code` header; otherwise, it responds with 401. Responds with 409 when `sellerEmail` or `carpenterEmail` already belongs to a user with another profile (for example, the salesperson's email belongs to a carpenter).","operationId":"createSellerLink","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuickServiceRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"🇧🇷 E-mail do vendedor ou do marceneiro é de um usuário de outro perfil · 🇪🇸 El correo del vendedor o del carpintero es de un usuario de otro perfil · 🇺🇸 Salesperson or carpenter email belongs to a user with another profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserServiceErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmbedSessionResponse"}}}}},"summary":"🇧🇷 Gera um link de acesso à tela de novo serviço · 🇪🇸 Genera un enlace de acceso a la pantalla de nuevo servicio · 🇺🇸 Generates an access link to the new service screen","tags":["Embed"]}},"/embed/service":{"post":{"description":"🇧🇷\n\nDevolve uma URL que abre o site da central no Cortecloud (whitelabel, com a marca da central) já autenticado como o marceneiro informado. O marceneiro é cadastrado no Cortecloud se ainda não existir.\n\nA URL vale para um único acesso e expira em 60 segundos: gere-a no momento em que o marceneiro for abri-la e entregue-a só a ele, pois ela dá acesso à conta dele.\n\nResponde 404 quando a central não tem site whitelabel configurado, e 409 quando `carpenterEmail` já pertence a um usuário de outro perfil (por exemplo, um vendedor).\n\n---\n\n🇪🇸\n\nDevuelve una URL que abre el sitio de la central en Cortecloud (whitelabel, con la marca de la central) ya autenticado como el carpintero indicado. El carpintero se registra en Cortecloud si todavía no existe.\n\nLa URL sirve para un único acceso y expira en 60 segundos: genérela en el momento en que el carpintero vaya a abrirla y entréguesela solo a él, ya que da acceso a su cuenta.\n\nResponde 404 cuando la central no tiene un sitio whitelabel configurado, y 409 cuando `carpenterEmail` ya pertenece a un usuario de otro perfil (por ejemplo, un vendedor).\n\n---\n\n🇺🇸\n\nReturns a URL that opens the service center's site on Cortecloud (whitelabel, with the service center's branding) already authenticated as the given carpenter. The carpenter is registered in Cortecloud if they don't exist yet.\n\nThe URL is valid for a single access and expires in 60 seconds: generate it at the moment the carpenter is going to open it and give it only to them, since it grants access to their account.\n\nResponds with 404 when the service center has no whitelabel site configured, and with 409 when `carpenterEmail` already belongs to a user with another profile (for example, a salesperson).","operationId":"createCarpenterLink","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceRequest"}}}},"responses":{"400":{"description":"🇧🇷 Requisição fora da validação da rota · 🇪🇸 Solicitud fuera de la validación de la ruta · 🇺🇸 Request failed the route validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"🇧🇷 Falha de autenticação · 🇪🇸 Falla de autenticación · 🇺🇸 Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"🇧🇷 Central sem site whitelabel configurado · 🇪🇸 Central sin sitio whitelabel configurado · 🇺🇸 Service center has no whitelabel site configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"🇧🇷 E-mail do marceneiro é de um usuário de outro perfil · 🇪🇸 El correo del carpintero es de un usuario de otro perfil · 🇺🇸 Carpenter email belongs to a user with another profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserServiceErrorResponse"}}}},"429":{"description":"🇧🇷 Limite de requisições excedido · 🇪🇸 Límite de solicitudes excedido · 🇺🇸 Rate limit exceeded","headers":{"Retry-After":{"description":"🇧🇷 Segundos até poder repetir · 🇪🇸 Segundos hasta poder repetir · 🇺🇸 Seconds until you can retry","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmbedSessionResponse"}}}}},"summary":"🇧🇷 Gera um link de acesso à área do marceneiro · 🇪🇸 Genera un enlace de acceso al área del carpintero · 🇺🇸 Generates an access link to the carpenter area","tags":["Embed"]}}},"info":{"title":"API Pública","description":"🇧🇷\n\nAPI para integrar o sistema da sua empresa (ERP, checkout de pagamento, sistema de vendas) ao Cortecloud, plataforma em que marceneiros encomendam peças de móveis cortadas sob medida a centrais de serviço, as empresas que vendem e produzem essas peças.\n\nCom ela, sua integração pode:\n- manter preço, estoque e status ativo/inativo dos materiais da central (chapas, fitas de borda e componentes);\n- consultar os serviços (pedidos) da central, associá-los aos pedidos do seu ERP e enviá-los para produção;\n- conduzir o pagamento online de um serviço num checkout do seu sistema;\n- abrir telas do Cortecloud já autenticadas para vendedores e marceneiros, sem que eles digitem usuário e senha.\n\n### Autenticação\n\nA Serrabits fornece à sua integração uma **api key**, que a identifica, e uma **secret key**, que assina as requisições. Para obtê-las, escreva para suporte@serrabits.com.br. A secret key nunca é enviada: só a assinatura vai na requisição. Ela deve ficar apenas no seu backend; quem tiver a secret key consegue fazer chamadas em nome da sua integração.\n\nToda requisição leva dois cabeçalhos:\n\n```text\nAuthorization: SB1-HMAC-SHA256 api-key=\"<api key>\", signed-headers=\"host\", signature=\"<assinatura>\"\nx-company-internal-code: <código da central>\n```\n\nUma api key pode estar vinculada a mais de uma central, e cada requisição atua sobre uma só: a indicada em `x-company-internal-code`. Esse cabeçalho não entra na assinatura.\n\nA assinatura cobre método, caminho, query string, host e corpo. Alterar qualquer um deles depois de assinar invalida a requisição, e uma requisição capturada não pode ser reaproveitada com outro caminho, método ou corpo.\n\n#### Como calcular `<assinatura>`\n\n1. Monte o texto a ser assinado, com uma informação por linha, separadas por `\\n`:\n   - método HTTP em maiúsculas (`GET`, `POST`, `PUT`, `PATCH`);\n   - caminho da URL, sem host nem query string (`/materials/boards`); caminho vazio vale `/`;\n   - parâmetros da query string ordenados por nome (e, em nomes repetidos, por valor), cada um como `nome=valor` codificado como no `encodeURIComponent` do JavaScript, unidos por `&`; sem query string, linha vazia;\n   - `host:<host>` seguido de uma linha em branco, onde `<host>` é exatamente o valor que sua biblioteca HTTP envia no cabeçalho `host` (hostname, mais `:porta` só quando a porta não é a padrão);\n   - a palavra `host`;\n   - SHA-256 em hexadecimal dos bytes do corpo; sem corpo, o SHA-256 da string vazia (`e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`).\n2. Calcule o HMAC-SHA256 desse texto com a secret key como chave.\n3. Use o resultado em hexadecimal minúsculo como `<assinatura>`.\n\nExemplo do texto assinado para `GET /materials/boards?limit=10` no host `api.example.com`, sem corpo:\n\n```text\nGET\n/materials/boards\nlimit=10\nhost:api.example.com\n\nhost\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n```\n\nExemplo de `POST /services/123/production` no host `api.example.com`, com o corpo `{\"sellerEmail\":\"vendedor@example.com\"}`. O hash é calculado sobre os bytes exatos do corpo enviado: reformatar o JSON depois de assinar (espaços, quebras de linha, ordem das chaves) invalida a assinatura.\n\n```text\nPOST\n/services/123/production\n\nhost:api.example.com\n\nhost\nd4f22123a7a0685bd98bb9f7fc9b3db455e5b4e0c4420f0e0ddedd4826a3e0cc\n```\n\nSem query string, a terceira linha fica vazia.\n\nA API responde 401 quando um dos cabeçalhos falta ou está malformado, a api key é desconhecida ou revogada, a central não pertence à api key, ou a assinatura não confere.\n\n### Limites de requisição\n\nCada api key pode fazer até 5 requisições por segundo em cada rota. As rotas que operam sobre a coleção inteira (listagem e atualização em lote de materiais, cópia entre centrais e listagem de serviços) aceitam 1 requisição a cada 5 segundos. Toda resposta traz `X-RateLimit-Limit`, `X-RateLimit-Remaining` e `X-RateLimit-Reset`; acima do limite, a resposta é 429 com `Retry-After` em segundos.\n\n### Paginação\n\nAs listagens devolvem no máximo 500 itens por página (também o padrão de `limit`). Para a próxima página, envie em `offset` o valor de `meta.next` da resposta anterior; `meta.next` nulo indica a última página.\n\n### Erros\n\nA API responde 400 quando o corpo ou a query string não passa na validação da rota, 401 quando a autenticação falha e 429 acima do limite de requisições. Os erros de negócio de cada rota (item não encontrado, status do serviço que não permite a operação) estão na descrição da operação. O corpo do erro traz uma mensagem com o motivo: use o status HTTP para decidir o tratamento e a mensagem para registrar e diagnosticar. Um 5xx sem outra explicação na operação pode ser transitório: repita com espera crescente e um número limitado de tentativas.\n\n---\n\n🇪🇸\n\nAPI para integrar el sistema de su empresa (ERP, checkout de pago, sistema de ventas) con Cortecloud, plataforma en la que carpinteros encargan piezas de muebles cortadas a medida a centrales de servicio, las empresas que venden y producen esas piezas.\n\nCon ella, su integración puede:\n- mantener el precio, el stock y el estado activo/inactivo de los materiales de la central (tableros, tapacantos y componentes);\n- consultar los servicios (pedidos) de la central, asociarlos a los pedidos de su ERP y enviarlos a producción;\n- conducir el pago en línea de un servicio en un checkout de su sistema;\n- abrir pantallas de Cortecloud ya autenticadas para vendedores y carpinteros, sin que tengan que escribir usuario y contraseña.\n\n### Autenticación\n\nSerrabits le proporciona a su integración una **api key**, que la identifica, y una **secret key**, que firma las solicitudes. Para obtenerlas, escriba a suporte@serrabits.com.br. La secret key nunca se envía: solo la firma va en la solicitud. Debe quedar únicamente en su backend; quien tenga la secret key puede hacer llamadas en nombre de su integración.\n\nToda solicitud lleva dos encabezados:\n\n```text\nAuthorization: SB1-HMAC-SHA256 api-key=\"<api key>\", signed-headers=\"host\", signature=\"<firma>\"\nx-company-internal-code: <código de la central>\n```\n\nUna api key puede estar vinculada a más de una central, y cada solicitud actúa sobre una sola: la indicada en `x-company-internal-code`. Este encabezado no entra en la firma.\n\nLa firma cubre el método, el path, la query string, el host y el cuerpo. Alterar cualquiera de ellos después de firmar invalida la solicitud, y una solicitud capturada no puede reutilizarse con otro path, método o cuerpo.\n\n#### Cómo calcular `<firma>`\n\n1. Arme el texto firmado, con un dato por línea, separadas por `\\n`:\n   - método HTTP en mayúsculas (`GET`, `POST`, `PUT`, `PATCH`);\n   - path de la URL, sin host ni query string (`/materials/boards`); un path vacío equivale a `/`;\n   - parámetros de la query string ordenados por nombre (y, en nombres repetidos, por valor), cada uno como `nombre=valor` codificado como en el `encodeURIComponent` de JavaScript, unidos por `&`; sin query string, línea vacía;\n   - `host:<host>` seguido de una línea en blanco, donde `<host>` es exactamente el valor que su biblioteca HTTP envía en el encabezado `host` (hostname, más `:puerto` solo cuando el puerto no es el predeterminado);\n   - la palabra `host`;\n   - SHA-256 en hexadecimal de los bytes del cuerpo; sin cuerpo, el SHA-256 de la cadena vacía (`e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`).\n2. Calcule el HMAC-SHA256 de ese texto con la secret key como clave.\n3. Use el resultado en hexadecimal en minúsculas como `<firma>`.\n\nEjemplo del texto firmado para `GET /materials/boards?limit=10` en el host `api.example.com`, sin cuerpo:\n\n```text\nGET\n/materials/boards\nlimit=10\nhost:api.example.com\n\nhost\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n```\n\nEjemplo de `POST /services/123/production` en el host `api.example.com`, con el cuerpo `{\"sellerEmail\":\"vendedor@example.com\"}`. El hash se calcula sobre los bytes exactos del cuerpo enviado: reformatear el JSON después de firmar (espacios, saltos de línea, orden de las claves) invalida la firma.\n\n```text\nPOST\n/services/123/production\n\nhost:api.example.com\n\nhost\nd4f22123a7a0685bd98bb9f7fc9b3db455e5b4e0c4420f0e0ddedd4826a3e0cc\n```\n\nSin query string, la tercera línea queda vacía.\n\nLa API responde 401 cuando falta uno de los encabezados o está mal formado, la api key es desconocida o fue revocada, la central no pertenece a la api key, o la firma no coincide.\n\n### Límites de solicitudes\n\nCada api key puede hacer hasta 5 solicitudes por segundo en cada ruta. Las rutas que operan sobre la colección entera (listado y actualización en lote de materiales, copia entre centrales y listado de servicios) aceptan 1 solicitud cada 5 segundos. Toda respuesta trae `X-RateLimit-Limit`, `X-RateLimit-Remaining` y `X-RateLimit-Reset`; por encima del límite, la respuesta es 429 con `Retry-After` en segundos.\n\n### Paginación\n\nLos listados devuelven como máximo 500 ítems por página (también el valor predeterminado de `limit`). Para la página siguiente, envíe en `offset` el valor de `meta.next` de la respuesta anterior; `meta.next` nulo indica la última página.\n\n### Errores\n\nLa API responde 400 cuando el cuerpo o la query string no pasa la validación de la ruta, 401 cuando la autenticación falla y 429 por encima del límite de solicitudes. Los errores de negocio de cada ruta (ítem no encontrado, estado del servicio que no permite la operación) están en la descripción de la operación. El cuerpo del error trae un mensaje con el motivo: use el estado HTTP para decidir el tratamiento y el mensaje para registrar y diagnosticar. Un 5xx sin otra explicación en la operación puede ser transitorio: repita con espera creciente y un número limitado de intentos.\n\n---\n\n🇺🇸\n\nAPI for integrating your company's system (ERP, payment checkout, sales system) with Cortecloud, a platform where carpenters order custom-cut furniture parts from service centers, the companies that sell and produce those parts.\n\nWith it, your integration can:\n- maintain the price, stock and active/inactive status of the service center's materials (boards, edge banding and hardware components);\n- query the service center's services (orders), link them to the orders in your ERP and send them to production;\n- handle a service's online payment in a checkout in your system;\n- open Cortecloud screens already authenticated for salespeople and carpenters, without them typing a username and password.\n\n### Authentication\n\nSerrabits provides your integration with an **api key**, which identifies it, and a **secret key**, which signs the requests. To get them, write to suporte@serrabits.com.br. The secret key is never sent: only the signature goes in the request. It must stay only in your backend; anyone who has the secret key can make calls on behalf of your integration.\n\nEvery request carries two headers:\n\n```text\nAuthorization: SB1-HMAC-SHA256 api-key=\"<api key>\", signed-headers=\"host\", signature=\"<signature>\"\nx-company-internal-code: <service center code>\n```\n\nAn api key can be linked to more than one service center, and each request acts on only one: the one given in `x-company-internal-code`. This header is not part of the signature.\n\nThe signature covers the method, path, query string, host and body. Changing any of them after signing invalidates the request, and a captured request cannot be reused with a different path, method or body.\n\n#### How to compute `<signature>`\n\n1. Build the signed text, with one item per line, separated by `\\n`:\n   - HTTP method in uppercase (`GET`, `POST`, `PUT`, `PATCH`);\n   - URL path, without host or query string (`/materials/boards`); an empty path counts as `/`;\n   - query string parameters sorted by name (and, for repeated names, by value), each as `name=value` encoded as JavaScript's `encodeURIComponent` does, joined by `&`; with no query string, an empty line;\n   - `host:<host>` followed by a blank line, where `<host>` is exactly the value your HTTP library sends in the `host` header (hostname, plus `:port` only when the port is not the default);\n   - the word `host`;\n   - hexadecimal SHA-256 of the body bytes; with no body, the SHA-256 of the empty string (`e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`).\n2. Compute the HMAC-SHA256 of this text using the secret key as the key.\n3. Use the result in lowercase hexadecimal as `<signature>`.\n\nExample of the signed text for `GET /materials/boards?limit=10` on host `api.example.com`, with no body:\n\n```text\nGET\n/materials/boards\nlimit=10\nhost:api.example.com\n\nhost\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n```\n\nExample of `POST /services/123/production` on host `api.example.com`, with the body `{\"sellerEmail\":\"vendedor@example.com\"}`. The hash is computed over the exact bytes of the body sent: reformatting the JSON after signing (spaces, line breaks, key order) invalidates the signature.\n\n```text\nPOST\n/services/123/production\n\nhost:api.example.com\n\nhost\nd4f22123a7a0685bd98bb9f7fc9b3db455e5b4e0c4420f0e0ddedd4826a3e0cc\n```\n\nWith no query string, the third line is empty.\n\nThe API responds with 401 when one of the headers is missing or malformed, the api key is unknown or revoked, the service center does not belong to the api key, or the signature does not match.\n\n### Rate limits\n\nEach api key can make up to 5 requests per second on each route. Routes that operate on the whole collection (listing and batch updating of materials, copying between service centers, and listing services) accept 1 request every 5 seconds. Every response includes `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`; above the limit, the response is 429 with `Retry-After` in seconds.\n\n### Pagination\n\nListings return at most 500 items per page (also the default for `limit`). For the next page, send in `offset` the `meta.next` value from the previous response; a null `meta.next` means the last page.\n\n### Errors\n\nThe API responds with 400 when the body or the query string fails the route's validation, 401 when authentication fails, and 429 above the rate limit. Each route's business errors (item not found, service status that doesn't allow the operation) are in the operation's description. The error body includes a message with the reason: use the HTTP status to decide how to handle it and the message to log and diagnose. A 5xx with no other explanation in the operation may be transient: retry with increasing delays and a limited number of attempts.","version":"1.0.0","contact":{}},"tags":[],"servers":[{"url":"https://apis.cortecloud.com.br","description":"🇧🇷 Produção · 🇪🇸 Producción · 🇺🇸 Production"},{"url":"https://apis.hml.cortecloud.com.br","description":"🇧🇷 Homologação · 🇪🇸 Homologación · 🇺🇸 Staging"}],"components":{"securitySchemes":{"SB1-HMAC-SHA256":{"type":"apiKey","in":"header","name":"Authorization","description":"🇧🇷\n\nValor do cabeçalho `Authorization`, com a api key e a assinatura da requisição: `SB1-HMAC-SHA256 api-key=\"<api key>\", signed-headers=\"host\", signature=\"<assinatura>\"`. O cálculo da assinatura está na seção Autenticação da descrição da API.\n\n---\n\n🇪🇸\n\nValor del encabezado `Authorization`, con la api key y la firma de la solicitud: `SB1-HMAC-SHA256 api-key=\"<api key>\", signed-headers=\"host\", signature=\"<firma>\"`. El cálculo de la firma está en la sección Autenticación de la descripción de la API.\n\n---\n\n🇺🇸\n\nValue of the `Authorization` header, with the api key and the request signature: `SB1-HMAC-SHA256 api-key=\"<api key>\", signed-headers=\"host\", signature=\"<signature>\"`. How to compute the signature is in the Authentication section of the API description."},"x-company-internal-code":{"type":"apiKey","in":"header","name":"x-company-internal-code","description":"🇧🇷\n\nCódigo da central sobre a qual a requisição atua. Detalhes na seção Autenticação da descrição da API.\n\n---\n\n🇪🇸\n\nCódigo de la central sobre la que actúa la solicitud. Detalles en la sección Autenticación de la descripción de la API.\n\n---\n\n🇺🇸\n\nCode of the service center the request acts on. Details in the Authentication section of the API description."}},"schemas":{"ErrorResponse":{"type":"object","properties":{"statusCode":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Status HTTP da resposta"},"message":{"type":"string","description":"Motivo do erro"},"error":{"description":"Nome do status HTTP (ex. \"Not Found\")","type":"string"}},"required":["statusCode","message"]},"CrossSyncRequest":{"type":"object","properties":{"sourceCompanyInternalCode":{"type":"string","minLength":1,"description":"Código interno da central de origem"},"targetCompanyInternalCodes":{"minItems":1,"type":"array","items":{"type":"string","minLength":1},"description":"Códigos internos das centrais de destino"},"syncPrice":{"default":false,"description":"Sincroniza preço","type":"boolean"},"syncStock":{"default":false,"description":"Sincroniza estoque","type":"boolean"},"syncActive":{"default":false,"description":"Desativa no destino os materiais que não existem na origem","type":"boolean"}},"required":["sourceCompanyInternalCode","targetCompanyInternalCodes"]},"ValidationErrorResponse":{"type":"object","properties":{"statusCode":{"type":"number","description":"Status HTTP da resposta","enum":[400]},"message":{"type":"string","enum":["Validation failed"]},"errors":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","description":"Tipo da falha de validação"},"path":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"}]},"description":"Caminho do campo que falhou"},"message":{"type":"string","description":"Motivo da falha"}},"required":["code","path","message"],"additionalProperties":{}},"description":"Falhas de validação encontradas"}},"required":["statusCode","message","errors"]},"CrossSyncResponse":{"type":"object","properties":{"source":{"type":"object","properties":{"companyInternalCode":{"type":"string"}},"required":["companyInternalCode"],"description":"Central de origem"},"targets":{"type":"array","items":{"type":"object","properties":{"companyInternalCode":{"type":"string"},"status":{"type":"string","enum":["queued"]}},"required":["companyInternalCode","status"]},"description":"Centrais de destino enfileiradas"}},"required":["source","targets"]},"ListBoardsResponse":{"type":"object","properties":{"resource":{"type":"array","items":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno da chapa","nullable":true},"active":{"type":"boolean","description":"Status ativo/inativo da chapa"},"price":{"type":"number","description":"Preço da chapa","nullable":true},"stock":{"type":"number","description":"Estoque disponível da chapa"},"unit":{"type":"number","description":"Unidade/arredondamento da chapa","nullable":true}},"required":["internal_code","active","price","stock"]},"description":"Lista de chapas retornadas"},"meta":{"type":"object","properties":{"count":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Total de chapas encontradas"},"next":{"type":"number","description":"Próximo offset para paginação","nullable":true}},"required":["count","next"]}},"required":["resource","meta"]},"LegacyValidationErrorResponse":{"type":"object","properties":{"errors":{"type":"object","properties":{"message":{"type":"string","description":"Motivo do erro"},"errors":{"type":"array","items":{"type":"string"},"description":"Falhas de validação encontradas"}},"required":["message","errors"]}},"required":["errors"]},"BatchUpdateBoardsRequest":{"anyOf":[{"type":"object","properties":{"resource":{"type":"array","items":{"type":"object","properties":{"internal_code":{"description":"Código interno da chapa","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço da chapa (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque da chapa (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo da chapa","type":"boolean"}}}}},"required":["resource"]},{"type":"array","items":{"type":"object","properties":{"internal_code":{"description":"Código interno da chapa","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço da chapa (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque da chapa (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo da chapa","type":"boolean"}}}},{"type":"object","properties":{"internal_code":{"description":"Código interno da chapa","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço da chapa (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque da chapa (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo da chapa","type":"boolean"}}}]},"BatchUpdateBoardsResponse":{"type":"object","properties":{"resource":{"type":"array","items":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno da chapa","nullable":true}},"required":["internal_code"]},"description":"Lista de chapas atualizadas"}},"required":["resource"]},"GetBoardResponse":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno da chapa","nullable":true},"active":{"type":"boolean","description":"Status ativo/inativo da chapa"},"price":{"type":"number","description":"Preço da chapa","nullable":true},"stock":{"type":"number","description":"Estoque disponível da chapa"},"unit":{"type":"number","description":"Unidade/arredondamento da chapa","nullable":true}},"required":["internal_code","active","price","stock"]},"UpdateBoardRequest":{"anyOf":[{"type":"object","properties":{"resource":{"maxItems":1,"type":"array","items":{"type":"object","properties":{"internal_code":{"description":"Código interno da chapa","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço da chapa (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque da chapa (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo da chapa","type":"boolean"}}}}},"required":["resource"]},{"maxItems":1,"type":"array","items":{"type":"object","properties":{"internal_code":{"description":"Código interno da chapa","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço da chapa (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque da chapa (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo da chapa","type":"boolean"}}}},{"type":"object","properties":{"internal_code":{"description":"Código interno da chapa","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço da chapa (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque da chapa (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo da chapa","type":"boolean"}}}]},"UpdateBoardResponse":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno da chapa","nullable":true}},"required":["internal_code"]},"ListComponentsResponse":{"type":"object","properties":{"resource":{"type":"array","items":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno do componente","nullable":true},"active":{"type":"boolean","description":"Status ativo/inativo do componente"},"price":{"type":"number","description":"Preço do componente","nullable":true},"stock":{"type":"number","description":"Estoque disponível do componente"},"unit":{"type":"number","description":"Unidade/arredondamento do componente","nullable":true}},"required":["internal_code","active","price","stock"]},"description":"Lista de componentes retornados"},"meta":{"type":"object","properties":{"count":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Total de componentes encontrados"},"next":{"type":"number","description":"Próximo offset para paginação","nullable":true}},"required":["count","next"]}},"required":["resource","meta"]},"BatchUpdateComponentsRequest":{"anyOf":[{"type":"object","properties":{"resource":{"type":"array","items":{"type":"object","properties":{"internal_code":{"description":"Código interno do componente","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço do componente (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque do componente (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo do componente","type":"boolean"}}}}},"required":["resource"]},{"type":"array","items":{"type":"object","properties":{"internal_code":{"description":"Código interno do componente","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço do componente (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque do componente (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo do componente","type":"boolean"}}}},{"type":"object","properties":{"internal_code":{"description":"Código interno do componente","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço do componente (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque do componente (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo do componente","type":"boolean"}}}]},"BatchUpdateComponentsResponse":{"type":"object","properties":{"resource":{"type":"array","items":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno do componente","nullable":true}},"required":["internal_code"]}}},"required":["resource"]},"GetComponentResponse":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno do componente","nullable":true},"active":{"type":"boolean","description":"Status ativo/inativo do componente"},"price":{"type":"number","description":"Preço do componente","nullable":true},"stock":{"type":"number","description":"Estoque disponível do componente"},"unit":{"type":"number","description":"Unidade/arredondamento do componente","nullable":true}},"required":["internal_code","active","price","stock"]},"UpdateComponentRequest":{"anyOf":[{"type":"object","properties":{"resource":{"maxItems":1,"type":"array","items":{"type":"object","properties":{"internal_code":{"description":"Código interno do componente","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço do componente (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque do componente (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo do componente","type":"boolean"}}}}},"required":["resource"]},{"maxItems":1,"type":"array","items":{"type":"object","properties":{"internal_code":{"description":"Código interno do componente","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço do componente (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque do componente (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo do componente","type":"boolean"}}}},{"type":"object","properties":{"internal_code":{"description":"Código interno do componente","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço do componente (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque do componente (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo do componente","type":"boolean"}}}]},"UpdateComponentResponse":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno do componente","nullable":true}},"required":["internal_code"]},"ListEdgesResponse":{"type":"object","properties":{"resource":{"type":"array","items":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno da fita","nullable":true},"active":{"type":"boolean","description":"Status ativo/inativo da fita"},"price":{"type":"number","description":"Preço da fita","nullable":true},"stock":{"type":"number","description":"Estoque disponível da fita"},"unit":{"type":"number","description":"Unidade/arredondamento da fita","nullable":true}},"required":["internal_code","active","price","stock"]},"description":"Lista de fitas retornadas"},"meta":{"type":"object","properties":{"count":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Total de fitas encontradas"},"next":{"type":"number","description":"Próximo offset para paginação","nullable":true}},"required":["count","next"]}},"required":["resource","meta"]},"BatchUpdateEdgesRequest":{"anyOf":[{"type":"object","properties":{"resource":{"type":"array","items":{"type":"object","properties":{"internal_code":{"description":"Código interno da fita","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço da fita (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque da fita (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo da fita","type":"boolean"}}}}},"required":["resource"]},{"type":"array","items":{"type":"object","properties":{"internal_code":{"description":"Código interno da fita","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço da fita (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque da fita (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo da fita","type":"boolean"}}}},{"type":"object","properties":{"internal_code":{"description":"Código interno da fita","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço da fita (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque da fita (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo da fita","type":"boolean"}}}]},"BatchUpdateEdgesResponse":{"type":"object","properties":{"resource":{"type":"array","items":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno da fita","nullable":true}},"required":["internal_code"]}}},"required":["resource"]},"GetEdgeResponse":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno da fita","nullable":true},"active":{"type":"boolean","description":"Status ativo/inativo da fita"},"price":{"type":"number","description":"Preço da fita","nullable":true},"stock":{"type":"number","description":"Estoque disponível da fita"},"unit":{"type":"number","description":"Unidade/arredondamento da fita","nullable":true}},"required":["internal_code","active","price","stock"]},"UpdateEdgeRequest":{"anyOf":[{"type":"object","properties":{"resource":{"maxItems":1,"type":"array","items":{"type":"object","properties":{"internal_code":{"description":"Código interno da fita","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço da fita (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque da fita (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo da fita","type":"boolean"}}}}},"required":["resource"]},{"maxItems":1,"type":"array","items":{"type":"object","properties":{"internal_code":{"description":"Código interno da fita","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço da fita (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque da fita (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo da fita","type":"boolean"}}}},{"type":"object","properties":{"internal_code":{"description":"Código interno da fita","anyOf":[{"type":"string"},{"type":"number"}]},"price":{"description":"Preço da fita (valor negativo é gravado como nulo)","type":"number"},"stock":{"description":"Estoque da fita (valor negativo é gravado como 0)","type":"number"},"unit":{"description":"Unidade/arredondamento (valor menor ou igual a zero é gravado como nulo)","type":"number"},"active":{"description":"Status ativo/inativo da fita","type":"boolean"}}}]},"UpdateEdgeResponse":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno da fita","nullable":true}},"required":["internal_code"]},"ListServicesResponse":{"type":"object","properties":{"resource":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number","description":"ID do serviço"},"internal_code":{"type":"string","description":"Código interno do serviço","nullable":true},"status":{"type":"object","properties":{"code":{"type":"number","description":"Código do status do serviço"},"created_date":{"type":"string","description":"Data de criação do serviço"},"budgeted_date":{"type":"string","description":"Data de orçamento do serviço","nullable":true},"purchased_date":{"type":"string","description":"Data de aprovação do serviço","nullable":true},"authorized_date":{"type":"string","description":"Data de envio para produção","nullable":true},"finished_date":{"type":"string","description":"Data de finalização do serviço","nullable":true}},"required":["code","created_date"]}},"required":["id","status"]}},"meta":{"type":"object","properties":{"count":{"type":"number","description":"Total de serviços encontrados"},"next":{"type":"number","description":"Próximo offset para paginação","nullable":true}},"required":["count","next"]}},"required":["resource","meta"]},"LegacyErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string","description":"Motivo do erro"},"code":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status_code":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"context":{}},"required":["message"]}},"required":["error"]},"GetServiceResponse":{"type":"object","properties":{"id":{"type":"number","description":"ID do serviço"},"internal_code":{"type":"string","description":"Código interno do serviço","nullable":true},"observation":{"type":"string","description":"Observações do serviço","nullable":true},"provider":{"type":"string","description":"Origem das peças do serviço","nullable":true},"status":{"type":"object","properties":{"code":{"type":"number","description":"Código do status do serviço"},"created_date":{"type":"string","description":"Data de criação do serviço"},"budgeted_date":{"type":"string","description":"Data de orçamento do serviço","nullable":true},"purchased_date":{"type":"string","description":"Data de aprovação do serviço","nullable":true},"authorized_date":{"type":"string","description":"Data de envio para produção","nullable":true},"finished_date":{"type":"string","description":"Data de finalização do serviço","nullable":true}},"required":["code","created_date"]},"history":{"type":"array","items":{"type":"object","properties":{"event_id":{"type":"number","description":"ID do evento de status"},"event_code_from":{"type":"number","description":"Código do status anterior"},"event_name_from":{"type":"string","description":"Nome do status anterior"},"event_code_to":{"type":"number","description":"Código do novo status"},"event_name_to":{"type":"string","description":"Nome do novo status"},"event_date":{"type":"string","description":"Data do evento"},"agent":{"type":"string","description":"Agente responsável pela alteração"}},"required":["event_id","event_code_from","event_name_from","event_code_to","event_name_to","event_date","agent"]},"description":"Histórico de alterações de status do serviço"},"steps":{"type":"object","properties":{"cut":{"type":"string","description":"Data de corte das peças","nullable":true},"edge":{"type":"string","description":"Data de aplicação de fita nas peças","nullable":true},"machining":{"type":"string","description":"Data de usinagem das peças","nullable":true},"packing":{"type":"string","description":"Data de embalagem das peças","nullable":true},"cutout":{"type":"string","description":"Data de expedição das peças","nullable":true}}},"client":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno do cliente","nullable":true}}},"labour":{"type":"object","properties":{"cutting":{"type":"object","properties":{"price":{"type":"number","description":"Preço do corte das peças"},"quantity":{"type":"number","description":"Quantidade de cortes realizados"},"length":{"type":"number","description":"Comprimento total cortado"},"parts":{"type":"number","description":"Quantidade de peças cortadas","nullable":true}},"required":["price","quantity","length"]},"edging":{"type":"object","properties":{"price":{"type":"number","description":"Preço da aplicação de fita nas peças"},"quantity":{"type":"number","description":"Metragem de fita aplicada nas peças"},"parts":{"type":"number","description":"Quantidade de peças com fita aplicada","nullable":true}},"required":["price","quantity"]},"machining":{"type":"object","properties":{"price":{"type":"number","description":"Preço da usinagem das peças"},"resume":{"type":"object","properties":{"drills":{"type":"array","items":{"type":"object","properties":{"diameter":{"type":"number","description":"Diâmetro da furação"},"quantity":{"type":"number","description":"Quantidade de furações"}},"required":["diameter","quantity"]},"description":"Lista de furações agrupadas por diâmetro"},"rip":{"type":"array","items":{"type":"object","properties":{"thickness":{"type":"number","description":"Espessura do rasgo"},"quantity":{"type":"number","description":"Metragem total do rasgo"}},"required":["thickness","quantity"]},"description":"Lista de rasgos agrupados por espessura"},"filister":{"type":"array","items":{"type":"object","properties":{"thickness":{"type":"number","description":"Espessura do filister"},"quantity":{"type":"number","description":"Metragem total do filister"}},"required":["thickness","quantity"]},"description":"Lista de filisters agrupados por espessura"}},"required":["drills","rip","filister"]},"parts":{"type":"number","description":"Quantidade de peças usinadas","nullable":true}},"required":["price","resume"]},"packing":{"type":"object","properties":{"price":{"type":"number","description":"Custo da embalagem das peças"}},"required":["price"]},"delivery":{"type":"object","properties":{"price":{"type":"number","description":"Custo do frete do serviço"}},"required":["price"]}},"required":["cutting","edging","machining","packing","delivery"]},"materials":{"type":"object","properties":{"boards":{"type":"array","items":{"type":"object","properties":{"description":{"type":"string","description":"Descrição da chapa"},"internal_code":{"type":"string","description":"Código interno da chapa","nullable":true},"price":{"type":"number","description":"Preço da chapa","nullable":true},"quantity":{"type":"number","description":"Quantidade de chapas utilizadas","nullable":true},"parts":{"type":"number","description":"Quantidade de peças produzidas a partir da chapa","nullable":true},"thickness":{"type":"number","description":"Espessura da chapa","nullable":true},"length":{"type":"number","description":"Comprimento da chapa","nullable":true},"width":{"type":"number","description":"Largura da chapa","nullable":true}},"required":["description"]},"description":"Lista de chapas utilizadas no serviço"},"edges":{"type":"array","items":{"type":"object","properties":{"description":{"type":"string","description":"Descrição da fita"},"internal_code":{"type":"string","description":"Código interno da fita","nullable":true},"price":{"type":"number","description":"Preço da fita","nullable":true},"quantity":{"type":"number","description":"Quantidade de fitas utilizadas","nullable":true},"unit":{"type":"number","description":"Quantidade de unidades de fita utilizadas","nullable":true},"applied":{"type":"number","description":"Metragem de fitas aplicadas nas peças","nullable":true},"thickness":{"type":"number","description":"Espessura da fita","nullable":true},"width":{"type":"number","description":"Largura da fita","nullable":true}},"required":["description"]},"description":"Lista de fitas utilizadas no serviço"},"components":{"type":"array","items":{"type":"object","properties":{"description":{"type":"string","description":"Descrição do componente"},"internal_code":{"type":"string","description":"Código interno do componente","nullable":true},"price":{"type":"number","description":"Preço do componente","nullable":true},"quantity":{"type":"number","description":"Quantidade de componentes utilizados","nullable":true},"unit":{"type":"number","description":"Unidade de medida do componente","nullable":true}},"required":["description"]},"description":"Lista de componentes utilizados no serviço"}},"required":["boards","edges","components"]},"parts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number","description":"ID da peça"},"length":{"type":"number","description":"Comprimento da peça","nullable":true},"width":{"type":"number","description":"Largura da peça","nullable":true},"quantity":{"type":"number","description":"Quantidade de peças","nullable":true},"function":{"type":"string","description":"Função da peça","nullable":true},"description":{"type":"string","description":"Descrição da peça","nullable":true},"board":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno da chapa utilizada na peça","nullable":true}},"description":"Chapa utilizada na peça","nullable":true},"edges":{"type":"object","properties":{"c1":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno da fita aplicada","nullable":true}},"nullable":true},"c2":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno da fita aplicada","nullable":true}},"nullable":true},"l1":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno da fita aplicada","nullable":true}},"nullable":true},"l2":{"type":"object","properties":{"internal_code":{"type":"string","description":"Código interno da fita aplicada","nullable":true}},"nullable":true}},"description":"Fitas aplicadas em cada lado da peça"},"drills":{"type":"object","properties":{"top":{"type":"number","description":"Quantidade de furações no topo","nullable":true},"face_a":{"type":"number","description":"Quantidade de furações na face A","nullable":true},"face_b":{"type":"number","description":"Quantidade de furações na face B","nullable":true}},"description":"Furações realizadas na peça"},"machining":{"type":"object","properties":{"face_a":{"type":"boolean","description":"Indica se houve usinagem na face A","nullable":true},"face_b":{"type":"boolean","description":"Indica se houve usinagem na face B","nullable":true}},"description":"Usinagem realizada na peça"}},"required":["id","edges","drills","machining"]},"description":"Lista de peças produzidas no serviço"}},"required":["id","status","history","steps","client","labour","materials","parts"]},"UpdateServiceRequest":{"type":"object","properties":{"internal_code":{"anyOf":[{"type":"string"},{"type":"number"}],"description":"Código interno do serviço","nullable":true}}},"UpdateServiceResponse":{"type":"object","properties":{"id":{"type":"number","description":"ID do serviço"}},"required":["id"]},"PrivateApiErrorResponse":{"type":"object","properties":{"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Status HTTP da resposta"},"name":{"type":"string","description":"Nome do erro"},"message":{"type":"string","description":"Motivo do erro"}},"required":["status","name","message"]},"SendToProductionRequest":{"type":"object","properties":{"sellerEmail":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$","description":"E-mail do vendedor da central responsável pelo envio"}},"required":["sellerEmail"]},"SendToProductionResponse":{"type":"object","properties":{"id":{"type":"number","description":"ID do serviço"}},"required":["id"]},"CancelCheckoutRequest":{"type":"object","properties":{"serviceId":{"type":"number","description":"ID do serviço a ser cancelado"}},"required":["serviceId"]},"CancelCheckoutResponse":{"type":"object","properties":{"message":{"type":"string","description":"Mensagem de confirmação da operação"}},"required":["message"]},"FinishCheckoutRequest":{"type":"object","properties":{"serviceId":{"type":"number","description":"ID do serviço a ser finalizado"},"paymentId":{"type":"string","description":"ID do pagamento associado ao checkout"}},"required":["serviceId","paymentId"]},"FinishCheckoutResponse":{"type":"object","properties":{"message":{"type":"string","description":"Mensagem de confirmação da operação"}},"required":["message"]},"ReturnServiceRequest":{"type":"object","properties":{"serviceId":{"type":"number","description":"ID do serviço a ser devolvido"},"paymentId":{"type":"string","description":"ID do pagamento vinculado ao serviço"}},"required":["serviceId","paymentId"]},"ReturnServiceResponse":{"type":"object","properties":{"message":{"type":"string","description":"Mensagem de confirmação da operação"}},"required":["message"]},"CheckoutUrlRequest":{"type":"object","properties":{"serviceId":{"type":"number","description":"ID do serviço para salvar a URL de checkout"},"url":{"type":"string","description":"URL do checkout a ser persistida"}},"required":["serviceId","url"]},"CheckoutUrlResponse":{"type":"object","properties":{"message":{"type":"string","description":"Mensagem de confirmação da operação"}},"required":["message"]},"QuickServiceRequest":{"type":"object","properties":{"companyInternalCode":{"type":"string","minLength":1,"description":"Código interno da central"},"productionInternalCode":{"type":"string","minLength":1,"description":"Código interno da linha de produção"},"sellerEmail":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$","description":"Email do vendedor"},"sellerName":{"type":"string","minLength":1,"description":"Nome do vendedor"},"carpenterEmail":{"type":"string","minLength":1,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$","description":"Email do marceneiro (cliente) a cadastrar/vincular"},"carpenterName":{"type":"string","minLength":1,"description":"Nome do marceneiro (cliente) a cadastrar/vincular"},"carpenterInternalCode":{"type":"string","minLength":1,"description":"Identificador único do marceneiro (cliente) a cadastrar/vincular"}},"required":["companyInternalCode","productionInternalCode","sellerEmail","sellerName","carpenterEmail","carpenterName","carpenterInternalCode"]},"UserServiceErrorResponse":{"type":"object","properties":{"error":{"type":"string","description":"Motivo do erro"}},"required":["error"]},"EmbedSessionResponse":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"URL de destino"}},"required":["url"]},"ServiceRequest":{"type":"object","properties":{"carpenterEmail":{"type":"string","minLength":1,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$","description":"Email do marceneiro (cliente) a cadastrar/vincular"},"carpenterName":{"type":"string","minLength":1,"description":"Nome do marceneiro (cliente) a cadastrar/vincular"}},"required":["carpenterEmail","carpenterName"]}}},"security":[{"SB1-HMAC-SHA256":[],"x-company-internal-code":[]}]}