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}

Response completa

{
"id": "uuid-seller-product",
"title": "Caneca Arte Abstrata",
"description": "Caneca com arte exclusiva",
"slug": "caneca-arte-abstrata",

"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",
"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",
"avatarUrl": "https://..."
},

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

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

O que cada bloco alimenta no frontend

BlocoDadosUso no frontend
storenome, slug, avatar, contadoresHeader da loja, link "ver mais"
artworkid, título, preview, dominantColorFallback de galeria, SEO, cor de fundo
title/description/slugtexto do produtoSEO, breadcrumb, compartilhamento
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
minPriceCents/maxPriceCentsrange de preço"A partir de R$ X"
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. Filtra por allowedOptions: template com options: {"color": "blue"} mas variante com allowedOptions: {"color": ["black", "white"]} → render excluído
  6. Templates com options: null aparecem em todas as variantes

Produtos relacionados

O endpoint de detalhe retorna relatedProducts:

"relatedProducts": {
"sameArtwork": [...],
"sameArtist": [...],
"recommended": [...]
}
CategoriaO que retornaLimite
sameArtworkOutros produtos com a mesma artwork12
sameArtistOutros produtos do mesmo seller12
recommendedMesmo tipo de produto de outros sellers12

Cada card retorna: id, title, slug, minPriceCents, thumbnailUrl, productTypeName, storeSlug, artistName.

Prioridade do thumbnail
  1. Imagem isPrimary da galeria
  2. Primeira imagem da galeria
  3. Último render disponível
  4. Preview da artwork (fallback)