Maestro de productos por API

El Maestro es el catálogo de productos de tu cuenta en Wivo: cada producto de cada marketplace que tengas integrado, con su costo y con los atributos internos que le hayas asignado.

Este endpoint te permite leerlo de forma programática. Para cada producto devuelve los dos identificadores con los que Wivo lo reconoce —ID Cuenta e ID Producto—, su costo actual y tus atributos internos.

Es la pieza que hace automatizable el costeo. Wivo también tiene un endpoint para escribir costos, la carga de costos por API, pero para escribir un costo hay que saber a qué producto corresponde. Leyendo el Maestro obtienes esa correspondencia, y el ciclo completo —leer tu maestro, cruzarlo por SKU contra tu ERP y devolver los costos actualizados— corre sin que nadie descargue una planilla a mano.

Está disponible para cuentas con plan Pro.

¿Para qué sirve?

  • Obtener los identificadores con los que Wivo reconoce cada producto, que son los que necesitas para asignarle un costo
  • Cruzar tus SKU internos con los productos de cada marketplace desde tu propio sistema
  • Detectar qué productos aún no tienen costo cargado
  • Mantener sincronizados tus atributos internos (producto, SKU, marca, categoría y campos personalizados)

Requisitos

  • Cuenta Wivo con plan Pro
  • API Key activa

No necesitas el add-on de la API de datos: este recurso viene incluido en el plan Pro.

¿Cómo obtener tu API Key?

  1. Ingresar a Wivo — Accede a tu cuenta con tu usuario administrador.
  2. Ir a Integraciones — En el menú de la esquina superior derecha, haz clic en “Integración con API”.
  3. Solicitar habilitación — Haz clic en “Solicitar habilitar API” y agenda una reunión con el equipo de Wivo para activar tu acceso.
  4. Obtener tu clave — Una vez habilitada, se mostrará tu API Key. Es personal, secreta y está asociada a tu cuenta.

Es la misma clave para todos los recursos de la API de Wivo.

Base URL

https://api.wivoanalytics.com

Autenticación

Todas las solicitudes deben incluir la API Key en el siguiente header HTTP:

Ocp-Apim-Subscription-Key: TU_API_KEY_AQUI

Solicitudes sin API Key o con clave inválida reciben 401 Unauthorized.

Importante: Tu API Key es un secreto. No la compartas, no la incluyas en código fuente público ni la expongas en logs. Almacénala en variables de entorno o en un gestor de secretos.

GET /master/products

Devuelve los productos de tu cuenta, paginados.

Parámetros

ParámetroTipoObligatorioDescripción
pageEnteroNoPágina a devolver. Default 1
limitEnteroNoProductos por página. Default 100, máximo 1000
source_idUUIDNoDevuelve solo los productos de una cuenta. Es el valor de la columna ID Cuenta
withoutCosttrue / falseNoCon true, devuelve solo los productos que aún no tienen costo cargado

Ejemplos de código

cURL:

# Primera página del maestro completo
curl "https://api.wivoanalytics.com/master/products?page=1&limit=1000" \
  -H "Ocp-Apim-Subscription-Key: TU_API_KEY_AQUI"

# Solo los productos sin costo cargado
curl "https://api.wivoanalytics.com/master/products?withoutCost=true" \
  -H "Ocp-Apim-Subscription-Key: TU_API_KEY_AQUI"

# Solo los productos de una cuenta
curl "https://api.wivoanalytics.com/master/products?source_id=3f2b1c8e-9a4d-4c2f-b7e1-5d6a8c0f1234" \
  -H "Ocp-Apim-Subscription-Key: TU_API_KEY_AQUI"

Python (requests):

import requests

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

productos = []
pagina = 1

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

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

print(f"{len(productos)} productos en el maestro")

Node.js (fetch):

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

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

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

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

console.log(`${productos.length} productos en el maestro`);

Respuesta exitosa — 200 OK

