API

Continente API: preços, promoções e rótulos do continente.pt em JSON

Com esta API, recebe em JSON aquilo que o continente.pt mostra a quem compra sem iniciar sessão: o preço de cada artigo, o preço riscado quando há desconto imediato, o PVPR do fabricante quando a loja o indica, o preço por kg ou por litro, a embalagem e, na ficha, os EAN e o rótulo completo (ingredientes, alergénios, origem, tabela nutricional). O sortido depende da loja que entrega na sua morada: com `postal_code` a pesquisa passa a mostrar a gama dessa loja, e a resposta diz qual é. Não é um canal para fornecedores nem para marcas que vendem ao Continente: não envia catálogos nem encomendas, apenas lê a loja online do lado do cliente.

Endpoints

endpointO que retornaObrigatórios
searchPesquisa como na caixa do site (em português dá melhores resultados): até 35 artigos por página, cada um com preço e a unidade a que se refere (`un`, `kg`, `lt`), preço riscado, PVPR, desconto, promoção por quantidade (`multibuy`), preço por kg/l, embalagem, marca e disponibilidade. Filtros por categoria, marca, dieta (biológico, vegan, sem glúten, sem lactose…) e intervalo de preço; seis ordenações.query
categoryUma categoria inteira pelo seu id (por exemplo `laticinios-leite`), com as mesmas colunas, filtros e paginação da pesquisa.todos opcionais
promotionsOs artigos que estão neste momento com desconto (o filtro «Com Desconto» do site): preço da promoção, preço anterior, percentagem ou valor do desconto e promoções por quantidade com as condições do site. Pode restringir por palavra, categoria, marca ou dieta.todos opcionais
productA ficha de um artigo pelo id que a pesquisa devolve: preços, janela de validade da promoção, EAN, quantidade máxima por encomenda, caminho de categorias, imagens e o rótulo (denominação legal, produtor, ingredientes, alergénios, conservação, origem, conteúdo líquido e tabela nutricional).product_id
categoriesA árvore de categorias do menu da loja: id, nome, endereço e subcategorias. Os ids servem para `category` e para o filtro de categoria.todos opcionais
storeQue loja Continente entrega num código postal português (formato NNNN-NNN): nome e id da loja, ou `covered: false` quando não há entrega.postal_code

Cada chamada é cobrada em créditos. Chamadas com erro ou bloqueadas são gratuitas.

Exemplo que funciona

Pesquisa «bacalhau» de 28 de outubro de 2026, loja por defeito: 137 artigos. Há três tipos de preço de referência e não são a mesma coisa. Nas Postas Médias Continente, `regular_price` 8,99 € é o preço antes do desconto imediato de 16 %. No desfiado Riberalves, os 13,99 € estão em `recommended_retail_price`: é o PVPR do fabricante, não um preço a que o Continente o tenha vendido, e por isso `on_offer` vem false. Nas ovas Frip, `price` é por kg (23,30 €/kg) e o valor por unidade fica em `unit_price`. Das 20 linhas, 7 traziam PVPR e 3 desconto imediato. A ficha do desfiado Riberalves acrescenta o que o nome não diz: ingredientes «Bacalhau-do-Pacífico e sal», origem Oceano Pacífico Nordeste.

Requisição
curl -X POST https://api.reefapi.com/continente/v1/search \
  -H "x-api-key: A_SUA_CHAVE" \
  -H "content-type: application/json" \
  -d '{"query": "bacalhau", "per_page": 20}'
