API de Wivo Analytics

La API de Wivo te permite acceder programáticamente a datos de ventas, ítems de órdenes, costos asociados (comisiones, envíos, promociones, publicidad), márgenes y métricas de rentabilidad disponibles en los reportes de la plataforma.

¿Por dónde empezar? Si vas a integrar por primera vez, lee las secciones 1 a 6 en orden: te llevan desde habilitar la API hasta dejar tus datos sincronizados. Las secciones 7 a 11 son la referencia técnica que vas a consultar de a ratos (parámetros, campos, límites).

1. Casos de uso principales

  1. Integrar datos de Wivo en data warehouses, ERPs, sistemas contables o herramientas internas
  2. Automatizar reportes y dashboards personalizados sin exportaciones manuales de archivos

2. Datos disponibles

La API entrega información a nivel de ítem de orden, que incluye:

  • Detalle de la orden (ID, fecha de compra, SKUs, tipo de envío, estado de orden y pago, comprador)
  • Atributos del producto (marca, categoría, publicación) y tu catálogo interno del Maestro de productos
  • Costos de la orden (comisiones, envío, logística)
  • Costos adicionales (almacenamiento fulfillment, publicidad)
  • Métricas derivadas: rentabilidad, costos y porcentajes. Wivo calcula la rentabilidad en tres alcances según qué costos descuenta — los tres llegan por la API, y están explicados en Los tres alcances de rentabilidad

3. Habilitar la API

  1. Accede a tu cuenta de Wivo con credenciales de administrador
  2. Ve a “Integración API” en el menú superior derecho
  3. Haz clic en “Solicitar habilitación de API”
  4. Agenda una reunión con un representante de Wivo para la activación
  5. Recibe tu API Key personal y confidencial

Precio. El acceso a la API de datos es un add-on, aparte de tu plan: tiene 30 días de prueba gratis y, después, cuesta un 30% adicional sobre el valor de tu plan base. Se factura por separado del plan. El Maestro de productos por API viene incluido en el plan Pro y no paga este add-on.

¿Vas a enviar las órdenes de tu tienda propia? La API de órdenes (beta) viene incluida en el plan Pro y no necesita esta habilitación: tu API Key está en la vista Integración con API.

4. Autenticación

Incluye tu API Key en el header HTTP de cada petición:

Ocp-Apim-Subscription-Key: TU_API_KEY

Las claves inválidas o ausentes retornan HTTP 401 Unauthorized. Si tu cuenta no tiene habilitado el acceso a la API de datos, o la suscripción fue revocada, retorna HTTP 403 Forbidden.

5. Tu primera petición

Con tu API Key lista, haz esta petición para confirmar que todo funciona. Trae los ítems de órdenes de un rango de fechas:

curl "https://api.wivoanalytics.com/data?date=purchase_date&from=2025-01-01&to=2025-01-31&page=1" \
  -H "Ocp-Apim-Subscription-Key: TU_API_KEY_AQUI"

La respuesta es un JSON con dos partes:

  • data — el array de ítems de orden (cada uno con sus ventas, costos y rentabilidad). Ver el detalle de los campos en la sección 8.
  • meta — información de paginación. Fíjate en totalPages: te dice cuántas páginas hay que recorrer para traer todo el rango.

Con esto ya puedes explorar los datos. Para una integración de verdad, sigue con la sección 6 (cómo mantener tus datos sincronizados) y usa las secciones 7 a 11 como referencia del detalle de cada parámetro y campo.

6. Cómo sincronizar tus datos: flujo histórico vs. flujo regular

Para una integración real vas a tener dos flujos: una carga histórica (una sola vez, para traer todo el pasado) y un flujo regular (recurrente, para mantenerte sincronizado).

Modelo mental — por qué borrar e insertar (delete + insert): Una orden no es inmutable. Después de la compra puede cambiar de estado, ajustar costos, recibir reembolsos o cancelarse. Por eso, cada vez que una orden aparece en la respuesta, borra todos sus ítems en tu base y vuelve a insertarlos completos. Así tu copia siempre refleja el último estado de Wivo, sin duplicados ni datos viejos. El campo para agrupar los ítems de una misma orden es Orden.

6.1. Carga histórica (backfill inicial)

Objetivo: traer toda la historia que incluye tu plan, una sola vez.

Usa date=purchase_date y pagina hasta agotar el rango. El campo meta.totalPages de la respuesta (ver sección 8) te dice cuántas páginas hay.

El punto de partida es el inicio de la ventana que incluye tu plan (ver sección 7.2). Desde ahí, un solo rango paginado cubre toda tu historia: sin to, la ventana llega hasta hoy.

