Cadastro de produtos pela API

O Cadastro é o catálogo de produtos da sua conta na Wivo: cada produto de cada marketplace que você tenha integrado, com o seu custo e com os atributos internos que você lhe atribuiu.

Este endpoint permite lê-lo de forma programática. Para cada produto devolve os dois identificadores com os quais a Wivo o reconhece —ID Cuenta e ID Producto—, o seu custo atual e os seus atributos internos.

É a peça que torna o custeio automatizável. A Wivo também tem um endpoint para escrever custos, a carga de custos pela API, mas para escrever um custo é preciso saber a que produto ele corresponde. Lendo o Cadastro você obtém essa correspondência, e o ciclo completo —ler seu cadastro, cruzá-lo por SKU com o seu ERP e devolver os custos atualizados— roda sem que ninguém baixe uma planilha manualmente.

Está disponível para contas com plano Pro.

Para que serve?

  • Obter os identificadores com os quais a Wivo reconhece cada produto, que são os que você precisa para lhe atribuir um custo
  • Cruzar seus SKUs internos com os produtos de cada marketplace a partir do seu próprio sistema
  • Detectar quais produtos ainda não têm custo carregado
  • Manter sincronizados seus atributos internos (produto, SKU, marca, categoria e campos personalizados)

Requisitos

  • Conta Wivo com plano Pro
  • API Key ativa

Você não precisa do add-on da API de dados: este recurso está incluído no plano Pro.

Como obter sua API Key?

  1. Entrar na Wivo — Acesse sua conta com seu usuário administrador.
  2. Ir para Integrações — No menu do canto superior direito, clique em “Integração com API”.
  3. Solicitar habilitação — Clique em “Solicitar habilitar API” e agende uma reunião com a equipe da Wivo para ativar seu acesso.
  4. Obter sua chave — Uma vez habilitada, sua API Key será exibida. É pessoal, secreta e está associada à sua conta.

É a mesma chave para todos os recursos da API da Wivo.

Base URL

https://api.wivoanalytics.com

Autenticação

Todas as solicitações devem incluir a API Key no seguinte header HTTP:

Ocp-Apim-Subscription-Key: SUA_API_KEY_AQUI

Solicitações sem API Key ou com chave inválida recebem 401 Unauthorized.

Importante: Sua API Key é um segredo. Não a compartilhe, não a inclua em código-fonte público nem a exponha em logs. Armazene-a em variáveis de ambiente ou em um gerenciador de segredos.

GET /master/products

Devolve os produtos da sua conta, paginados.

Parâmetros

ParâmetroTipoObrigatórioDescrição
pageInteiroNãoPágina a devolver. Padrão 1
limitInteiroNãoProdutos por página. Padrão 100, máximo 1000
source_idUUIDNãoDevolve apenas os produtos de uma conta. É o valor da coluna ID Cuenta
withoutCosttrue / falseNãoCom true, devolve apenas os produtos que ainda não têm custo carregado

Exemplos de código

cURL:

# Primeira página do cadastro completo
curl "https://api.wivoanalytics.com/master/products?page=1&limit=1000" \
  -H "Ocp-Apim-Subscription-Key: SUA_API_KEY_AQUI"

# Apenas os produtos sem custo carregado
curl "https://api.wivoanalytics.com/master/products?withoutCost=true" \
  -H "Ocp-Apim-Subscription-Key: SUA_API_KEY_AQUI"

# Apenas os produtos de uma conta
curl "https://api.wivoanalytics.com/master/products?source_id=3f2b1c8e-9a4d-4c2f-b7e1-5d6a8c0f1234" \
  -H "Ocp-Apim-Subscription-Key: SUA_API_KEY_AQUI"

Python (requests):

import requests

url = "https://api.wivoanalytics.com/master/products"
headers = {"Ocp-Apim-Subscription-Key": "SUA_API_KEY_AQUI"}

produtos = []
pagina = 1

while True:
    response = requests.get(
        url, headers=headers, params={"page": pagina, "limit": 1000}
    )
    response.raise_for_status()
    corpo = response.json()

    produtos.extend(corpo["data"])
    if pagina >= corpo["meta"]["totalPages"]:
        break
    pagina += 1