Resposta (resumida)
{
  "ok": true,
  "data": {
    "store": { "postal_code": null, "store_name": null, "store_id": null, "resolved_from": "site default for an anonymous visitor ..." },
    "query": "bacalhau",
    "sort": "relevance",
    "total": 137,
    "page": 1,
    "per_page": 20,
    "has_more": true,
    "results": [
      {
        "rank": 2,
        "product_id": "5734372",
        "name": "Bacalhau Desfiado 9 Meses de Cura MSC Congelado Riberalves",
        "brand": "Riberalves",
        "price": 8.39,
        "price_unit": "un",
        "regular_price": null,
        "recommended_retail_price": 13.99,
        "currency": "EUR",
        "discount": null,
        "on_offer": false,
        "unit_price": 20.98,
        "unit_price_unit": "kg",
        "pack_size": "emb. 400 gr",
        "category_path": "Supermercado/Peixaria/Bacalhau Congelado/Desfiado"
      },
      {
        "rank": 7,
        "product_id": "7291115",
        "name": "Postas Médias de Bacalhau MSC Demolhado Ultracongelado Continente",
        "price": 7.49,
        "price_unit": "un",
        "regular_price": 8.99,
        "recommended_retail_price": null,
        "discount": { "kind": "immediate_discount", "text": "Desconto Imediato: 16%", "value": 16.0, "unit": "%" },
        "on_offer": true,
        "unit_price": 12.48,
        "unit_price_unit": "kg",
        "pack_size": "emb. 600 gr"
      },
      {
        "rank": 20,
        "product_id": "7799798",
        "name": "Ovas de Bacalhau Higienizadas Congeladas Frip",
        "price": 23.3,
        "price_unit": "kg",
        "regular_price": 24.59,
        "unit_price": 9.32,
        "unit_price_unit": "un",
        "pack_size": "Quant. Mínima = 400 gr"
      },
      ...
    ]
  },
  "meta": { "record_count": 20, "total": 137, "charged_credits": 3, "cache_hit": false, "mode": "live" }
}

Scraper do continente.pt: onde o preço engana

No HTML do continente.pt, o preço riscado tem um atributo `content` que guarda o preço da promoção, não o preço riscado: num artigo a 1,79 €, o texto dizia «1,99€» e o atributo «1.79». Quem lê o atributo grava duas vezes o preço de promoção e perde o desconto. E o mesmo lugar no cartão do artigo serve tanto para o preço antes do desconto como para o PVPR do fabricante; a camada de dados do site dá aos dois o mesmo nome. Aqui saem em dois campos.

O preço impresso também se parte em pedaços: «5» num elemento e «,34€» noutro. Durante a construção do motor, uma versão que trocava as etiquetas por espaços leu 5,0 em vez de 5,34; o teste com a página guardada apanhou-o antes da primeira chamada real.

Há ainda os silêncios. Uma categoria com um id que o site não conhece não dá erro: o continente.pt mostra o catálogo inteiro (66 004 artigos na medição). Um artigo indisponível traz preço 0 na camada de dados, embora a página continue a imprimir o preço. Aqui a categoria desconhecida é recusada e o artigo indisponível mantém o preço impresso com `available: false`.

Nada disto interrompe um script. Quem regista todas as semanas o preço do bacalhau até à Consoada só dá por eles mais tarde, na folha de cálculo: descontos que nunca existiram, artigos esgotados a 0 € e uma categoria que, em vez de umas dezenas de linhas, traz 66 mil.

Limites e observações honestas

  • API independente: não foi criada nem é apoiada pelo Continente, e a ReefAPI não tem com a marca nenhum contrato ou parceria.
  • Os descontos do Cartão Continente não aparecem: só se veem com sessão iniciada. O `price` é o preço para quem compra sem cartão.
  • O sortido muda com a loja que entrega no código postal: «bacalhau» deu 137 artigos na loja por defeito, 138 em Gaia (4000-322) e 61 no Funchal (9000-018). Os preços dos artigos em comum não mudaram; na construção do motor foram 335 pares artigo×loja, sem nenhuma diferença.
  • A ordenação `unit_price_asc` compara o número sem olhar à unidade: nas primeiras linhas de «bacalhau» misturavam-se 3,48 €/un (postas vendidas ao kg) e 3,90 €/kg (comida húmida para gato). Para comparar preço por kg, filtre `unit_price_unit` antes de ordenar.
  • A pesquisa por palavra é larga: em «bacalhau» vieram também comida húmida para gato e um suplemento de óleo de fígado de bacalhau. Para ficar na peixaria, use `category` com o id que a ficha devolve (por exemplo `peixaria-e-talho-peixaria-bacalhau-congelado-desfiado`); repare que o próprio Continente arruma aí também o paloco do Pacífico desfiado.
  • No mesmo artigo, `max_order_quantity` veio 99 na pesquisa e 10 no `product`; não verificámos qual dos dois o carrinho aplica.
  • O site não publica quantidades em stock, custos de entrega nem horários disponíveis; só `available` e os limites por encomenda.
  • Créditos: 3 por chamada em `search`, `category`, `promotions`, `product` e `categories`; 1 em `store`.