desde_cuando = inicio_de_la_ventana_de_tu_plan()   # ver sección 7.2

page = 1
total_pages = 1                      # se actualiza con la primera respuesta
while page <= total_pages:
    resp = GET("/data", params={
        "date": "purchase_date",
        "from": desde_cuando,
        "page": page,
        "limit": 1000,
    })
    guardar_con_delete_insert(resp["data"])   # borrar ítems de cada Orden y reinsertar
    total_pages = resp["meta"]["totalPages"]
    page += 1

# Guarda el mayor "Fecha de actualización" (updated_at) que hayas visto:
# es el punto de partida del flujo regular.

Pide páginas grandes y respeta el rate limit. Con limit=1000 traes 10 veces más filas por request que con el mínimo, y el techo son 5 req/min (ver sección 10): unas 5.000 filas por minuto. Agrega una pausa entre páginas y reintentos con backoff exponencial ante un HTTP 429.

6.2. Flujo regular (incremental, por hora o por día)

Objetivo: mantener tu copia sincronizada trayendo solo lo que cambió.

Usa date=updated_at desde la última fecha que procesaste. Esto trae órdenes nuevas y actualizaciones (cambios de estado, ajustes de costo, cancelaciones, reembolsos):

last_synced = "2025-01-15T09:55:00"   # ← último updated_at procesado, MENOS la ventana de seguridad

page = 1
total_pages = 1
while page <= total_pages:
    resp = GET("/data", params={
        "date": "updated_at",
        "from": last_synced,
        "page": page,
        "limit": 1000,
    })
    guardar_con_delete_insert(resp["data"])
    total_pages = resp["meta"]["totalPages"]
    page += 1

La ventana se aplica a la fecha de actualización: la respuesta trae las subórdenes actualizadas en el rango, aunque se hayan comprado antes. Una orden comprada hace tres meses que hoy cambia de estado aparece en la ventana de hoy.

El alcance cubre las compras de los últimos 120 días y viene declarado en cada respuesta (ver sección 11).

Ventana de seguridad (recomendado): resta 5–10 min a tu último updated_at antes de pedir de nuevo. Si lo último procesado fue 2025-01-15T10:00:00, pide desde 2025-01-15T09:55:00. Esto evita perder cambios por desfases de reloj o latencia. Como reinsertas por orden completa, volver a traer una orden no genera duplicados.

Elige ventanas cortas. Una ventana de varios días puede devolver varias páginas aun con limit=1000. Con el rate limit de 5 req/min (ver sección 10), sincronizar por hora es más rápido y liviano que por día.

Límite de 7 días con updated_at: un request no puede cubrir más de 7 días (ver sección 7.2). Si tu proceso estuvo caído más de una semana, avanza en ventanas de ≤7 días hasta alcanzar el presente.

7. Referencia: endpoint y parámetros

7.1. Endpoint

  • GET /data — Devuelve órdenes e ítems de costos con todo su detalle.

7.2. Parámetros de GET /data

  • date (purchase_date o updated_at): Debes escoger uno de estos parámetros (obligatorio)
  • from: obligatorio, ISO 8601. Acepta 2025-01-31 o 2025-01-31T09:55:00
  • to: opcional, ISO 8601. Acepta 2025-02-01 o 2025-02-01T18:30:00
  • item_type: opcional. Filtra por tipo de fila: order, publication o marketplace. Acepta varios valores separados por coma. Los alias orders y publications siguen siendo válidos
  • payment_status: opcional. Filtra por estado de pago: paid, unpaid o noinformation. Acepta varios valores separados por coma
  • item_status: opcional. Filtra por estado de la orden: paid, canceled o returned. Acepta varios valores separados por coma
  • page: opcional
  • limit: opcional, tamaño de página. Default 1000, máximo 1000
  • categories: opcional, lista separada por comas: income, costs, reimbursement, products, orders, channels, internal-cost. Agrega columnas a cada fila de la respuesta —medidas, atributos, o ambos según la categoría— (ver sección 9). Si se omite, se devuelve exactamente el conjunto base
  • timezone: opcional, único valor aceptado utc. Devuelve Fecha de compra como instante en UTC en vez de la hora local del canal. Si se omite, nada cambia; cualquier otro valor retorna HTTP 400 Bad Request (ver sección 11)

Hora en from y to: si envías hora, se respeta. Si envías solo la fecha, from se completa a las 00:00:00 y to a las 23:59:59 de ese día. La zona en que se interpretan depende del campo que filtres y de si envías timezone (ver sección 11).

Ventana de fechas que incluye tu plan. Tu plan define desde cuándo puedes consultar:

PlanPuedes consultar desde
FreeEl día 1 del mes anterior al actual
ProEl 1 de enero de dos años atrás

