SKU vs SkuId vs ProductId¶
A Gubee usa três identificadores distintos para representar entidades de catálogo. Entender a diferença é pré-requisito para escolher o endpoint correto e evitar os erros mais comuns de integração (404, routing incorreto, duplicação).
Os três identificadores¶
| Identificador | Origem | Tipo | Estabilidade | Exemplo |
|---|---|---|---|---|
| sku | Definido pelo seller (ERP/ecommerce) | String livre |
Mutável pelo seller | "SKU-DEMO-001" |
| skuId | Gerado pela Gubee ao criar a variação | String opaca, pode conter / |
Imutável, mas pode conter barras | "ABCD-1234" ou "ABC/DEF-001" |
| productId | externalId enviado pelo seller ao criar o produto pai |
String livre |
Mutável via update | "PROD-DEMO-001" |
Relação: um produto (productId) tem N variações, cada uma com seu
próprio sku (do seller) e skuId (Gubee). Preço e estoque são por variação
(skuId), não por produto.
Por que o skuId pode conter /?¶
Por razões históricas de modelagem, alguns skuIds são compostos por
<prefixo>/<sufixo>. Isso quebra o routing de URL porque o o roteamento trata /
como separador de path segment.
Como descobrir o skuId a partir do sku¶
Use o endpoint dedicado (SkuResolveResource), com cache Caffeine no BFF:
- TTL: 5 minutos (
cache.sku-id.ttl: 5m) - Capacidade: 50.000 entradas por instância (
cache.sku-id.max-size: 50000) - Chave de cache:
sellerId + ':' + sku
# sku -> skuId
curl -s -X GET "$GUBEE_API/integration/skus/by-sku?sku=SKU-DEMO-001" \
-H "Authorization: Bearer $JWT"
{
"id": "4e8b3f01-1234-4abc-9def-426614174000",
"skuId": "ABCD-1234",
"sku": "SKU-DEMO-001",
"ean": "7891234567890"
}
Caminho inverso (skuId → sku):
curl -s -X GET "$GUBEE_API/integration/skus/by-skuid?skuId=ABCD-1234" \
-H "Authorization: Bearer $JWT"
Há também rotas em lote em /integration/products/skuIds/bySkus (GET e POST)
para resolver vários SKUs de uma vez — útil em importações iniciais.
Diagrama de fluxo¶
+-----------------------+
sku (seller) | |
─────────>| BFF /integration/skus/by-sku
| |
| SkuResolver (cache) |
| |
| -> priceservice |
| (downstream) |
| |
+-----------+-----------+
|
v
skuId (Gubee, pode ter '/')
|
v
+---------------------------+
| PUT /integration/prices/* |
| PUT /integration/stocks/* |
+---------------------------+
As três variantes de endpoint¶
A maior parte dos endpoints de escrita (preço, estoque, imagem) existem em três sabores. Exemplo com preço:
Variante 1: path params — PUT /integration/prices/{productId}/{skuId}¶
curl -X PUT "$GUBEE_API/integration/prices/PROD-DEMO-001/ABCD-1234" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{ "value": 199.90, "type": "DEFAULT" }'
- Mais RESTful e cacheável por CDN.
- Quebra se o
skuIdcontiver/. O roteamento HTTP não consegue distinguir/ABCD/DEF-001de dois segmentos de path. - Recomendado quando você tem certeza de que os skuIds são simples.
Variante 2: body params — PUT /integration/prices/v2¶
curl -X PUT "$GUBEE_API/integration/prices/v2" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{
"productId": "PROD-DEMO-001",
"skuId": "ABC/DEF-001",
"price": { "value": 199.90, "type": "DEFAULT" }
}'
- Mesma semântica da variante 1, mas com identificadores no body.
- Funciona com skuId contendo
/. - Use quando você já tem o skuId e ele pode conter barras.
- Existe também
/list/v2para enviar múltiplos preços.
Variante 3: by sku (resolução interna) — PUT /integration/prices/bysku¶
curl -X PUT "$GUBEE_API/integration/prices/bysku" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{
"sku": "SKU-DEMO-001",
"price": { "value": 199.90, "type": "DEFAULT" }
}'
- O BFF resolve
sku → skuIdinternamente viaSkuResolver(cacheado 5min). - O integrador não precisa conhecer o skuId — trabalha só com o próprio sku.
- Recomendado para integrações ERP/hub: você não precisa sincronizar o skuId, que é opaco.
- Mesma variante existe em estoque (
/integration/stocks/bysku).
Matriz de decisão¶
| Situação | Variante recomendada |
|---|---|
| Integrador trabalha com SKU próprio (ERP/hub) | /bysku (resolução interna cacheada) |
Integrador já persistiu o skuId e sabe que é simples (sem /) |
/{productId}/{skuId} (RESTful) |
Integrador tem skuId mas ele pode conter / |
/v2 (body params) |
| Sincronização inicial em lote (centenas de itens) | /bysku em paralelo (5–10 conexões) |
Endpoint sem variante /bysku |
/v2 ou /{productId}/{skuId} após resolver via /integration/skus/by-sku |
Rotas de leitura¶
Para ler preço/estoque por sku, use:
# preço por sku
curl -X GET "$GUBEE_API/integration/prices/bysku?sku=SKU-DEMO-001" \
-H "Authorization: Bearer $JWT"
# estoque por sku (todos os warehouses)
curl -X GET "$GUBEE_API/integration/stocks/bysku?sku=SKU-DEMO-001" \
-H "Authorization: Bearer $JWT"
Há também rotas por itemId (skuId de produto ou adId de anúncio):
GET /integration/prices/{platform}/{itemId}GET /integration/stocks/{itemId}/{warehouseId}GET /integration/stocks/all/{platform}/{itemId}(todos os warehouses)
Em leituras,
{itemId}éskuIdpara domínioPRODUCTeadIdpara domínioAD. Veja Ad vs Produto para entender a diferença.
Erros comuns¶
404 Not Found em /{productId}/{skuId} quando skuId contém /¶
Sintoma: o skuId é ABC/DEF-001 e o endpoint retorna 404 mesmo existindo.
Causa: o roteamento interpreta ABC/DEF-001 como dois segmentos de path.
Solução: use /v2 ou /bysku.
404 SKU not found em /bysku¶
Sintoma: o sku existe no ERP mas o endpoint não encontra.
Causa: o produto não foi criado ainda, ou foi criado com sku diferente, ou o
cache do SkuResolver está stale (5min).
Solução:
1. Confirme com GET /integration/products/bySku/{sku} que o produto existe.
2. Aguarde 5 minutos para o cache expirar caso tenha criado o produto agora.
3. Recrie o produto com POST /integration/products/v2/createupdate se necessário.
Duplicação de variação ao usar /{productId}/{skuId} com skuId errado¶
Sintoma: ao atualizar, um novo skuId é gerado em vez de atualizar o existente.
Causa: o skuId informado não casa com nenhum existente para o productId; o downstream interpreta como criação.
Solução: sempre resolva o skuId via /integration/skus/by-sku antes de chamar
variantes /{productId}/{skuId} ou /v2.
Referência rápida de endpoints¶
Resolução¶
| Método | Path | Descrição |
|---|---|---|
GET |
/integration/skus/by-sku?sku=X |
sku → skuId |
GET |
/integration/skus/by-skuid?skuId=X |
skuId → sku |
GET |
/integration/products/skuIds/bySkus?skus=A,B,C |
lote sku → skuId |
POST |
/integration/products/skuIds/bySkus |
lote (sem limite de URL) |
GET |
/integration/products/skus/bySkuIds?skuIds=A,B,C |
lote skuId → sku |
POST |
/integration/products/skus/bySkuIds |
lote (sem limite de URL) |
Produto¶
| Método | Path | Identificador |
|---|---|---|
GET |
/integration/products/{productId} |
productId |
GET |
/integration/products/bySku/{sku} |
sku |
GET |
/integration/products/bySkuId/{skuId} |
skuId |
POST |
/integration/products/v2/createupdate |
externalId no body |
PUT |
/integration/products/{productId} |
productId |
PATCH |
/integration/products/{externalId} |
externalId |
Próximos passos¶
- Quickstart: fluxo completo usando
/bysku. - CQRS e consistência eventual: por que preço e estoque são assíncronos.
- Ad vs Produto: por que o mesmo produto tem múltiplos
anúncios e como isso afeta
itemId.