Pular para o conteúdo principal

Página Pública do Produto

A response do endpoint público contém tudo que o frontend precisa para renderizar a PDP (Product Detail Page).

Endpoint​

GET /stores/{store_slug}/products/{product_slug}

Também disponível por ID: GET /stores/{store_slug}/products/{product_id}.

Para listar todos os produtos da loja (sem detalhe): GET /stores/{store_slug}/products.

:::danger Não use o endpoint do seller no frontend público O frontend público deve usar apenas /stores/{slug}/products/.... Nunca chame /seller-products/me — esse é o endpoint do dashboard do seller (requer autenticação, expõe campos internos de placement, e retorna estado editável inclusive para produtos não publicados). :::

Response completa​

{
"id": "uuid-seller-product",
"title": "Caneca Arte Abstrata",
"description": "Caneca com arte exclusiva",
"slug": "caneca-arte-abstrata",
"tags": ["abstrato", "canecas"],
"backgroundColor": "#F5E6D3",

"productTypeId": "uuid-product-type",
"productTypeName": "Caneca Cerâmica",
"productTypeSlug": "caneca-ceramica",

"assetDefinitions": [
{
"key": "size",
"label": "Tamanho",
"values": [
{ "value": "350ml", "label": "350ml" },
{ "value": "700ml", "label": "700ml" }
]
},
{
"key": "finish",
"label": "Acabamento",
"values": [
{ "value": "glossy", "label": "Brilhante" },
{ "value": "matte", "label": "Fosco" }
]
}
],

"optionDefinitions": [
{
"key": "color",
"label": "Cor",
"inputType": "color_picker",
"displayBehavior": "filter",
"required": true,
"values": [
{ "value": "black", "label": "Preto", "hexColor": "#000000" },
{ "value": "white", "label": "Branco", "hexColor": "#FFFFFF" },
{ "value": "red", "label": "Vermelho", "hexColor": "#FF0000" },
{ "value": "blue", "label": "Azul Marinho", "hexColor": "#1261A0" }
]
}
],

"skus": [
{
"id": "uuid-seller-variant-1",
"productVariantId": "uuid-variant-glossy-350",
"isActive": true,
"allowedOptions": { "color": ["black", "white", "red", "blue"] },
"optionLabel": "350ml Brilhante",
"priceCents": 4990,
"renders": [
{
"templateId": "caneca-350ml-black-v1",
"url": "https://cdn.../render-black.webp",
"options": { "color": "black" }
},
{
"templateId": "caneca-350ml-white-v1",
"url": "https://cdn.../render-white.webp",
"options": { "color": "white" }
}
]
}
],

"minPriceCents": 4990,
"maxPriceCents": 6990,

"store": {
"storeName": "Arte Store",
"storeSlug": "arte-store",
"displayName": "Arte Store",
"avatarUrl": "https://...",
"isFollowing": null
},

"artwork": {
"id": "uuid-artwork",
"title": "Arte Abstrata",
"previewUrl": "https://...",
"dominantColor": "#6b4f2a"
},

"images": [{ "url": "https://...", "altText": "Foto 1", "isPrimary": true }],

"likesCount": 15,
"isLiked": null,

"relatedProducts": {
"sameArtwork": ["...StoreProductResponse[]"],
"sameArtist": ["...StoreProductResponse[]"],
"recommended": ["...StoreProductResponse[]"]
}
}

:::info isFollowing / isLiked são null para visitantes anônimos Para usuários autenticados, são true ou false. Use esse valor para alternar o ícone do botão (ex: coração cheio vs vazio) e esconder o botão quando null se preferir forçar login antes da ação. :::

O que cada bloco alimenta no frontend​

BlocoDadosUso no frontend
storenome, slug, displayName, avatar, isFollowingHeader da loja, botão "seguir", link "ver mais"
artworkid, título, preview, dominantColorFallback de galeria, SEO, cor de fundo
title/description/slugtexto do produtoSEO, breadcrumb, compartilhamento
tagslista de stringsSEO, filtros de busca
backgroundColorhex colorCor de fundo customizada da PDP
assetDefinitionstamanho, acabamento, etc.Seletores que mudam SKU/preço
optionDefinitionscor, etc. com inputType e displayBehaviorSeletores visuais (color picker, radio)
skus[]variantes com preço, allowedOptions, rendersPreço, galeria, options disponíveis
skus[].renders[]templateId, url, optionsImagens filtradas por option
images[]fotos da galeria (uploaded pelo seller)Galeria estática (não muda com options)
minPriceCents/maxPriceCentsrange de preço"A partir de R$ X"
likesCount / isLikedcontador e estado do like do usuárioBotão de coração + contador
relatedProductssameArtwork, sameArtist, recommendedCarousels de recomendação (só no detalhe)
informação

Nada está faltando. O frontend não precisa de requests adicionais — tudo vem em uma única chamada.

Como o backend monta os renders por SKU​

Para cada SKU (SellerProductVariant):

  1. Pega assets da ProductVariant (ex: {"size": "350ml", "finish": "glossy"})
  2. Busca templates ativos do ProductType
  3. Filtra templates cujos assets são subconjunto dos assets da variante
  4. Para cada match, busca o render mais recente com status rendered
  5. Se existe render, adiciona ao array renders[] do SKU com templateId, url e options
  6. Filtra por allowedOptions: template com options: {"color": "blue"} mas variante com allowedOptions: {"color": ["black", "white"]} → render excluído
  7. Templates com options: null aparecem em todas as variantes (genéricos)

Produtos relacionados​

O endpoint de detalhe retorna relatedProducts com 3 categorias:

CategoriaO que retornaLimite
sameArtworkOutros produtos usando a mesma artwork (outros tipos de produto ou sellers)12
sameArtistOutros produtos do mesmo seller com outras artworks12
recommendedMesmo tipo de produto de outros sellers (mais recentes primeiro)12

:::info Formato completo, não um card reduzido Cada item em sameArtwork[], sameArtist[] e recommended[] retorna o mesmo formato (StoreProductResponse) do produto principal — com SKUs, renders, store, artwork, likesCount, etc.

Isso permite renderizar mockups reais nos cards do carousel sem chamadas adicionais. O endpoint de listagem (GET /stores/{slug}/products) não retorna relatedProducts (por performance). :::

Para escolher a imagem de cada card, veja getRelatedProductImage em Galeria e Filtragem.