Con purchase_date puedes pedir esa ventana completa en una sola petición y recorrerla paginando con limit (el ritmo lo marca el rate limit, ver sección 10).

Con date=updated_at una petición no puede cubrir más de 7 días, cualquiera sea tu plan.

Un to posterior al día de hoy se recorta a hoy, porque más allá no hay datos todavía. El valor efectivo viaja en meta.to.

Un from anterior a la ventana de tu plan retorna HTTP 400 Bad Request, con tu plan y la fecha desde la que puedes consultar en el mensaje. La petición falla completa: no se devuelve un rango recortado, para que puedas distinguir un tramo que no entró de uno que vino vacío.

Un parámetro inválido —fecha, rango excedido, o un valor no reconocido en item_type, payment_status o item_status— retorna HTTP 400 Bad Request indicando qué valor se rechazó y cuáles son los válidos.

Un nombre de parámetro que no esté en esta lista también retorna 400, con los nombres válidos en el mensaje. Es a propósito: si un parámetro mal escrito se ignorara en silencio, recibirías todas las filas creyendo que filtraste.

Ejemplos:

Con purchase_date:

curl "https://api.wivoanalytics.com/data?date=purchase_date&from=2025-01-01&to=2025-01-31&page=1" \
  -H "Ocp-Apim-Subscription-Key: TU_API_KEY_AQUI"

Con updated_at:

curl "https://api.wivoanalytics.com/data?date=updated_at&from=2025-01-01T20:55:00" \
  -H "Ocp-Apim-Subscription-Key: TU_API_KEY_AQUI"

7.3. Valores de los filtros y lo que devuelve cada columna

Los filtros se envían con la clave en inglés. Las columnas de la respuesta traen la etiqueta en español.

ParámetroValor a enviarColumnaValor que verás
item_typeorderTipo de DatoOrden
item_typepublicationTipo de DatoPublicación
item_typemarketplaceTipo de DatoMarketplace
payment_statuspaidEstado de PagoPagado
payment_statusunpaidEstado de PagoInformado
payment_statusnoinformationEstado de PagoSin Información
item_statuspaidEstado de OrdenRegular
item_statuscanceledEstado de OrdenCancelada
item_statusreturnedEstado de OrdenDevuelta

unpaid se muestra como Informado. Antes esa columna decía No Pagado. Lo que cambió es la etiqueta que viaja en la respuesta, no el contrato: el valor que envías en el filtro sigue siendo payment_status=unpaid. Si tu proceso concilia comparando el texto de la columna Estado de Pago, ajústalo a Informado; si filtra por la clave, no tienes que cambiar nada.

Ojo con item_status=paid: devuelve las órdenes en estado Regular, o sea las que no fueron canceladas ni devueltas. No tiene relación con el estado de pago; para eso está payment_status.

Los filtros son independientes entre sí y se combinan con AND. Los valores dentro de un mismo filtro se combinan con OR: payment_status=paid,unpaid trae las filas que estén en cualquiera de los dos estados.

Qué trae una fila marketplace

Son movimientos que el marketplace registra a nivel de cuenta y no de una venta puntual: tarifas de almacenamiento, cobros de publicidad, cargos de facturación, y también sus reembolsos y compensaciones.

Lo que caracteriza a estas filas:

  • Ventas y Unidades vienen en 0
  • SKU Producto viene en Sin SKU
  • Producto trae la descripción que el marketplace le da al movimiento, tal cual la escribe y en su propio idioma: Wivo no la traduce ni la normaliza. Un mismo tipo de cobro puede llegar como Cobro por Productos patrocinados desde una cuenta de un marketplace en español y como Tarifa pelo serviço de armazenamento Full desde una de Brasil. No conviene clasificar por este texto: para eso está la medida de costo que acompaña a la fila
  • Costo de Marketplace trae el monto, junto con la medida de la sección de costo que corresponda
  • Estado de Orden viene en Regular

Importan al calcular costos: traen costo y no traen ventas. Si las excluyes con item_type=order o item_type=order,publication, ese costo no aparece en la respuesta. Cuánto pesa depende de la cuenta y del marketplace.

Pedir el mismo recorte que el panel de Rentabilidad

Wivo Analytics tiene una vista de Rentabilidad que muestra estos mismos datos. Si usas la plataforma y quieres que tus cifras coincidan con las de esa vista, o si simplemente quieres el recorte con el que Wivo calcula rentabilidad, es este: órdenes y publicaciones, en estado Regular, dejando fuera las filas sin información de pago.

Se pide así:

curl "https://api.wivoanalytics.com/data?date=purchase_date&from=2025-01-01&item_type=order,publication&payment_status=paid,unpaid&item_status=paid" \
  -H "Ocp-Apim-Subscription-Key: TU_API_KEY_AQUI"

Ese recorte define qué filas entran. Qué alcance de rentabilidad quieres leer define qué columnas pides, y se agrega con categories. Los tres alcances —Marketplace, Comercial y Total— se diferencian por los costos que descuentan, y están explicados en Los tres alcances de rentabilidad:

AlcanceColumnas que lo componenQué agregar a la petición
MarketplaceRentabilidad Marketplace, % Rentabilidad Marketplace, Costo de Marketplacenada: vienen en el conjunto base
ComercialRentabilidad Comercial, % Rentabilidad Comercial, Costo Comercial, % Costo Comercial&categories=internal-cost,costs
TotalRentabilidad Total, % Rentabilidad Total, Costo Total, % Costo Total&categories=internal-cost,costs

Comercial y Total se piden con las mismas categorías, así que una sola petición trae las columnas de los dos alcances a la vez. No hace falta pedirlos por separado: eliges cuál leer según la pregunta que estés respondiendo.

Si comparas contra la plataforma y los totales no cuadran, revisa además la ventana de fechas y su zona horaria (ver sección 11): es la causa más frecuente.

8. Estructura de respuesta de GET /data

Ejemplo simplificado:

{
  "data": [
    {
      "Canal": "Marketplace A",
      "Cuenta": "Cuenta Demo 1",
      "Orden": "1000000000000001",
      "Nro. suborden": "1000000000000001",
      "Nro. Paquete": "1000000000000001",
      "N° de Liquidación": "1000000000000001",
      "SKU Producto": "SKU-DEMO-001",
      "SKU Marketplace": "9000000000001",
      "Producto": "Producto Demostración 1 - Talla: L",
      "Variante": "Talla: L",
      "SKU Variante": "SKU-DEMO-001",
      "Fecha de actualización": "2024-01-11T06:26:29.000Z",
      "Estado de Orden": "Regular",
      "Estado de Pago": "Pagado",
      "Estado de Despacho": "Entregado",
      "Tipo de Despacho": "No Fulfillment",
      "Fecha de compra": "2024-01-09T23:56:56.000",
      "Tipo de Dato": "Orden",
      "Ventas": "7500",
      "Unidades": "1",
      "Costo de Marketplace": "1500.00",
      "Rentabilidad Marketplace": "6000.00",
      "% Rentabilidad Marketplace": "80.00",
      "Costo Envío": "1000",
      "Costo de Comisiones": "500"
    },
    {
      "Canal": "Marketplace A",
      "Cuenta": "Cuenta Demo 1",
      "Orden": "1000000000000002",
      "Nro. suborden": "1000000000000003",
      "Nro. Paquete": "1000000000000002",
      "N° de Liquidación": "1000000000000002",
      "SKU Producto": "SKU-DEMO-002",
      "SKU Marketplace": "9000000000002",
      "Producto": "Producto Demostración 2 - Talla: L Tamaño: 10.2",
      "Variante": "Color: Azul, Tamaño: 10.2",
      "SKU Variante": "SKU-DEMO-002",
      "Fecha de actualización": "2024-01-11T06:29:13.000Z",
      "Estado de Orden": "Regular",
      "Estado de Pago": "Pagado",
      "Estado de Despacho": "Entregado",
      "Tipo de Despacho": "Fulfillment",
      "Fecha de compra": "2024-01-09T23:56:43.000",
      "Tipo de Dato": "Orden",
      "Ventas": "12000",
      "Unidades": "1",
      "Costo de Marketplace": "4000.00",
      "Rentabilidad Marketplace": "8000.00",
      "% Rentabilidad Marketplace": "66.67",
      "Costo Envío": "2000",
      "Costo de Comisiones": "2000"
    }
    // ... aquí podrías seguir agregando más items con los mismos campos
  ],
  "meta": {
    "page": 1,
    "pageSize": 100,
    "count": 100,
    "from": "2024-01-09T00:00:00",
    "to": "2024-01-09T23:59:59",
    "date": "purchase_date",
    "totalRows": 3282,
    "totalPages": 33
  },
  "correlation_id": "00000000-0000-4000-8000-000000000001"
}

El objeto meta te da todo lo necesario para paginar: page (página actual), totalPages (total de páginas del rango) y totalRows (total de ítems). Recorre desde page=1 hasta totalPages para traer el rango completo.

Este ejemplo es la respuesta por defecto, la que recibes si no envías categories. Con ese parámetro cada ítem llega con columnas adicionales —atributos del producto y de la orden, el desglose de costos, los alcances de rentabilidad— y el conjunto base no cambia (ver sección 9).

