2026-05-17
v0.10.0 — Configuração de portal por produto aceita UUID
Quem integra Garu via API normalmente recebe UUIDs (list_products, webhooks, GET /api/products). Mas os endpoints /portal-config exigiam o id numérico interno — uma pegadinha que custou um incidente real (UUID era convertido pra 0 ou NaN por parseInt, e devolvia 500 em vez de uma mensagem útil).
A v0.10.0 corrige os dois lados: aceita UUID no endpoint canônico e devolve 400 limpo quando a entrada não é nem UUID nem id numérico.
GET/POST/PATCH/DELETE /api/products/:id/portal-config aceita UUID:id agora aceita o UUID do produto (preferido) ou o id numérico legado. A resolução é automática — strings numéricas vão pelo path inteiro, qualquer outra string é tratada como UUID.
# UUID — recomendado
curl -X POST https://garu.com.br/api/products/a1b2c3d4-e5f6-7890-abcd-ef1234567890/portal-config \
-H "Authorization: Bearer $GARU_API_KEY" \
-d '{"businessName": "Coach Maria", "primaryColor": "#257264"}'
# Id numérico — ainda funciona (back-compat)
curl -X POST https://garu.com.br/api/products/57/portal-config \
-H "Authorization: Bearer $GARU_API_KEY" \
-d '{"businessName": "Coach Maria", "primaryColor": "#257264"}'
A ownership check carrega o produto pelo identificador resolvido e valida que pertence ao seller chamando — mesma garantia de antes, agora com mais de um identificador na porta de entrada.
/api/portal/configuration/product/:id devolve 400 em vez de 500GET e PUT /api/portal/configuration/product/:productId continuam aceitando só o id numérico (esse endpoint está deprecado em favor do canônico acima). Mas agora ParseIntPipe rejeita entradas não-numéricas com 400 "Validation failed (numeric string is expected)" antes de tocar o banco — antes, parseInt silencioso convertia "abc…" em NaN e a query falhava com 500 genérico.
Strings que não são nem UUID válido nem id inteiro (ex.: "abc", UUID truncado) eram passadas direto pro Postgres, que respondia invalid input syntax for type uuid → 500 genérico — exatamente a mesma classe de bug que motivou a versão. Agora a validação acontece no service (isUUID do class-validator) antes da query e devolve 404.
Quando o caller passa um identificador (UUID ou id) de um produto que existe mas pertence a outro seller, a resposta agora é 404 Product not found em vez de 403 Product does not belong to this seller. Pequena mudança de contrato, motivada por segurança: a resposta 403 confirmava a existência do recurso pra quem não deveria saber. Comportamento "exists but not yours" e "doesn't exist" agora são indistinguíveis.
A seção "Configuração por Produto" em /api-reference/assinaturas/portal virou um link pra página canônica em /api-reference/produtos/portal-config. Sem mais dois exemplos divergentes pra mesma feature.
Aditivo, sem breaking change. Quem chama com id numérico continua igual. Quem quiser migrar pra UUID pode trocar o segmento do path — não precisa mudar mais nada.
@garuhq/node e @garuhq/mcp ainda assinam productId: number. A REST API aceita UUID hoje; o wrapper UUID-first no SDK e a atualização da descrição da MCP tool vêm num release próximo.