Mapa de Ofertas

API pública — documentação técnica

Integre seu ERP ou loja virtual ao Mapa de Ofertas: cadastro e atualização de produtos, marcas, categorias e sincronização de estoque em tempo real.

Introdução

A API é REST sobre HTTPS com corpos JSON (criação de produto também aceita multipart/form-data para envio direto de imagem). Todas as rotas ficam sob /api/v1 e operam exclusivamente sobre o catálogo da empresa dona da chave — nunca é possível ler ou alterar dados de outra empresa.

As chaves de API são geradas no painel da empresa em Configurações → Chaves de API (requer assinatura ativa).

Autenticação

Toda requisição deve enviar a chave no header Authorization (ou, alternativamente, em X-Api-Key):

Authorization: Bearer mo_live_XXXXXXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
  • A chave completa é exibida uma única vez na criação — armazenamos apenas um hash.
  • Chaves podem ser revogadas individualmente no painel; a revogação é imediata.
  • Se a assinatura da empresa expirar, a API responde 403 subscription_inactive — a mesma chave volta a funcionar quando o pagamento é regularizado.

Formato de erros

Erros sempre retornam o envelope:

{"error": {"code": "conflict", "message": "já existe um produto com este SKU na sua empresa"}}
HTTPcodeQuando ocorre
400invalid_argumentCorpo/parâmetros inválidos (JSON malformado, image_url inacessível, campo obrigatório ausente)
401unauthorizedChave de API ausente, inválida ou revogada
403subscription_inactiveAssinatura da empresa não está ativa — a chave volta a funcionar ao regularizar o pagamento
404not_foundRecurso não encontrado (ou não pertence à sua empresa)
409conflictConflito — ex.: SKU duplicado na empresa
422plan_limit_reachedRegra de plano — ex.: limite de produtos atingido
429rate_limitedMuitas requisições — aguarde e tente novamente
500internalErro interno — tente novamente mais tarde

Rate limits

  • ~120 requisições/minuto por chave de API (todas as rotas).
  • Criações de produto com download de image_url têm um limite adicional mais restrito (~30/min).
  • Ao exceder, a resposta é 429 rate_limited — aguarde e repita com backoff.

Criar produto

POST/api/v1/products

Cria um produto no catálogo da sua empresa. Aceita JSON (com image_url para o servidor baixar a imagem) ou multipart/form-data (com o arquivo no campo "image" — o arquivo tem prioridade sobre image_url). Marca e categoria podem ser informadas por nome (brand/category — criadas automaticamente se não existirem) ou por id (brand_id/category_id). Adoção do catálogo pré-cadastrado ("Adiciona fácil"): informe shared_product_id (obtido em GET /shared-products) ou apenas o gtin (código de barras) — nome, descrição, foto, marca e categoria são herdados e você só precisa enviar o seu preço (e SKU, se quiser).

CampoTipoObrigatórioDescrição
namestringsim*Nome do produto (*opcional na adoção via shared_product_id/gtin — é herdado)
pricenumbersimPreço em reais (> 0)
shared_product_iduuidnãoAdota um produto do catálogo pré-cadastrado — campos descritivos são herdados
gtinstringnãoCódigo de barras (EAN-8/UPC-A/EAN-13/GTIN-14). Se já existir no catálogo pré-cadastrado, adota a entrada; senão registra o código na entrada nova
descriptionstringnãoDescrição curta
skustringnãoCódigo interno/ERP — único por empresa (máx. 64)
in_stockbooleannãoVisibilidade na vitrine (padrão true)
sale_unitstringnãoUnidade de venda: unidade (padrão), caixa, pacote, fardo, engradado, palete, kit, combo, dúzia, saco, bandeja ou galão
wholesale_pricenumbernãoPreço de atacado em reais (> 0 e menor que price). Deve vir junto de wholesale_min_qty
wholesale_min_qtynumbernãoQuantidade mínima para valer o preço de atacado (mínimo 2). Deve vir junto de wholesale_price
brandstringnãoMarca por nome (cria se não existir)
categorystringnãoCategoria por nome (cria se não existir)
brand_id / category_iduuidnãoIds existentes (têm prioridade sobre o nome)
image_urlstringnãoURL http(s) pública da imagem — baixada e convertida para WebP
imagearquivonãoSomente multipart: JPG, PNG ou WEBP até 10 MB
  • 201 — Produto criado — retorna {"id": "...", "message": "produto criado"}
  • 409 — SKU duplicado na sua empresa
  • 422 — Sem plano ativo ou limite de produtos do plano atingido