También trae window y fields, que declaran la zona horaria de la ventana y de cada campo de fecha (ver sección 11):

"meta": {
  "page": 1,
  "pageSize": 100,
  "count": 100,
  "from": "2024-01-09T00:00:00",
  "to": "2024-01-09T23:59:59",
  "date": "purchase_date",
  "totalRows": 3282,
  "totalPages": 33,
  "window": { "field": "purchase_date", "timezone": "local" },
  "fields": {
    "Fecha de compra": { "type": "datetime", "timezone": "local" },
    "Fecha de actualización": { "type": "datetime", "timezone": "UTC" }
  }
}

9. Columnas adicionales (categories)

Por defecto, cada ítem de data trae un conjunto base: los atributos de la orden y del producto que ves en el ejemplo de la sección 8, más 7 medidas.

Ventas, Unidades, Costo de Marketplace, Rentabilidad Marketplace, % Rentabilidad Marketplace, Costo Envío, Costo de Comisiones.

El parámetro categories agrega columnas a cada ítem de data: el desglose detrás de esos totales, atributos adicionales del producto y de la orden, y los alcances de rentabilidad. Pides una o más categorías separadas por coma.

Una categoría no significa “todo lo de X”. Significa “lo de X que no viene ya en el conjunto base”. categories=channels agrega Tipo de Canal, mientras Canal y Cuenta siguen llegando siempre, la pidas o no. Con las medidas ocurre lo mismo: Ventas pertenece a income y llega igual sin pedir nada.

El conjunto base llega siempre. Pidas las categorías que pidas, esas columnas aparecen con las mismas claves y los mismos valores: categories únicamente agrega, nunca quita ni renombra.

Una misma orden puede ocupar varias filas, y dos de ellas pueden coincidir en todas las columnas que recibes y diferir solo en los montos. No uses las columnas de la respuesta como clave única para deduplicar: perderías registros.

Los porcentajes son de la fila, no de la ventana. % Costo Total o % Rentabilidad Total son la tasa de esa fila sola. Para la tasa de un conjunto —un día, una marca, un canal— suma los montos y haz la división tú: promediar los porcentajes de las filas da otro número.

Las columnas se identifican por su nombre exacto (el mismo que aparece como clave en el JSON, siempre en español). Si pides varias categorías y comparten alguna columna, aparece una sola vez (no se duplica). Los totales Ventas y Costo de Marketplace ya vienen en el conjunto base; las categorías agregan su desglose.

income — Ingresos de la orden

Columna
Ventas
Despacho pagado por comprador
Ingreso por Envío Flex
Ingreso de Compensación por Daños
Ingreso por promoción
Ingresos sin categorizar
Ingreso Totaltotal de la categoría

costs — Costos del marketplace

Refleja el análisis de costos de la plataforma, agrupado por sección. El total de cada sección está en negrita.

Ojo con el gran total. Costo de Marketplace es el costo total del canal y las ocho secciones de abajo son su desglose. Si necesitas el total exacto, usa Costo de Marketplace directamente en vez de sumar las secciones.

El desglose de comisiones describe el cobro, no lo reemplaza. Cobro de Comisiones y Reembolso de Comisiones son los totales que informa el marketplace; Comisión Variable, Comisión Fija y Comisión por Cuotas —con sus tres reembolsos— te dicen de qué se componen. Para conciliar montos, usa los totales.

Comisiones: Cobro de Comisiones, Comisión Variable, Comisión Fija, Comisión por Cuotas, Reembolso de Comisiones, Reembolso de Comisión Variable, Reembolso de Comisión Fija, Reembolso de Comisión por Cuotas, Costo de Comisiones

Envío: Despacho pagado por comprador, Cobro Envío Flex, Ingreso por Envío Flex, Reembolso de envío, Cobro de Envío, Costo Envío

Publicidad: Cobro por publicidad, Reembolso por publicidad, Costos por publicidad

Almacenamiento Fulfillment: Cobro por Costo Logístico, Reembolso de Costo Logístico, Cobro por Servicio Almacenamiento, Cobro por Almacenamiento Prolongado, Cobro por Descarte de Stock, Reembolso por servicio almacenamiento, Reembolso por descarte de stock, Reembolso por almacenamiento prolongado, Costos de Almacenamiento Fulfillment

Otros costos: Cobro de Ajuste sobre la Comisión, Reembolso de Ajuste sobre la Comisión, Cobro de Penalizacion por Cancelación, Devolución de Penalización por Cancelación, Cobro Logística Inversa, Reembolso Logística Inversa, Cobro de Penalización por Daños, Ingreso de Compensación por Daños, Reembolso de Ajuste sobre Venta, Ingreso por promoción, Cobros sin categorizar, Ingresos sin categorizar, Reembolsos sin categorizar, Cobro de Impuestos, Reembolso de Impuestos, Otros costos

