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/jsonem 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 umnextopcional 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
ETage/ouLast-Modified. A sincronização usaIf-None-Match/If-Modified-Since; um304nã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) | texto | Seu identificador estável. Único no feed. |
| name (title) | texto ou mapa por idioma | Nome de exibição. |
| prices ou price | ver seção 3 | Pelo 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. |
| currency | texto | Moeda de price quando não há prices (padrão: a moeda da empresa). |
| price | número | Preço base, usado só quando não há prices. |
| slug (handle) | texto | Identificador de URL; permite montar o link do produto. |
| url (link) | texto | Página do produto. O atendente compartilha para o cliente ver fotos e comprar. |
| description | texto ou mapa | Pesquisável (primeiros ~500 caracteres por idioma). |
| category | texto ou mapa | Alimenta a resposta a “o que vocês vendem?”. |
| product_type | texto | physical, digital, service… |
| images | lista de URLs | A primeira vira a imagem do produto. |
| is_active (active) | booleano | false esconde o produto (padrão true). |
| offer_only / hidden | booleano | true esconde do catálogo público. |
Opcionais
| unit | texto | Unidade de venda (padrão un). |
| min_qty (min_quantity) | inteiro | Quantidade 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) | booleano | Disponibilidade. Ausente = o atendente não promete estoque. |
| stock (stock_qty) | inteiro | Unidades disponíveis; implica in_stock. |
| lead_time_days | inteiro | Prazo de produção/despacho. |
| country_exclusion | ["BR", "US"] | Países (ISO 3166-1) onde o produto NÃO é vendido. |
| features, brand, options… | qualquer JSON | Guardados 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
- Se o produto tem o mapa
prices, ele é a verdade e o campopriceé ignorado (muitas lojas guardampricenuma moeda interna). - 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.
- 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.