print(f"{len(produtos)} produtos no cadastro")

Node.js (fetch):

const headers = { "Ocp-Apim-Subscription-Key": "SUA_API_KEY_AQUI" };

const produtos = [];
let pagina = 1;
let totalPaginas = 1;

do {
  const response = await fetch(
    `https://api.wivoanalytics.com/master/products?page=${pagina}&limit=1000`,
    { headers }
  );
  const corpo = await response.json();

  produtos.push(...corpo.data);
  totalPaginas = corpo.meta.totalPages;
  pagina += 1;
} while (pagina <= totalPaginas);

console.log(`${produtos.length} produtos no cadastro`);

Resposta bem-sucedida — 200 OK

{
  "data": [
    {
      "Marketplace": "Mercado Livre",
      "Cuenta": "Minha Loja",
      "ID Cuenta": "3f2b1c8e-9a4d-4c2f-b7e1-5d6a8c0f1234",
      "ID Producto": "MLB1234567890",
      "SKU Producto": "SKU-001",
      "Nombre Producto": "Camiseta Básica",
      "Costo de producto (con IVA)": 1500.5,
      "Producto Interno": "Camiseta Genérica",
      "SKU Producto Interno": "INT-001",
      "Marca Interna": "Nike",
      "Categoría Interna": "Roupas"
    }
  ],
  "meta": {
    "page": 1,
    "pageSize": 100,
    "count": 1,
    "totalRows": 1,
    "totalPages": 1
  },
  "correlation_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Os nomes dos campos estão em espanhol porque são idênticos às colunas da planilha de custos, a mesma que você pode baixar da plataforma e a que a carga pela API aceita. Isso é intencional: você pode converter esta resposta em CSV e enviá-la tal como está, sem renomear nada.

Campos da resposta

CampoDescrição
MarketplaceCanal ao qual o produto pertence
CuentaNome da conta nesse canal
ID CuentaIdentificador da conta na Wivo (UUID). Chave para a carga de custos
ID ProductoIdentificador do produto no marketplace. Chave para a carga de custos
SKU ProductoSKU do produto no marketplace
Nombre ProductoNome do produto no marketplace
Costo de producto (con IVA)Custo atual. null se o produto ainda não tem custo carregado
Producto InternoNome interno que você atribuiu ao produto
SKU Producto InternoSeu SKU interno
Marca InternaMarca interna que você atribuiu
Categoría InternaCategoria interna que você atribuiu

Se você configurou campos personalizados na plataforma, eles aparecem ao final de cada produto com o nome que você deu a eles. Por exemplo, um campo chamado “Subcategoria” é devolvido como "Subcategoria": "Camisetas".

Metadados de paginação

CampoDescrição
pagePágina devolvida
pageSizeProdutos por página
countProdutos nesta página
totalRowsTotal de produtos que atendem ao filtro
totalPagesTotal de páginas

A ordem é estável entre chamadas, então você pode paginar sem risco de repetir ou omitir produtos.

Respostas do servidor

CódigoSignificadoRepetir
200Consulta bem-sucedidaNão
400Parâmetro inválidoNão
401API Key ausente ou inválidaNão
403Plano Pro necessário, ou assinatura revogadaNão
429Limite de solicitações excedidoSim
500Erro internoSim

400 Bad Request:

{
  "error": "Parámetro 'source_id' inválido: debe ser el UUID de una cuenta (columna 'ID Cuenta' del Maestro).",
  "correlation_id": "a1b2c3d4-..."
}

403 Forbidden:

{
  "error": "El Maestro de productos está disponible en el plan Pro. Contacta a tu ejecutivo de Wivo para activarlo.",
  "correlation_id": "a1b2c3d4-..."
}

Limites de uso

  • 30 requisições por minuto por conta
  • 5.000 requisições por dia
  • Exceder os limites retorna HTTP 429 Too Many Requests

Com páginas de 1.000 produtos, um catálogo de 20.000 produtos é lido em menos de um minuto. Implemente novas tentativas com backoff exponencial diante de um 429.

Receitas

Automatizar a carga de custos de ponta a ponta

Este é o fluxo completo: ler o cadastro, cruzá-lo com o seu ERP e devolver os custos. A última etapa usa POST /costs/fill/csv, cujos parâmetros e respostas estão detalhados em carga de custos pela API.

import csv
import io
import requests

BASE = "https://api.wivoanalytics.com"
headers = {"Ocp-Apim-Subscription-Key": "SUA_API_KEY_AQUI"}

# 1. Ler o cadastro
produtos = []
pagina = 1
while True:
    corpo = requests.get(
        f"{BASE}/master/products",
        headers=headers,
        params={"page": pagina, "limit": 1000},
    ).json()
    produtos.extend(corpo["data"])
    if pagina >= corpo["meta"]["totalPages"]:
        break
    pagina += 1

# 2. Cruzar pelo seu SKU com o custo do seu ERP
custos_erp = {"SKU-001": 1800.0, "SKU-002": 3500.0}  # o que o seu sistema devolver

for produto in produtos:
    novo_custo = custos_erp.get(produto["SKU Producto"])
    if novo_custo is not None:
        produto["Costo de producto (con IVA)"] = novo_custo

# 3. Converter para CSV sem renomear nada
buffer = io.StringIO()
writer = csv.DictWriter(buffer, fieldnames=list(produtos[0].keys()))
writer.writeheader()
writer.writerows(produtos)

# 4. Enviar a carga
resposta = requests.post(
    f"{BASE}/costs/fill/csv",
    headers=headers,
    files={"file": ("custos.csv", buffer.getvalue().encode("utf-8"), "text/csv")},
    data={
        "email": "usuario@minhaempresa.com",
        "username": "Pipeline de Custos",
        "fromDate": "2025-01-01",
    },
)
print(resposta.json())  # {"processId": "..."}

fromDate define a partir de quando os custos são aplicados ao seu histórico. Se você o omitir, aplicam-se desde o primeiro dia do mês de dois anos atrás. Envie-o se o seu custo é ponderado e muda com frequência.

Saber quantos produtos faltam custear

Uma única requisição, sem baixar o catálogo: peça uma página de um produto e leia o total.

curl "https://api.wivoanalytics.com/master/products?withoutCost=true&limit=1" \
  -H "Ocp-Apim-Subscription-Key: SUA_API_KEY_AQUI"

O campo meta.totalRows da resposta é a quantidade de produtos sem custo carregado.

Custear apenas o que é novo

Se o seu catálogo já está custeado e você só quer cobrir os produtos que entraram depois, pagine com withoutCost=true em vez de ler o cadastro completo.

Perguntas frequentes

Por que devo usar o ID Producto que a API entrega e não o do meu sistema? Porque a carga de custos procura cada produto pela combinação de ID Cuenta e ID Producto. Se você enviar um identificador que não existe na Wivo, a carga não falha: cria um produto novo que não corresponde a nenhum anúncio real e polui o seu catálogo. Partir do cadastro evita esse problema.

Posso carregar custos usando o meu SKU interno como identificador? Não diretamente. O cruzamento por SKU você faz do seu lado: lê o cadastro, procura o seu SKU na coluna SKU Producto (ou em SKU Producto Interno, se você o carregou antes) e escreve o custo na linha correspondente, que já traz os identificadores corretos.

O que acontece se um produto não tem custo? O campo Costo de producto (con IVA) vem como null. Ao converter para CSV fica como célula vazia, que a carga interpreta como “sem custo”.

Os produtos sem vendas aparecem? Sim. O cadastro é o seu catálogo completo, não apenas o que foi vendido em um período.

Com que frequência é atualizado? As mudanças de custo e de atributos internos se refletem em poucos minutos. Um produto recém-criado no marketplace pode levar até 30 minutos para aparecer.

Este recurso consome a minha cota da API de dados? Não. Tem o seu próprio limite de 30 requisições por minuto, independente do de GET /data.