Descuentos y Promociones: Cobro por Cupones de Descuento, Reembolso por Cupones de Descuento, Costos de Descuentos y Promociones

Gestión de Cuenta: Cobro por Asesoría Comercial (KAM), Cobro por Uso de Mercado Pago, Cobro por Mantenimiento eShop, Cobro por Reputación, Cobro por Publicar, Reembolso por Asesoría Comercial (KAM), Reembolso por Uso de Mercado Pago, Reembolso por Mantenimiento eShop, Costos de Gestión de Cuenta

Financiamiento: Cobro por Financiación y Cuotas Mercado Pago, Cobro por Adelanto de Dinero, Reembolso por Financiación y Cuotas Mercado Pago, Costos de Financiamiento

Gran total: Costo de Marketplace

Además del desglose por sección, costs trae los totales y las tasas de la vista de Rentabilidad:

Totales de la venta: Venta Cancelada, Cobro Total, Cobros Comercial

Costo por alcance: Costo de Marketplace (Marketplace), Costo Comercial (Comercial), Costo Total (Total)

Tasas: % Costo de Marketplace, % Costo Comercial, % Costo Total, % Cobro de Comisiones, % Costo de Comisiones, % Costo de Publicidad, % Costo Envío, % Costo Producto

Qué mide cada alcance está explicado en Los tres alcances de rentabilidad.

reimbursement — Reembolsos de cargos

Columna
Reembolso de Ajuste sobre la Comisión
Devolución de Penalizacion por Cancelación
Reembolso Logística Inversa
Reembolso de Ajuste sobre Venta
Reembolso de Comisiones
Reembolso de Comisión Variable
Reembolso de Comisión Fija
Reembolso de Comisión por Cuotas
Reembolso de envío
Reembolso de Costo Logístico
Reembolso por publicidad
Reembolsos sin categorizar
Reembolso por servicio almacenamiento
Reembolso por descarte de stock
Reembolso por almacenamiento prolongado
Reembolso de Impuestos
Reembolso Totaltotal de la categoría

products — Atributos del producto

Columna
Marca
Categoría
Id publicaciónIdentificador de la publicación en el marketplace

Producto, SKU Producto, SKU Marketplace, Variante y SKU Variante ya vienen en el conjunto base.

orders — Atributos de la orden

Columna
Comprador
Tipo de Despacho del MarketplaceModalidad de despacho tal como la nombra el marketplace
Fecha de Pago

Tipo de Despacho y Tipo de Despacho del Marketplace son dos columnas distintas, no dos nombres del mismo dato. La primera viene en el conjunto base y distingue fulfillment de no fulfillment. La segunda llega con categories=orders y trae la modalidad que declara el marketplace.

Orden, Nro. suborden, Nro. Paquete, N° de Liquidación, Fecha de compra y los estados ya vienen en el conjunto base.

channels — Atributos del canal

Columna
Tipo de CanalDistingue, por ejemplo, un marketplace de una tienda propia

Canal y Cuenta ya vienen en el conjunto base.

internal-cost — Catálogo interno y rentabilidad

Trae tu catálogo interno —el que cargas en el Maestro de productos— y el costo de producto con las rentabilidades que dependen de él.

Columna
Marca Interna
Categoría Interna
Producto Interno
SKU Producto Interno
Costo de Producto
Rentabilidad Comercial
% Rentabilidad Comercial
Rentabilidad Total
% Rentabilidad Total

Los costos de cada alcance —Costo Comercial, Costo Total y sus tasas— llegan con categories=costs.

Los tres alcances de rentabilidad

Wivo calcula tres rentabilidades sobre la misma venta, y las tres son correctas a la vez: lo que cambia es qué costos descuenta cada una. Las tres se piden desde la API.

AlcanceQué descuentaPara qué sirve
MarketplaceSolo los cobros del canal, sin el costo de tu productoConciliar contra lo que el canal te deposita
ComercialLos cobros del canal atribuibles a la venta, más el costo del productoDecidir precio y surtido de un producto, sin mezclar gastos que no dependen de esa venta
TotalTodo: los ocho tipos de costo del canal más el costo del productoLa mirada del negocio: qué queda al final

Comercial es Total sin los cuatro cobros que no son consecuencia de haber vendido esa unidad: publicidad, almacenamiento fulfillment, gestión de cuenta y financiamiento. Muchos vendedores los pagan de otro presupuesto y necesitan la rentabilidad del producto sin ellos; en el alcance Total siguen sumando. Los cuatro llegan igual en la respuesta con categories=costs, cada uno en su sección.