# JSON com image_url
curl -X POST https://SEU-DOMINIO.com/api/v1/products \
  -H "Authorization: Bearer SUA_CHAVE_API" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Café Torrado 500g",
    "description": "Café torrado e moído",
    "price": 19.90,
    "sale_unit": "unidade",
    "wholesale_price": 17.90,
    "wholesale_min_qty": 6,
    "sku": "CAF-500",
    "brand": "Pilão",
    "category": "Mercearia",
    "image_url": "https://exemplo.com/cafe.jpg"
  }'

# multipart com arquivo local
curl -X POST https://SEU-DOMINIO.com/api/v1/products \
  -H "Authorization: Bearer SUA_CHAVE_API" \
  -F "name=Arroz Tipo 1 5kg" \
  -F "price=25.50" \
  -F "sku=ARZ-5KG" \
  -F "category=Mercearia" \
  -F "image=@/caminho/arroz.jpg"

Catálogo pré-cadastrado

GET/api/v1/shared-products

Navegue no catálogo global de produtos pré-cadastrados (o "Adiciona fácil" do painel): produtos criados e pré-cadastrados que você pode adotar informando só o seu preço e SKU. Busque por nome/marca ou encontre a entrada exata pelo código de barras (?gtin=) — o caminho recomendado para integrações de ERP: para cada item do seu estoque, consulte o GTIN; se existir, adote via shared_product_id no POST /products; se não, crie o produto completo com o campo gtin preenchido.

CampoTipoObrigatórioDescrição
searchquerynãoBusca parcial por nome ou marca
gtinquerynãoCódigo de barras exato (EAN-8/UPC-A/EAN-13/GTIN-14)
limitquerynãoMáx. de itens (padrão 50, máx. 100)
offsetquerynãoDeslocamento da paginação
  • 200 — {"shared_products": [{id, name, description, image_url, brand, category, gtin}], "has_more": bool}
  • 400 — GTIN inválido (dígito verificador incorreto)
# busca por nome
curl "https://SEU-DOMINIO.com/api/v1/shared-products?search=cafe&limit=20" \
  -H "Authorization: Bearer SUA_CHAVE_API"

# busca exata por código de barras
curl "https://SEU-DOMINIO.com/api/v1/shared-products?gtin=7896089012347" \
  -H "Authorization: Bearer SUA_CHAVE_API"

Sincronizar por SKU (upsert)

PUT/api/v1/products/by-sku/{sku}

Criação ou atualização idempotente pelo SKU — feito para sincronização recorrente de ERP: pode reenviar o estoque inteiro toda noite com segurança. SKU novo: cria o produto (mesmos campos do create, incluindo adoção via shared_product_id/gtin). SKU existente: atualiza somente os campos enviados (price, in_stock, name, description, image_url, sale_unit, wholesale_price, wholesale_min_qty).

CampoTipoObrigatórioDescrição
skupathsimSKU do produto na sua empresa (máx. 64)
pricenumberna criaçãoPreço em reais (> 0); na atualização, envie para alterar
wholesale_price / wholesale_min_qtynumbernãoPreço de atacado + quantidade mínima (sempre juntos). Na atualização: omitir mantém, enviar 0 em qualquer um remove o atacado
demais campos—nãoIguais ao POST /products (name, gtin, shared_product_id, in_stock, sale_unit, ...)
  • 201 — Produto criado (SKU não existia)
  • 200 — Produto atualizado
  • 422 — Sem plano ativo ou limite de produtos atingido (só na criação)
curl -X PUT https://SEU-DOMINIO.com/api/v1/products/by-sku/CAF-500 \
  -H "Authorization: Bearer SUA_CHAVE_API" \
  -H "Content-Type: application/json" \
  -d '{"gtin": "7896089012347", "price": 18.90, "in_stock": true, "wholesale_price": 16.90, "wholesale_min_qty": 6}'

Listar produtos

GET/api/v1/products

Lista apenas os produtos da empresa dona da chave, incluindo os ocultos (in_stock=false). Suporta paginação e filtros. Cada item traz também sale_unit, wholesale_price e wholesale_min_qty (null quando o produto não tem preço de atacado).

