Pular para conteúdo

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 skuId contiver /. O roteamento HTTP não consegue distinguir /ABCD/DEF-001 de 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/v2 para 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 → skuId internamente via SkuResolver (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} é skuId para domínio PRODUCT e adId para domínio AD. 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