{
  "data": [
    {
      "Marketplace": "Mercado Libre",
      "Cuenta": "Mi Tienda",
      "ID Cuenta": "3f2b1c8e-9a4d-4c2f-b7e1-5d6a8c0f1234",
      "ID Producto": "MLC1234567890",
      "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": "Ropa"
    }
  ],
  "meta": {
    "page": 1,
    "pageSize": 100,
    "count": 1,
    "totalRows": 1,
    "totalPages": 1
  },
  "correlation_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Campos de la respuesta

CampoDescripción
MarketplaceCanal al que pertenece el producto
CuentaNombre de la cuenta en ese canal
ID CuentaIdentificador de la cuenta en Wivo (UUID). Clave para la carga de costos
ID ProductoIdentificador del producto en el marketplace. Clave para la carga de costos
SKU ProductoSKU del producto en el marketplace
Nombre ProductoNombre del producto en el marketplace
Costo de producto (con IVA)Costo actual. null si el producto aún no tiene costo cargado
Producto InternoNombre interno que asignaste al producto
SKU Producto InternoTu SKU interno
Marca InternaMarca interna que asignaste
Categoría InternaCategoría interna que asignaste

Si configuraste campos personalizados en la plataforma, aparecen al final de cada producto con el nombre que tú les diste. Por ejemplo, un campo llamado “Subcategoría” se devuelve como "Subcategoría": "Poleras".

Los nombres de los campos son idénticos a las columnas de la planilla de costos, la misma que puedes descargar desde la plataforma y la que acepta la carga por API. Es intencional: puedes convertir esta respuesta a CSV y enviarla tal cual, sin renombrar nada.

Metadatos de paginación

CampoDescripción
pagePágina devuelta
pageSizeProductos por página
countProductos en esta página
totalRowsTotal de productos que cumplen el filtro
totalPagesTotal de páginas

El orden es estable entre llamadas, así que puedes paginar sin riesgo de repetir u omitir productos.

Respuestas del servidor

CódigoSignificadoReintentar
200Consulta exitosaNo
400Parámetro inválidoNo
401API Key ausente o inválidaNo
403Plan Pro requerido, o suscripción revocadaNo
429Límite de solicitudes excedido
500Error interno

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-..."
}

Límites de uso

  • 30 peticiones por minuto por cuenta
  • 5.000 peticiones por día
  • Superar los límites retorna HTTP 429 Too Many Requests

Con páginas de 1.000 productos, un catálogo de 20.000 productos se lee en menos de un minuto. Implementa reintentos con backoff exponencial ante un 429.

Recetas

Automatizar la carga de costos de punta a punta

Este es el flujo completo: leer el maestro, cruzarlo con tu ERP y devolver los costos. El último paso usa POST /costs/fill/csv, cuyos parámetros y respuestas están detallados en carga de costos por API.

import csv
import io
import requests

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

# 1. Leer el maestro
productos = []
pagina = 1
while True:
    cuerpo = requests.get(
        f"{BASE}/master/products",
        headers=headers,
        params={"page": pagina, "limit": 1000},
    ).json()
    productos.extend(cuerpo["data"])
    if pagina >= cuerpo["meta"]["totalPages"]:
        break
    pagina += 1

# 2. Cruzar por tu SKU contra el costo de tu ERP
costos_erp = {"SKU-001": 1800.0, "SKU-002": 3500.0}  # lo que devuelva tu sistema

for producto in productos:
    nuevo_costo = costos_erp.get(producto["SKU Producto"])
    if nuevo_costo is not None:
        producto["Costo de producto (con IVA)"] = nuevo_costo

# 3. Convertir a CSV sin renombrar nada
buffer = io.StringIO()
writer = csv.DictWriter(buffer, fieldnames=list(productos[0].keys()))
writer.writeheader()
writer.writerows(productos)

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

fromDate define desde cuándo se aplican los costos a tu historial. Si lo omites, se aplican desde el primer día del mes de hace dos años. Envíalo si tu costo es ponderado y cambia seguido.

Saber cuántos productos te faltan por costear

Una sola petición, sin descargar el catálogo: pide una página de un producto y lee el total.

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

El campo meta.totalRows de la respuesta es la cantidad de productos sin costo cargado.

Costear solo lo nuevo

Si tu catálogo ya está costeado y solo quieres cubrir los productos que ingresaron después, pagina con withoutCost=true en lugar de leer el maestro completo.

Preguntas frecuentes

¿Por qué debo usar el ID Producto que entrega la API y no el de mi sistema? Porque la carga de costos busca cada producto por la combinación de ID Cuenta e ID Producto. Si envías un identificador que no existe en Wivo, la carga no falla: crea un producto nuevo que no corresponde a ninguna publicación real y ensucia tu catálogo. Partir del maestro evita ese problema.

¿Puedo cargar costos usando mi SKU interno como identificador? No directamente. El cruce por SKU lo haces de tu lado: lees el maestro, buscas tu SKU en la columna SKU Producto (o en SKU Producto Interno si lo cargaste antes) y escribes el costo en la fila correspondiente, que ya trae los identificadores correctos.

¿Qué pasa si un producto no tiene costo? El campo Costo de producto (con IVA) viene como null. Al convertir a CSV queda como celda vacía, que la carga interpreta como “sin costo”.

¿Aparecen los productos sin ventas? Sí. El maestro es tu catálogo completo, no solo lo que se vendió en un período.

¿Con qué frecuencia se actualiza? Los cambios de costo y de atributos internos se reflejan en pocos minutos. Un producto recién creado en el marketplace puede tardar hasta 30 minutos en aparecer.

¿Este recurso consume mi cuota de la API de datos? No. Tiene su propio límite de 30 peticiones por minuto, independiente del de GET /data.