CampoTipoObrigatórioDescrição
limitquerynãoMáx. de itens (padrão 30, máx. 100)
offsetquerynãoDeslocamento da paginação
searchquerynãoBusca por nome ou SKU (parcial)
skuquerynãoSKU exato
  • 200 — {"products": [...], "has_more": bool}
curl "https://SEU-DOMINIO.com/api/v1/products?limit=50&search=cafe" \
  -H "Authorization: Bearer SUA_CHAVE_API"

Atualizar produto

PATCH/api/v1/products/{id}

Atualização parcial: envie apenas os campos que deseja alterar — os demais são mantidos. Mesmos campos do create (exceto brand/category por nome; use brand_id/category_id). Atacado: envie wholesale_price e wholesale_min_qty juntos para definir; envie 0 em qualquer um deles para remover; omita ambos para manter.

CampoTipoObrigatórioDescrição
sale_unitstringnãoUnidade de venda (unidade, caixa, pacote, fardo, engradado, palete, kit, combo, dúzia, saco, bandeja, galão)
wholesale_pricenumbernãoPreço de atacado (> 0 e menor que price). Enviar 0 remove o atacado
wholesale_min_qtynumbernãoQuantidade mínima do atacado (mínimo 2). Enviar 0 remove o atacado
  • 200 — Produto atualizado
  • 404 — Produto não encontrado (ou não pertence à sua empresa)
  • 409 — SKU duplicado
curl -X PATCH https://SEU-DOMINIO.com/api/v1/products/ID_DO_PRODUTO \
  -H "Authorization: Bearer SUA_CHAVE_API" \
  -H "Content-Type: application/json" \
  -d '{"price": 18.50, "in_stock": true}'

# definir preço de atacado (sempre o par junto)
curl -X PATCH https://SEU-DOMINIO.com/api/v1/products/ID_DO_PRODUTO \
  -H "Authorization: Bearer SUA_CHAVE_API" \
  -H "Content-Type: application/json" \
  -d '{"wholesale_price": 16.90, "wholesale_min_qty": 6}'

# remover o preço de atacado
curl -X PATCH https://SEU-DOMINIO.com/api/v1/products/ID_DO_PRODUTO \
  -H "Authorization: Bearer SUA_CHAVE_API" \
  -H "Content-Type: application/json" \
  -d '{"wholesale_price": 0}'

Criar marca

POST/api/v1/brands

Cria uma marca na sua empresa. Nomes são únicos sem diferenciar maiúsculas: se já existir, a marca existente é reaproveitada (resposta 200 com "reused": true).

CampoTipoObrigatórioDescrição
namestringsimNome da marca
  • 201 — Marca criada
  • 200 — Marca já existente reaproveitada ("reused": true)
curl -X POST https://SEU-DOMINIO.com/api/v1/brands \
  -H "Authorization: Bearer SUA_CHAVE_API" \
  -H "Content-Type: application/json" \
  -d '{"name": "Pilão"}'

Criar categoria

POST/api/v1/categories

Cria uma categoria na sua empresa (reaproveita se o nome já existir). O campo icon é opcional.

CampoTipoObrigatórioDescrição
namestringsimNome da categoria
iconstringnãoIdentificador de ícone exibido na vitrine
  • 201 — Categoria criada
  • 200 — Categoria já existente reaproveitada
curl -X POST https://SEU-DOMINIO.com/api/v1/categories \
  -H "Authorization: Bearer SUA_CHAVE_API" \
  -H "Content-Type: application/json" \
  -d '{"name": "Mercearia"}'

Webhook de estoque

POST/api/v1/webhooks/stock

Endpoint dedicado para o seu ERP sincronizar disponibilidade: altera SOMENTE o campo in_stock do produto, identificado por sku ou product_id. Com in_stock=false o produto some da vitrine, das buscas e do mapa imediatamente; com true ele volta.

CampoTipoObrigatórioDescrição
skustringum dos doisSKU do produto na sua empresa
product_iduuidum dos doisId do produto
in_stockbooleansimtrue = visível, false = oculto
  • 200 — Estoque atualizado
  • 404 — Produto não encontrado
curl -X POST https://SEU-DOMINIO.com/api/v1/webhooks/stock \
  -H "Authorization: Bearer SUA_CHAVE_API" \
  -H "Content-Type: application/json" \
  -d '{"sku": "CAF-500", "in_stock": false}'