CamadaDoisDocumentação

Formato aberto

Feed de catálogo

v1 · setembro de 2026

O seu catálogo continua no seu sistema. Publique uma URL que devolva os produtos em JSON e o atendente da CamadaDois passa a cotar com os preços da sua loja — na moeda do cliente, com a quantidade certa e o link do produto. Qualquer loja, ERP ou desenvolvedor implementa este formato em uma tarde.

1. O endpoint

  • GET em https:// (http é recusado), resposta application/json em UTF-8.
  • Autenticação opcional por um cabeçalho fixo (ex.: Authorization: Bearer …). Credenciais na própria URL não são aceitas.
  • A resposta é uma lista JSON de produtos, ou um objeto com a lista em items (também aceitos: products, data) e um next opcional com a próxima página:
{ "items": [ … ], "next": "https://loja.example.com/api/products?page=2" }
  • Cada leitura deve trazer todos os produtos à venda. Um produto que some do feed é tratado como descontinuado (desativado, nunca apagado — volta quando reaparecer). Um feed vazio é tratado como erro e não altera nada.
  • Recomendado: enviar ETag e/ou Last-Modified. A sincronização usa If-None-Match / If-Modified-Since; um 304 não custa nada.
  • Limites: 20 MB por página, 30 s por requisição, 50 páginas.

2. O produto

Nomes canônicos abaixo; os apelidos entre parênteses também são aceitos, então uma API existente costuma funcionar sem mudanças. Qualquer campo de texto pode ser um mapa por idioma — { "pt-BR": "Cone de pétalas", "en-US": "Petal cone" } — e o atendente responde no idioma do cliente.

Obrigatórios

sku (id, code)textoSeu identificador estável. Único no feed.
name (title)texto ou mapa por idiomaNome de exibição.
prices ou pricever seção 3Pelo menos um preço.

Recomendados

prices{ "BRL": 6.5, "EUR": 0.87 }Preço por moeda (ISO 4217). Preferido. Números JSON, não strings.
currencytextoMoeda de price quando não há prices (padrão: a moeda da empresa).
pricenúmeroPreço base, usado só quando não há prices.
slug (handle)textoIdentificador de URL; permite montar o link do produto.
url (link)textoPágina do produto. O atendente compartilha para o cliente ver fotos e comprar.
descriptiontexto ou mapaPesquisável (primeiros ~500 caracteres por idioma).
categorytexto ou mapaAlimenta a resposta a “o que vocês vendem?”.
product_typetextophysical, digital, service…
imageslista de URLsA primeira vira a imagem do produto.
is_active (active)booleanofalse esconde o produto (padrão true).
offer_only / hiddenbooleanotrue esconde do catálogo público.

Opcionais

unittextoUnidade de venda (padrão un).
min_qty (min_quantity)inteiroQuantidade mínima; o atendente avisa o cliente.
price_tiers[{ "min_qty": 10, "price": 5.9, "currency": "BRL" }]Preços por volume. O atendente aplica a maior faixa cujo min_qty ≤ quantidade — e somente essas; nunca inventa desconto.
in_stock (available)booleanoDisponibilidade. Ausente = o atendente não promete estoque.
stock (stock_qty)inteiroUnidades disponíveis; implica in_stock.
lead_time_daysinteiroPrazo de produção/despacho.
country_exclusion["BR", "US"]Países (ISO 3166-1) onde o produto NÃO é vendido.
features, brand, options…qualquer JSONGuardados como atributos (≤ 8 KB) e pesquisáveis quando texto.

Campos desconhecidos são ignorados. Linhas sem sku, name ou preço são puladas e aparecem no painel (“linhas ignoradas: … sem preço”).

3. Moedas

  1. Se o produto tem o mapa prices, ele é a verdade e o campo price é ignorado (muitas lojas guardam price numa moeda interna).
  2. Na cotação, o atendente escolhe a moeda nesta ordem: a que o cliente pediu (se publicada) → a moeda do país do cliente, pelo número do WhatsApp (+55 → BRL, +351 → EUR, +47 → NOK, +1 → USD…) → a moeda padrão da empresa → a moeda base do produto. Ele sempre nomeia a moeda e nunca converte entre moedas.
  3. Números JSON com ponto decimal. Strings como "6,50" são toleradas, mas "1.500" é lido como mil e quinhentos.

4. Exemplo mínimo

[
  { "sku": "MUG-01", "name": "Caneca de cerâmica", "price": 35.9, "currency": "BRL" },
  { "sku": "MUG-02",
    "name": { "pt-BR": "Caneca esmaltada", "en-US": "Enamel mug" },
    "prices": { "BRL": 49.9, "EUR": 8.5 },
    "url": "https://loja.example.com/p/caneca-esmaltada" }
]

5. Exemplo completo (um produto)

{
  "sku": "cone",
  "slug": "petal-cone",
  "name": { "pt-BR": "Cones para Pétalas Secas", "en-US": "Dried Petal Cones" },
  "description": { "pt-BR": "Cones em papel vegetal para a chuva de pétalas…" },
  "category": "cone",
  "product_type": "physical",
  "unit": "un",
  "prices": { "BRL": 9.5, "EUR": 1.73, "USD": 2.0, "NOK": 18.99 },
  "price_tiers": [ { "min_qty": 100, "price": 8.9, "currency": "BRL" } ],
  "min_qty": 10,
  "in_stock": true,
  "lead_time_days": 7,
  "images": [ "https://cdn.example.com/products/cone/1.jpg" ],
  "url": "https://loja.example.com/pt-BR/shop/petal-cone",
  "country_exclusion": [],
  "is_active": true
}

6. O que o atendente faz com isso

  • Sincroniza a cada hora (configurável, mínimo 5 min) e sob demanda no painel. Linhas iguais não custam nada.
  • Busca sem acento por SKU, nomes em todos os idiomas, categoria e descrição; cota o preço exato por SKU e quantidade na moeda certa, com faixas de volume e o link do produto; informa estoque só se o feed publicar.
  • Todo número citado vem dessas ferramentas — respostas com preços que não batem com o catálogo são bloqueadas antes de chegar ao cliente. Produto fora do feed é “não vendemos”, nunca um chute.
  • Um feed fora do ar nunca afeta uma resposta: o atendente segue cotando pela última leitura boa e o painel mostra o erro.

7. Checklist para quem implementa

  • GET em https devolve 200 com application/json
  • Lista JSON, ou objeto com items (+ next quando paginado)
  • Todo produto tem sku único, name e prices ou price
  • Preços em números JSON; moedas em códigos ISO 4217
  • Produtos descontinuados são omitidos (não zerados)
  • ETag / Last-Modified servidos (recomendado)
  • url do produto (ou slug + modelo de link no painel)

Não tem loja online ou preços ao vivo? Sem problema: envie uma planilha ou mantenha a tabela de preços nos documentos do atendente. As três formas convivem.