Qué significa cada alcance para tu negocio y cuándo conviene cada uno está en Tipos de rentabilidad en Wivo.

Cómo se compone la rentabilidad

Con categories=income,costs,reimbursement,internal-cost recibes las cuatro columnas que la forman, y puedes reproducir el cálculo fila por fila:

Rentabilidad Total     = Ingreso Total - Cobro Total      + Reembolso Total - Costo de Producto
Rentabilidad Comercial = Ingreso Total - Cobros Comercial + Reembolso Total - Costo de Producto

La única diferencia entre las dos es el cobro que restan: Cobros Comercial es Cobro Total sin esos cuatro cobros. La resta entre las dos rentabilidades te dice cuánto pesan en la fila.

Cuando el costo de producto todavía no está cargado

El costo de producto lo cargas tú en Wivo: el marketplace no lo informa. Cuando una fila todavía no lo tiene cargado en el Maestro de productos, Costo de Producto llega en 0, no vacío. Ese 0 entra igual en el cálculo, así que Rentabilidad Comercial y Rentabilidad Total quedan más altas de lo que serán una vez que cargues el costo.

Tenlo presente antes de consolidar rentabilidad sobre un conjunto de filas. La práctica recomendada es cruzar el SKU Producto Interno de cada fila contra tu propio maestro de costos y decidir qué hacer con las que no encuentres —excluirlas, imputarles un costo o revisarlas— en vez de sumar todo de corrido. Rentabilidad Marketplace no descuenta el costo de producto, así que no se ve afectada.

Ejemplos

curl "https://api.wivoanalytics.com/data?date=purchase_date&from=2025-01-01&to=2025-01-31&categories=income,costs" \
  -H "Ocp-Apim-Subscription-Key: TU_API_KEY_AQUI"

Cada ítem de data llega con el conjunto base más las columnas de las categorías pedidas (en negrita las que aparecen solo por categories=income,costs):

{
  "Orden": "1000000000000001",
  "Ventas": "7500",
  "Unidades": "1",
  "Costo de Marketplace": "1500.00",
  "Rentabilidad Marketplace": "6000.00",
  "Ingreso Total": "7500.00",
  "Cobro de Comisiones": "500",
  "Costo de Comisiones": "500",
  "Cobro de Envío": "1000",
  "Costo Envío": "1000"
}

Con categories=products,orders,channels,internal-cost la misma fila llega con los atributos del catálogo y los otros dos alcances de rentabilidad:

{
  "Orden": "1000000000000001",
  "Marca": "Marca Demostración",
  "Categoría": "Categoría Demostración",
  "Id publicación": "9000000000001",
  "Comprador": "Comprador Demostración",
  "Tipo de Despacho del Marketplace": "Envío a domicilio",
  "Tipo de Canal": "Marketplace",
  "Marca Interna": "Marca Interna Demostración",
  "Categoría Interna": "Categoría Interna Demostración",
  "Producto Interno": "Producto Interno Demostración",
  "SKU Producto Interno": "SKU-INT-001",
  "Ventas": "7500",
  "Costo de Producto": "3000",
  "Rentabilidad Comercial": "3300.00",
  "% Rentabilidad Comercial": "44.0",
  "Rentabilidad Total": "3000.00",
  "% Rentabilidad Total": "40.0"
}

Una categoría no válida retorna HTTP 400 Bad Request.

10. Límites de uso (Rate limits)

  • 5 peticiones por minuto por API Key
  • 7.200 peticiones por día por API Key
  • Superar cualquiera de los dos retorna HTTP 429 Too Many Requests

Los dos límites se aplican, no son una recomendación. Con limit=1000 (ver sección 7.2), 5 peticiones por minuto equivalen a unas 5.000 filas por minuto, así que el techo real de tu sincronización lo marca el tamaño de página que pidas: cuanto más grande, menos peticiones necesitas para el mismo dato.

Como buenas prácticas, implementa reintentos con backoff exponencial y agrupa la lógica para aprovechar al máximo cada petición.

11. Fechas y zonas horarias

La respuesta trae dos campos de fecha, y cada uno viene en una zona distinta. Es importante para cualquier cálculo o cruce con tus propias fuentes.

CampoZonaFormato
Fecha de actualizaciónUTC2026-08-14T16:00:42.286Z — con designador Z y milisegundos
Fecha de compraHora local del canal de venta2026-08-14T08:12:59.000 — sin designador de zona

Con categories=orders se suma una tercera columna de fecha, Fecha de Pago, en el mismo formato que Fecha de compra: sin designador de zona. Trátala con el mismo criterio.

