Pular para conteúdo

Anúncio vs Produto

A distinção entre produto e anúncio é central na modelagem Gubee. Confundir os dois leva a erros como atualizar preço no produto quando o desejado era no anúncio, ou esperar que uma edição no catálogo reflita instantaneamente na publicação.

O que é um produto?

Um produto é a entidade de catálogo. Tem:

  • Um externalId (também chamado productId), definido pelo seller.
  • Metadados (título, descrição, marca, dimensões, NBM).
  • N variações, cada uma com seu próprio sku (do seller) e skuId (Gubee).
  • Imagens e vídeos por variação.
  • Atributos, categorias, EAN.

Rotas canônicas: /integration/products/*.

O produto não está associado a um marketplace específico. Ele é a "fonte da verdade" do catálogo.

O que é um anúncio?

Um anúncio é a publicação do produto em um marketplace específico. Tem:

  • Um adId (gerado pela Gubee).
  • Um originSkuId que aponta para a variação do produto que o originou.
  • Um platform (MERCADOLIVRE, SHOPEE, etc.).
  • Título e descrição enriquecidos por template (podem diferir do produto).
  • Preço, estoque e imagens específicos da publicação.
  • Status (ACTIVE, INACTIVE, PAUSED).

Rotas canônicas: /integration/ads/* e /bffweb/ads/*.

Relação: 1 produto → N anúncios

Para um produto com N variações publicado em M marketplaces, existem até N×M anúncios. Cada anúncio é independente: preço e estoque podem variar por marketplace, mesmo que o produto subjacente seja o mesmo.

                  PRODUTO (productId=PROD-001)
                 /          |           \
          var skuId-A   var skuId-B   var skuId-C
              |             |             |
       +------+------+ +----+----+ +------+------+
       |      |      | |         | |      |      |
      ML     SHOPEE  B2W  ML    SHOPEE  ML    SHOPEE  B2W
       |      |      |   |        |       |     |      |
     ad#1   ad#2  ad#3 ad#4    ad#5    ad#6  ad#7  ad#8

Cada ad#N tem seu próprio adId e seu próprio preço/estoque.

Replicação produto → anúncio

A replicação de imagens e vídeos do produto para os anúncios derivados é controlada pelo campo updateOptions no anúncio:

var updateOptions: Set<UpdateOption> = mutableSetOf()

Valores do enum UpdateOption:

  • IMAGES: alterações nas imagens da variação do produto são replicadas para o anúncio via plataforma de streaming de eventos (ProductImageUpdated).
  • VIDEOS: idem para vídeos (mediaservice.video.ready).

Quando IMAGES ou VIDEOS estão no set, o anúncio "herda" as mudanças. Caso contrário, o anúncio mantém imagem/vídeo próprios.

Toggle da replicação

Atenção: este endpoint está em /bffweb (superfície web), não em /integration. Parceiros ERP/hub raramente precisam tocá-lo — a replicação é normalmente configurada via painel.

curl -X PUT "$GUBEE_API/bffweb/ads/update/updateOptions" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "adIds": ["ad#1", "ad#2"],
    "updateOptions": ["IMAGES", "VIDEOS"]
  }'

Resposta (202 Accepted): lista de adIds afetados.

["ad#1", "ad#2"]

Endpoints de anúncio (superfície /integration)

Listar anúncios por originSkuId

curl -X GET "$GUBEE_API/integration/ads/list/byOriginSkuId?originSkuIds=SKU-DEMO-001,SKU-DEMO-002" \
  -H "Authorization: Bearer $JWT"
[
  {
    "id": "ad#1",
    "sellerId": "SELLER123",
    "originSkuId": "SKU-DEMO-001",
    "platform": "MERCADOLIVRE",
    "status": "ACTIVE",
    "name": "Tênis Runner Preto 42 - ML",
    "defaultPrice": { "value": 209.90 }
  },
  {
    "id": "ad#5",
    "sellerId": "SELLER123",
    "originSkuId": "SKU-DEMO-002",
    "platform": "SHOPEE",
    "status": "ACTIVE",
    "name": "Tênis Runner Preto 43 - SHOPEE"
  }
]

Limite de 10 originSkuIds por chamada. Acima disso, retorna 400.

Detalhe completo (com template enriquecido)

curl -X GET "$GUBEE_API/integration/ads/full/ad%231" \
  -H "Authorization: Bearer $JWT"

Retorna AdGroupApiDTO com:

  • Título e descrição finais (após aplicação do template).
  • Todas as variações do grupo (se o anúncio for pai de variações).
  • Preço, estoque, imagens, vídeos, atributos, especificações.

Buscar originSkuIds por critério

curl -X POST "$GUBEE_API/integration/ads/search/originSkuIds/MERCADOLIVRE" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "ACTIVE",
    "onlySimple": true
  }'

Retorna lista de originSkuIds cujos anúncios na plataforma informada casam com o critério. Útil para sincronização inicial de catálogo.

Mapear adIdoriginSkuId

curl -X POST "$GUBEE_API/integration/ads/map/originSkuIds" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '["ad#1", "ad#2", "ad#999"]'
{
  "ad#1": "SKU-DEMO-001",
  "ad#2": "SKU-DEMO-001"
}

ad#999 foi omitido da resposta porque não existe ou não tem originSkuId. Esta é a semântica do endpoint: IDs inválidos são silenciosamente descartados.

Expandir adIds pais para filhos

curl -X POST "$GUBEE_API/integration/ads/obtain/originSkuIds" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '["ad-parent#1"]'

Retorna Set<String> com todos os originSkuIds das variações filhas. Útil quando o parceiro recebe um adId pai (que não é publicável individualmente) e precisa dos itens filhos.

Quando usar endpoint de produto vs anúncio

Cenário Use
Criar/atualizar dados de catálogo (título, descrição, dimensões, EAN) /integration/products/*
Sincronizar preço/estoque "default" do produto /integration/prices/* e /integration/stocks/* (domínio PRODUCT)
Sincronizar preço/estoque por marketplace /integration/prices/platforms/{itemId} com adId como itemId
Ler como o anúncio está publicado (com template aplicado) /integration/ads/full/{id}
Descobrir quais anúncios existem para um SKU /integration/ads/list/byOriginSkuId
Replicar imagens/vídeos para anúncios /bffweb/ads/update/updateOptions
Atualizar título/descrição específicos do anúncio /integration/ads/titledescription/byOriginSkuId/{skuId}

itemId: skuId vs adId

Em endpoints que aceitam {itemId} (preço, estoque), o significado depende do domínio:

  • domainType=PRODUCT (default): itemId é o skuId da variação.
  • domainType=AD: itemId é o adId.
# preço de um produto (default)
curl -X GET "$GUBEE_API/integration/prices/MERCADOLIVRE/SKUID-123" \
  -H "Authorization: Bearer $JWT"

# preço de um anúncio específico
curl -X PUT "$GUBEE_API/integration/prices/platforms/ad%231?domainType=AD" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '[{ "platform": "MERCADOLIVRE", "value": 219.90, "priceType": "DEFAULT" }]'

Consistência entre produto e anúncio

Após atualizar preço/estoque no produto, a propagação para os anúncios derivados acontece via plataforma de streaming de eventos e pode levar até 30s (e mais se a replicação estiver com updateOptions desativada — nesse caso, o anúncio mantém valor próprio). Veja CQRS e consistência eventual.

Anúncios são derivados do produto por um job interno; não tente criar anúncios manualmente para refletir uma mudança de produto. A criação de anúncio é um fluxo de publicação separado (normalmente via painel web).

Resumo

  • Produto = catálogo, fonte da verdade, identificado por productId / sku / skuId.
  • Anúncio = publicação em marketplace, identificado por adId, ligado ao produto via originSkuId.
  • Preço/estoque podem estar em qualquer dos dois domínios — escolha pelo domainType ou pelo endpoint (/prices/bysku vs /prices/platforms/{itemId}).
  • Replicação é controlada por updateOptions (IMAGES, VIDEOS).
  • Latência entre produto e anúncio é medida em segundos, não milissegundos.

Próximos passos