API de pedidos (beta)
Beta. A API está em beta: o contrato pode mudar, e avisamos antes.
Se o seu e-commerce é de desenvolvimento próprio, não existe um conector que baixe os seus pedidos. Com esta API, você mesmo os envia a partir do seu sistema, e eles aparecem na Wivo junto com os dos seus marketplaces: em Vendas, em Rentabilidade e no Cadastro de produtos.
Você envia lotes de pedidos para POST /orders. Cada pedido vai completo, com todas as suas linhas, e a Wivo calcula o resto: o custo a partir do seu Cadastro, e o frete e a comissão do gateway de pagamento distribuídos entre as linhas.
Está incluída no plano Pro: não é um add-on. Por enquanto é apenas para contas do Chile, com valores em pesos chilenos (CLP).
Os nomes das telas e botões aparecem em espanhol, como na app da Wivo. As mensagens de erro da API também vêm em espanhol.
Para que serve?
- Ver as vendas da sua loja própria nos mesmos painéis que as dos seus marketplaces
- Calcular a rentabilidade com o custo do seu Cadastro, o custo de frete e a comissão do seu gateway de pagamento
- Manter em dia cancelamentos e devoluções: você reenvia o pedido com o novo status e a Wivo o substitui
Requisitos
- Conta Wivo com plano Pro, do Chile
- Sua API Key, da tela Integración con API
- O
source_idda sua fonte Tienda propia (API) (loja própria via API)
Você não precisa do add-on da API de dados: este recurso está incluído no plano Pro.
Como obter sua API Key?
- Entre na Wivo com o seu usuário.
- Abra Integración con API no menu, ou acesse direto app.wivoanalytics.com/u/0/#/api.
- Copie sua API Key. Com o plano Pro você a obtém ali mesmo, sem o add-on da API de dados. É pessoal, secreta e está associada à sua conta.
É a mesma chave para todos os recursos da API da Wivo.
Como obter seu source_id?
O source_id identifica a sua fonte Tienda propia (API): é a “integração” que recebe os seus pedidos. Você mesmo a cria, sem credenciais:
- Abra Integraciones (Integrações) no menu, ou acesse app.wivoanalytics.com/u/0/#/marketplaces/accounts.
- Clique em Agregar (Adicionar) e, em Tiendas Ecommerce, escolha Tienda propia (API) · Beta. Não são pedidas credenciais: a fonte é criada ao escolhê-la.
- Copie o
source_idque aparece na tela.
Depois você continua a vê-lo em Integraciones, junto à sua Tienda propia (API). Cada conta tem apenas uma: se você a escolher de novo, a Wivo mostra a que você já tem.
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.
POST /orders
Recebe um lote de até 100 pedidos, em JSON (Content-Type: application/json).
O que você precisa saber antes de integrar
- A unidade é o pedido completo. Cada vez que você envia um pedido, ele traz todas as suas linhas, não apenas a que mudou. Reenviar o mesmo
order_idsubstitui o pedido inteiro: uma linha que não vem, desaparece. Por isso reenviar nunca duplica. purchase_datenão muda. É a data da compra e se mantém igual em cada reenvio. Se você a mover mais de 5 dias, o pedido aparece duas vezes.- Tudo ou nada. Se um único pedido do lote tiver um erro, nenhum entra. A resposta
422diz qual campo de qual pedido falhou, para que você corrija e reenvie o lote completo. 202quer dizer recebido, não inserido. Seus pedidos aparecem na app alguns minutos depois.- Valores em CLP, com IVA incluído, tal como o comprador os vê.
- O custo do produto não vai no pedido. Ele é carregado no Cadastro, como em qualquer outro canal (veja a receita).
Corpo
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
source_id | UUID | Sim | O source_id da sua Tienda propia (API). Tem que ser da mesma conta que a API Key |
orders | Lista | Sim | Entre 1 e 100 pedidos |
Campos de cada pedido
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
order_id | Texto (id) | Sim | ID do pedido na sua loja. Único por fonte e dentro do lote. Reenviá-lo substitui o pedido completo |
purchase_date | Data | Sim | Data da compra. Não muda entre envios |
last_update_date | Data | Sim | Última modificação do pedido. Não pode ser anterior a purchase_date |
currency | Texto | Sim | Sempre "CLP" |
payment_status | Texto | Sim | paid ou unpaid |
shipment_status | Texto | Não | Status do envio (veja status). Padrão noinformation |
shopper | Objeto | Não | O comprador: id (obrigatório dentro do objeto) e name |
shipping_cost | Valor | Não | O que custa para você enviar o pedido, não o que o comprador paga |
shipping_income | Valor | Não | O que o comprador pagou pelo frete, com IVA. Se não vier, é 0 |
payment_fee | Valor | Não | Comissão do gateway de pagamento (Webpay, Mercado Pago etc.) do pedido |
items | Lista | Sim | Todas as linhas do pedido, entre 1 e 200 |
Campos de cada linha
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
product_id | Texto (id) | Sim | ID do produto na sua loja. É o ID Producto com que ele aparece no Cadastro |
sku | Texto (id) | Não | SKU do produto |
name | Texto | Sim | Nome do produto |
variant | Objeto | Não | A variante: id (obrigatório dentro do objeto) e name |
brand | Texto | Não | Marca |
category | Texto | Não | Categoria |
quantity | Inteiro | Sim | Unidades, de 1 a 100.000 |
unit_price | Valor | Sim | Preço unitário de lista, com IVA, antes do desconto |
discount | Valor | Não | Desconto total da linha (não unitário), com IVA. Padrão 0. Não pode superar unit_price × quantity |
status | Texto | Sim | Status da linha: paid, canceled, returned ou pending |
Se você não enviar variant, brand, category ou shopper, a Wivo os mostra como “Sin información” (sem informação).
Status
Só são aceitos os status da Wivo. Se a sua loja usa outros nomes, converta-os antes de enviar: um status que não está na lista rejeita o lote.
items[].status, status da linha:
| Valor | Significado |
|---|---|
paid | Paga |
canceled | Cancelada |
returned | Devolvida |
pending | Pagamento pendente. A Wivo a conta como não concretizada, igual a uma cancelada, até você reenviar o pedido com a linha em paid |
payment_status, status de pagamento do pedido: paid (pago) ou unpaid (não pago).
shipment_status, status do envio do pedido:
| Valor | Significado |
|---|---|
noinformation | Sem informação (padrão) |
inpreparation | Em preparação |
intransit | Em trânsito |
delivered | Entregue |
returned | Devolvido |
returninprocess | Devolução em andamento |
inmediation | Em mediação |
faileddelivery | Entrega malsucedida |
notrequired | Não requer envio |
canceled | Cancelado |
Datas
As datas vão no formato RFC 3339 com offset explícito: 2026-09-24T15:30:00-03:00 ou 2026-09-24T18:30:00Z. Sem offset, são rejeitadas.
- Separador
Tentre data e hora (não um espaço) - Segundos obrigatórios; fração de segundo opcional (
15:30:00.123-03:00) - Offset
Zou±HH:MM. Não são aceitos-03nem-0300
Por que o offset? O Chile muda de horário duas vezes por ano, e uma hora local sem fuso é ambígua na mudança: pode mover um pedido de dia sem que ninguém perceba.
Além disso, purchase_date não pode estar mais de 24 horas no futuro nem ter mais de 2 anos.
Valores
Todos os valores vão em CLP, com IVA incluído, e não podem ser negativos.
- O total pago de uma linha é
unit_price × quantity − discount. shipping_costé o seu custo de frete;shipping_income, o que o comprador pagou pelo frete. O seu custo líquido de frete é a diferença. Não misture a receita emshipping_cost: isso inverteria o sentido do número na sua rentabilidade.payment_feeé a comissão do gateway. Se você não a enviar, a comissão fica como desconhecida.- A Wivo distribui
shipping_cost,shipping_incomeepayment_feeentre as linhas do pedido em proporção ao total de cada linha: a linha mais cara carrega mais.
Por exemplo, no pedido WEB-1001 do exemplo válido as linhas somam $23.980 e $8.990 (total $32.970). O frete de $3.990 fica em $2.902,04 para a primeira e $1.087,96 para a segunda.
Identificadores e textos
- Os ids (
order_id,product_id,sku,variant.id,shopper.id) têm até 64 caracteres e não podem ter aspas simples (') nem caracteres de controle. - Os textos (
name,brand,category,variant.name,shopper.name) têm até 255 caracteres e aceitam aspas simples: “María O’Higgins” é válido. - O
source_idé um UUID de 36 caracteres, com hifens. Tanto faz se vier em maiúsculas ou minúsculas. - Um
order_idnão pode se repetir dentro do mesmo lote.
Exemplos
cURL
curl -X POST "https://api.wivoanalytics.com/orders" \
-H "Ocp-Apim-Subscription-Key: SUA_API_KEY_AQUI" \
-H "Content-Type: application/json" \
-d '{
"source_id": "SEU_SOURCE_ID_AQUI",
"orders": [
{
"order_id": "WEB-1001",
"purchase_date": "2026-09-20T15:30:00-03:00",
"last_update_date": "2026-09-20T16:05:00-03:00",
"currency": "CLP",
"payment_status": "paid",
"shipment_status": "delivered",
"shipping_cost": 3990,
"shipping_income": 2990,
"payment_fee": 1250,
"items": [
{
"product_id": "P-10",
"sku": "POL-AZ-M",
"name": "Polera azul",
"quantity": 2,
"unit_price": 12990,
"discount": 2000,
"status": "paid"
}
]
}
]
}'
Se os seus dados tiverem aspas simples (por exemplo, um comprador “O’Higgins”), no terminal envie o corpo a partir de um arquivo, assim as aspas não cortam o comando:
curl -X POST "https://api.wivoanalytics.com/orders" \
-H "Ocp-Apim-Subscription-Key: SUA_API_KEY_AQUI" \
-H "Content-Type: application/json" \
--data @pedidos.json
Python (requests)
import requests
lote = {
"source_id": "SEU_SOURCE_ID_AQUI",
"orders": [
{
"order_id": "WEB-1001",
"purchase_date": "2026-09-20T15:30:00-03:00",
"last_update_date": "2026-09-20T16:05:00-03:00",
"currency": "CLP",
"payment_status": "paid",
"items": [
{"product_id": "P-10", "name": "Polera azul", "quantity": 2,
"unit_price": 12990, "discount": 2000, "status": "paid"},
],
}
],
}
response = requests.post(
"https://api.wivoanalytics.com/orders",
headers={"Ocp-Apim-Subscription-Key": "SUA_API_KEY_AQUI"},
json=lote,
timeout=30,
)
corpo = response.json()
if response.status_code == 202:
print(f"{corpo['accepted']} pedidos recebidos")
elif response.status_code == 422:
for erro in corpo["errors"]:
print(f"Pedido {erro['order_id']} · {erro['field']}: {erro['error']}")
else:
print(response.status_code, corpo)
Node.js (fetch)
const lote = {
source_id: "SEU_SOURCE_ID_AQUI",
orders: [
{
order_id: "WEB-1001",
purchase_date: "2026-09-20T15:30:00-03:00",
last_update_date: "2026-09-20T16:05:00-03:00",
currency: "CLP",
payment_status: "paid",
items: [
{ product_id: "P-10", name: "Polera azul", quantity: 2,
unit_price: 12990, discount: 2000, status: "paid" },
],
},
],
};
const response = await fetch("https://api.wivoanalytics.com/orders", {
method: "POST",
headers: {
"Ocp-Apim-Subscription-Key": "SUA_API_KEY_AQUI",
"Content-Type": "application/json",
},
body: JSON.stringify(lote),
});
const corpo = await response.json();
if (response.status === 202) {
console.log(`${corpo.accepted} pedidos recebidos`);
} else if (response.status === 422) {
for (const e of corpo.errors) console.error(`Pedido ${e.order_id} · ${e.field}: ${e.error}`);
} else {
console.error(response.status, corpo);
}
Exemplo válido completo
Dois pedidos: um pago e entregue, com todos os campos opcionais, e um não pago com sua única linha cancelada, só com os obrigatórios.
{
"source_id": "3f2b6c1e-8a4d-4c2e-9b7a-1d2e3f4a5b6c",
"orders": [
{
"order_id": "WEB-1001",
"purchase_date": "2026-09-20T15:30:00-03:00",
"last_update_date": "2026-09-20T16:05:00-03:00",
"currency": "CLP",
"payment_status": "paid",
"shipment_status": "delivered",
"shopper": {"id": "C-77", "name": "María O'Higgins"},
"shipping_cost": 3990,
"payment_fee": 1250,
"items": [
{"product_id": "P-10", "sku": "POL-AZ-M", "name": "Polera azul", "variant": {"id": "P-10-M", "name": "M"}, "brand": "Marca Propia", "category": "Poleras", "quantity": 2, "unit_price": 12990, "discount": 2000, "status": "paid"},
{"product_id": "P-22", "name": "Gorro de lana", "quantity": 1, "unit_price": 8990, "status": "paid"}
]
},
{
"order_id": "WEB-1002",
"purchase_date": "2026-09-21T10:00:00-03:00",
"last_update_date": "2026-09-22T09:00:00-03:00",
"currency": "CLP",
"payment_status": "unpaid",
"items": [
{"product_id": "P-10", "name": "Polera azul", "quantity": 1, "unit_price": 12990, "status": "canceled"}
]
}
]
}
Exemplo inválido
Cinco erros em um único pedido: data sem offset, um status de pagamento que não é da Wivo (pagado), quantidade 0, preço negativo e um campo que não existe no contrato (costo, que além disso é justamente o que não se envia).
{
"source_id": "3f2b6c1e-8a4d-4c2e-9b7a-1d2e3f4a5b6c",
"orders": [
{
"order_id": "WEB-2001",
"purchase_date": "2026-09-20T15:30:00",
"last_update_date": "2026-09-20T16:05:00-03:00",
"currency": "CLP",
"payment_status": "pagado",
"items": [
{"product_id": "P-10", "name": "Polera azul", "quantity": 0, "unit_price": -5, "status": "paid", "costo": 4000}
]
}
]
}
A resposta é um 422 com um erro por problema, e nenhum pedido entra:
{
"errors": [
{"index": 0, "order_id": "WEB-2001", "field": "/orders/0/purchase_date", "error": "Debe ser una fecha RFC 3339 con offset explícito, p. ej. 2026-09-24T15:30:00-03:00."},
{"index": 0, "order_id": "WEB-2001", "field": "/orders/0/payment_status", "error": "Debe ser uno de: paid, unpaid."},
{"index": 0, "order_id": "WEB-2001", "field": "/orders/0/items/0/costo", "error": "El campo 'costo' no existe en el contrato v1."},
{"index": 0, "order_id": "WEB-2001", "field": "/orders/0/items/0/quantity", "error": "Debe ser mayor o igual a 1."},
{"index": 0, "order_id": "WEB-2001", "field": "/orders/0/items/0/unit_price", "error": "Debe ser mayor o igual a 0."}
],
"correlation_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
JSON Schema v1
É o schema com o qual a API valida cada lote (JSON Schema draft 2020-12). Você pode usá-lo para validar seus lotes antes de enviá-los. As descrições internas do schema estão em espanhol. As regras que o schema não consegue expressar estão mais abaixo.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://api.wivoanalytics.com/schemas/orders-v1.schema.json",
"title": "Wivo — lote de órdenes v1 (Tienda propia API)",
"description": "Cuerpo de POST /orders (contrato v1).",
"type": "object",
"additionalProperties": false,
"required": ["source_id", "orders"],
"properties": {
"source_id": {
"description": "UUID (identifier) de la fuente 'Tienda propia (API)' del tenant. Se verifica contra el tenant de la API key.",
"type": "string",
"format": "uuid"
},
"orders": {
"type": "array",
"minItems": 1,
"maxItems": 100,
"items": { "$ref": "#/$defs/order" }
}
},
"$defs": {
"text": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"pattern": "^[^\\u0000-\\u001f]*$"
},
"id": {
"type": "string",
"minLength": 1,
"maxLength": 64,
"description": "Sin caracteres de control ni comilla simple.",
"pattern": "^[^\\u0000-\\u001f']*$"
},
"amount": {
"type": "number",
"minimum": 0,
"maximum": 100000000000
},
"datetime": {
"description": "ISO 8601 / RFC 3339 CON offset explícito (p. ej. 2026-09-24T15:30:00-03:00). Sin offset se rechaza.",
"type": "string",
"format": "date-time"
},
"order": {
"type": "object",
"additionalProperties": false,
"required": ["order_id", "purchase_date", "last_update_date", "currency", "payment_status", "items"],
"properties": {
"order_id": {
"$ref": "#/$defs/id",
"description": "ID de la orden en la tienda. Único por fuente. Reenviar el mismo order_id REEMPLAZA la orden completa."
},
"purchase_date": {
"$ref": "#/$defs/datetime",
"description": "Fecha de compra. INMUTABLE: si cambia más de 5 días respecto de lo ya enviado, la orden se duplica."
},
"last_update_date": { "$ref": "#/$defs/datetime" },
"currency": { "const": "CLP" },
"payment_status": { "enum": ["paid", "unpaid"] },
"shipment_status": {
"enum": ["noinformation", "inpreparation", "intransit", "delivered", "returned", "returninprocess", "inmediation", "faileddelivery", "notrequired", "canceled"],
"default": "noinformation"
},
"shopper": {
"type": "object",
"additionalProperties": false,
"required": ["id"],
"properties": {
"id": { "$ref": "#/$defs/id" },
"name": { "$ref": "#/$defs/text" }
}
},
"shipping_cost": {
"$ref": "#/$defs/amount",
"description": "Lo que le cuesta AL SELLER despachar la orden (no lo que paga el comprador). Wivo lo prorratea entre las líneas por su total."
},
"shipping_income": {
"$ref": "#/$defs/amount",
"description": "Lo que PAGÓ EL COMPRADOR por el despacho, IVA incluido. Va a shipping_import, prorrateado entre las líneas por su total. El costo neto de despacho del seller = shipping_cost − shipping_income."
},
"payment_fee": {
"$ref": "#/$defs/amount",
"description": "Comisión de la pasarela de pago de la orden (Webpay, Mercado Pago, etc.). Va a market_fee, prorrateada entre las líneas por su total."
},
"items": {
"type": "array",
"minItems": 1,
"maxItems": 200,
"description": "TODAS las líneas de la orden, siempre. Una actualización trae la orden completa.",
"items": { "$ref": "#/$defs/item" }
}
}
},
"item": {
"type": "object",
"additionalProperties": false,
"required": ["product_id", "name", "quantity", "unit_price", "status"],
"properties": {
"product_id": {
"$ref": "#/$defs/id",
"description": "ID del producto en la tienda. Es el 'ID Producto' con el que aparece en el Maestro de Wivo."
},
"sku": { "$ref": "#/$defs/id" },
"name": { "$ref": "#/$defs/text" },
"variant": {
"type": "object",
"additionalProperties": false,
"required": ["id"],
"properties": {
"id": { "$ref": "#/$defs/id" },
"name": { "$ref": "#/$defs/text" }
}
},
"brand": { "$ref": "#/$defs/text" },
"category": { "$ref": "#/$defs/text" },
"quantity": { "type": "integer", "minimum": 1, "maximum": 100000 },
"unit_price": {
"$ref": "#/$defs/amount",
"description": "Precio unitario de lista, IVA incluido, ANTES del descuento."
},
"discount": {
"$ref": "#/$defs/amount",
"default": 0,
"description": "Descuento TOTAL de la línea (no unitario), IVA incluido. No puede superar unit_price × quantity."
},
"status": { "enum": ["paid", "canceled", "returned", "pending"] }
}
}
}
}
Regras que o schema não expressa
A API também rejeita com 422:
- Um
order_idrepetido dentro do mesmo lote. - Um
discountmaior queunit_price × quantity. - Uma
purchase_datemais de 24 horas no futuro ou com mais de 2 anos. - Uma
last_update_dateanterior apurchase_date. - Datas e UUIDs fora do formato estrito: os
formatdate-timeeuuidsão validados de verdade. Data com separadorT(não espaço), segundos obrigatórios, fração opcional e offsetZou±HH:MM; oTe oZtambém são aceitos em minúscula. UUID canônico de 36 caracteres, sem prefixourn:uuid:nem chaves, em maiúsculas ou minúsculas.
Se você valida com uma biblioteca de JSON Schema, ative a validação de formatos (em Python, FormatChecker; em Node, ajv-formats): sem ela, uma data sem offset passaria na sua validação e a API a rejeitaria.
Respostas do servidor
Toda resposta da API traz um correlation_id. Guarde-o: é o que nos permite rastrear um envio se você nos escrever.
| Código | Significado | Tentar de novo |
|---|---|---|
202 | Lote recebido. Os pedidos aparecem na app alguns minutos depois | Não |
400 | O corpo está vazio ou não é um JSON válido | Não, corrija o corpo |
401 | API Key ausente ou inválida | Não |
403 | Conta sem plano Pro, assinatura revogada, ou um source_id que não é uma Tienda propia (API) ativa da sua conta. Também quando se esgota o limite diário | Não |
413 | Mais de 100 pedidos ou mais de 1 MB no lote | Não: divida o lote |
422 | Lote inválido. Nenhum pedido entrou | Não: corrija e reenvie o lote completo |
429 | Você superou as 30 solicitações por minuto | Sim, depois do que indicar o header Retry-After |
503 | Não conseguimos receber o lote neste momento (retryable: true) | Sim, o mesmo lote |
202 Accepted
{
"accepted": 1,
"order_ids": ["WEB-1001"],
"dag_run_id": "tpapi__3f2b6c1e-8a4d-4c2e-9b7a-1d2e3f4a5b6c__f5610004e788a9df4b644366ee7112b4ffd54eb640d2d2eed526b5e0fd874f31",
"duplicate": false,
"correlation_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
| Campo | Descrição |
|---|---|
accepted | Quantidade de pedidos recebidos |
order_ids | Os order_id recebidos, na ordem do lote |
dag_run_id | Identificador do processamento do lote. Cite-o se nos escrever sobre um envio |
duplicate | true se já tínhamos recebido exatamente este mesmo lote: ele não é processado duas vezes |
202 quer dizer que recebemos o lote, não que os pedidos já estejam nos seus relatórios: eles aparecem na app alguns minutos depois.
422 Unprocessable Entity
Cada erro traz:
| Campo | Descrição |
|---|---|
index | Posição do pedido em orders (a partir de 0). null se o erro é do lote, por exemplo em /source_id |
order_id | O order_id desse pedido, ou null se não veio ou não é válido |
field | JSON Pointer para o campo com erro, por exemplo /orders/0/items/1/unit_price. Um campo que sobra aponta para esse campo: /orders/0/items/0/costo |
error | O que está errado (em espanhol) |
A lista traz no máximo 100 erros. Se havia mais, a resposta acrescenta "truncated": true. O exemplo completo está em Exemplo inválido.
413 Payload Too Large
{
"error": "El lote trae 101 órdenes y el máximo por request es 100. Divide el envío en lotes de hasta 100 órdenes.",
"max_orders": 100,
"correlation_id": "a1b2c3d4-..."
}
Se o lote pesar mais de 1 MB, a resposta traz "max_bytes": 1048576 em vez de max_orders. Nos dois casos, reenviar o mesmo lote não vai funcionar: divida-o.
403 Forbidden
{
"error": "La fuente '3f2b6c1e-8a4d-4c2e-9b7a-1d2e3f4a5b6c' no es una fuente 'Tienda propia (API)' activa de tu cuenta.",
"correlation_id": "a1b2c3d4-..."
}
503 Service Unavailable
{
"error": "No pudimos recibir el lote en este momento. Reintenta el mismo lote: si el contenido es idéntico, Wivo reconoce el reintento y no lo procesa dos veces.",
"retryable": true,
"correlation_id": "a1b2c3d4-..."
}
Limites de uso
- 100 pedidos por solicitação, e até 200 linhas por pedido
- 1 MB por solicitação (1.048.576 bytes)
- 30 solicitações por minuto por API Key
- 5.000 solicitações por dia
Passar de 100 pedidos ou de 1 MB retorna 413; de 30 solicitações por minuto, 429; e esgotar as 5.000 do dia, 403 até a cota ser renovada.
Com lotes de 100 pedidos, 30 solicitações por minuto são 3.000 pedidos por minuto. Enviar um lote a cada 2 segundos mantém você abaixo do limite.
Novas tentativas e idempotência
Reenviar é seguro. Há duas garantias, e juntas cobrem qualquer nova tentativa:
- O mesmo lote não é processado duas vezes. Se você reenviar exatamente o mesmo conteúdo (mesmo que mude a ordem das chaves ou os espaços), a API responde
202com"duplicate": truee o mesmodag_run_id. - Reenviar um pedido o substitui. Se o conteúdo mudou, é um lote novo, e cada
order_idsubstitui a sua versão anterior. Nunca duplica.
O que fazer de acordo com a resposta:
| Resposta | O que fazer |
|---|---|
503 com retryable: true | Tente de novo o mesmo lote, com espera crescente (2, 4, 8… segundos) |
429 | Espere os segundos do header Retry-After e tente de novo |
| Sem resposta (timeout, queda de rede) | Tente de novo o mesmo lote: se ele já tinha chegado, responde duplicate: true |
400, 401, 403, 413, 422 | Não tente de novo igual: corrija primeiro. Repetir o mesmo lote dá o mesmo erro |
Receitas
Enviar muitos pedidos, com novas tentativas
Divida seus pedidos em lotes de 100, envie-os em um ritmo que respeite o limite por minuto e tente de novo apenas o que se resolve tentando de novo.
import time
import requests
URL = "https://api.wivoanalytics.com/orders"
HEADERS = {"Ocp-Apim-Subscription-Key": "SUA_API_KEY_AQUI"}
SOURCE_ID = "SEU_SOURCE_ID_AQUI"
def enviar_lote(pedidos, tentativas=5):
lote = {"source_id": SOURCE_ID, "orders": pedidos}
espera = 2
for tentativa in range(tentativas):
try:
response = requests.post(URL, headers=HEADERS, json=lote, timeout=30)
except requests.RequestException:
response = None # sem resposta: reenviar o mesmo lote é seguro
if response is not None:
if response.status_code == 202:
return response.json()
if response.status_code == 429:
espera = int(response.headers.get("Retry-After", espera))
elif response.status_code != 503:
# 400, 401, 403, 413 e 422 não se resolvem tentando de novo
raise RuntimeError(f"Lote rejeitado ({response.status_code}): {response.text}")
time.sleep(espera)
espera = min(espera * 2, 60)
raise RuntimeError("Não foi possível enviar o lote: tente mais tarde com o mesmo conteúdo")
pedidos = [...] # os pedidos da sua loja, cada um completo
for i in range(0, len(pedidos), 100):
resultado = enviar_lote(pedidos[i:i + 100])
print(resultado["accepted"], "pedidos recebidos", "(já estavam)" if resultado["duplicate"] else "")
time.sleep(2) # 30 solicitações por minuto
Se um lote de 100 pedidos com muitas linhas pesar mais de 1 MB, a API responde 413 com max_bytes: use lotes menores.
Atualizar um pedido: cancelamento ou devolução
Reenvie o pedido completo, com o mesmo order_id e a mesma purchase_date, as linhas no novo status e uma last_update_date nova. Por exemplo, se o comprador devolveu o gorro do pedido WEB-1001:
{
"source_id": "SEU_SOURCE_ID_AQUI",
"orders": [
{
"order_id": "WEB-1001",
"purchase_date": "2026-09-20T15:30:00-03:00",
"last_update_date": "2026-09-25T11:00:00-03:00",
"currency": "CLP",
"payment_status": "paid",
"shipment_status": "delivered",
"shipping_cost": 3990,
"payment_fee": 1250,
"items": [
{"product_id": "P-10", "name": "Polera azul", "quantity": 2, "unit_price": 12990, "discount": 2000, "status": "paid"},
{"product_id": "P-22", "name": "Gorro de lana", "quantity": 1, "unit_price": 8990, "status": "returned"}
]
}
]
}
A camiseta (Polera azul) vai igual, mesmo sem ter mudado: se você a omitir, essa linha desaparece da Wivo.
Carregar o custo dos seus produtos
O custo não vai no pedido. Os produtos dos seus pedidos aparecem no Cadastro com Marketplace “Tienda propia”, e ali você carrega o custo como em qualquer outro canal: com a planilha do Cadastro na app, ou pela API.
Para fazer isso pela API, leia os produtos da sua loja que ainda não têm custo com o Cadastro de produtos pela API, filtrando pelo seu source_id (é o ID Cuenta dos seus produtos):
curl "https://api.wivoanalytics.com/master/products?source_id=SEU_SOURCE_ID_AQUI&withoutCost=true" \
-H "Ocp-Apim-Subscription-Key: SUA_API_KEY_AQUI"
E devolva os custos com a carga de custos pela API. O product_id que você envia em cada linha é o ID Producto do Cadastro.
Perguntas frequentes
Quanto tempo meus pedidos demoram para aparecer na Wivo?
Alguns minutos depois do 202. O 202 confirma que recebemos o lote; o processamento vem depois.
Como sei que meus pedidos estão chegando? Em Integraciones, a sua Tienda propia (API) mostra quando chegou o último pedido. Se ainda não chegou nenhum, ela indica isso.
O que acontece se recebi um 202 mas os pedidos não aparecem?
Nesta versão não existe um endpoint para consultar o status de um lote. Se depois de um tempo você não os vir, escreva para nós pelo chat da app ou para soporte@wivoanalytics.com com o correlation_id e o dag_run_id da resposta, e verificamos.
O que acontece se eu enviar o mesmo lote duas vezes?
Nada de ruim. A API responde 202 com "duplicate": true e o lote não é processado duas vezes.
Posso enviar só a linha que mudou?
Não. Cada envio traz o pedido completo, porque reenviar um order_id substitui o pedido inteiro: uma linha que não vem, desaparece.
Posso corrigir a data de compra de um pedido?
Evite: purchase_date tem que ser sempre a mesma. Se você a mover mais de 5 dias, o pedido aparece duas vezes.
Posso apagar um pedido?
Não nesta versão. Reenviá-lo com as linhas em canceled muda o seu status, mas não o apaga.
Posso enviar o custo dos produtos no pedido?
Não, e um campo costo rejeita o lote. O custo fica no Cadastro, como em todos os seus canais: assim há uma única fonte de verdade. Veja Carregar o custo dos seus produtos.
Por que o meu order_id com aspas simples dá erro?
Os ids não aceitam aspas simples, para que o order_id fique na Wivo exatamente igual ao da sua loja e você possa cruzá-los. Os textos, como o nome do comprador, aceitam.
Posso enviar pedidos antigos?
Sim, com purchase_date de até 2 anos atrás, em lotes de 100 e respeitando os limites de uso. Não há uma carga histórica em massa separada.
Posso enviar pedidos em outra moeda ou de outro país? Por enquanto não: durante a beta a API é apenas para contas do Chile e valores em CLP.
Este recurso consome minha cota da API de dados? Não. Está incluído no plano Pro, não precisa do add-on e tem o seu próprio limite de 30 solicitações por minuto.