Fecha de compra también puede pedirse en UTC, con un parámetro: ver Pedir la fecha de compra en UTC.

Fecha de actualización

Viene siempre en UTC, con la Z y con milisegundos. Es el mismo valor sin importar por qué campo filtres, así que puedes parsearla directamente como instante.

Marca cuándo Wivo actualizó por última vez ese registro, y es el campo que se usa como cursor del flujo incremental de la sección 6.2.

Fecha de compra

Viene en la hora local del canal de venta, sin designador de zona. No la interpretes como UTC: la mayoría de los parsers asumen UTC cuando falta la Z, y eso desplaza la fecha varias horas.

Como la zona depende del canal, dos órdenes compradas en el mismo instante en canales de países distintos traen relojes distintos en este campo. Si necesitas comparar instantes o cruzar con fuentes en UTC, pide este mismo campo en UTC con timezone=utc (ver abajo). Fecha de actualización es la referencia cuando lo que te interesa es cuándo se actualizó el registro, no cuándo se compró.

Pedir la fecha de compra en UTC

Con timezone=utc en la petición, Fecha de compra llega como instante en UTC: el mismo formato que Fecha de actualización, con designador Z y milisegundos. Así puedes parsearla sin conocer la zona del canal.

curl "https://api.wivoanalytics.com/data?date=purchase_date&from=2025-01-01&to=2025-01-31&timezone=utc"   -H "Ocp-Apim-Subscription-Key: TU_API_KEY_AQUI"

Qué formato tiene cada campo de fecha en cada caso:

CampoSin timezoneCon timezone=utc
Fecha de compraHora local del canal, sin designador de zonaInstante en UTC, con Z
Fecha de actualizaciónUTC, con ZUTC, con Z
Fecha de Pago (con categories=orders)Hora local del canal, sin designador de zonaHora local del canal, sin designador de zona

Un ejemplo con el desplazamiento a la vista: una compra registrada a las 08:12:59 en un canal que opera en UTC−4 llega como 2026-08-14T08:12:59.000 sin el parámetro, y como 2026-08-14T12:12:59.000Z con él.

timezone también define la zona de la ventana. Con timezone=utc, from y to se interpretan en UTC, así que un mismo rango de fechas no selecciona exactamente las mismas compras que sin el parámetro: las de las primeras y últimas horas del rango entran o salen según el desplazamiento del canal. Si comparas las dos respuestas, espera totales distintos.

Fecha de Pago llega siempre en la hora local del canal, con el parámetro y sin él. meta.fields declara su zona en cada respuesta.

El único valor aceptado es utc, en minúsculas. Cualquier otro —local, UTC en mayúsculas o el nombre de una zona— retorna HTTP 400 Bad Request, indicando el valor recibido y cuáles son los válidos.

Zona de from y to

Se interpretan en la misma zona que el campo que estás filtrando, y meta.window te lo indica en cada respuesta:

FiltroZona de from y to
date=updated_atUTC
date=purchase_dateHora local del canal, igual que el campo
date=purchase_date + timezone=utcUTC

Con date=updated_at, el valor de Fecha de actualización que recibes se puede reenviar tal cual como from en el siguiente request. Si filtras por updated_at, timezone no altera la ventana: esa ventana se interpreta en UTC en todos los casos.

Alcance de la búsqueda por fecha de actualización

Con date=updated_at, la respuesta incluye las subórdenes cuya fecha de compra esté dentro de los 120 días previos al inicio del rango consultado.

Cada respuesta declara ese límite en meta.window.purchaseDateFrom:

"window": {
  "field": "updated_at",
  "timezone": "UTC",
  "purchaseDateFrom": "2026-04-16T00:00:00"
}

Para consultar compras anteriores a ese límite, usa date=purchase_date con el rango que necesites.

Declaración en la respuesta

meta.fields declara la zona de cada campo de fecha en cada respuesta, con las mismas claves que ves en data: Fecha de compra, Fecha de actualización y, cuando pides categories=orders, Fecha de Pago. La declaración refleja lo que pediste, así que no necesitas deducir la zona del formato ni recordar con qué parámetros armaste la petición. Si tu integración verifica el formato antes de parsear, léelo de ahí en vez de asumirlo.

Así se ve una respuesta pedida con timezone=utc y categories=orders:

"window": { "field": "purchase_date", "timezone": "UTC" },
"fields": {
  "Fecha de compra": { "type": "datetime", "timezone": "UTC" },
  "Fecha de actualización": { "type": "datetime", "timezone": "UTC" },
  "Fecha de Pago": { "type": "datetime", "timezone": "local" }
}