Ver demonstração

API do Mercado Livre: o que ela devolve de dado de venda (e o que não devolve)

O /orders do Mercado Livre traz a comissão em sale_fee, mas o frete do vendedor exige /shipments/{id}/costs e a devolução vive em outro recurso.

· 10 min de leitura · Gabriel Sorato

A API do Mercado Livre devolve o pedido em GET /orders/$ORDER_ID com preço, quantidade e a comissão de cada item no campo sale_fee, mas não devolve o custo do frete do vendedor: esse exige uma segunda chamada, a /shipments/$SHIPMENT_ID/costs. A devolução fica em outro recurso, o /post-purchase, e os pedidos ficam salvos por até 12 meses (documentação de Orders, atualizada em 21/09/2026 e lida em 3 de novembro de 2026).

Em dois posts anteriores desta série eu disse que não tinha conseguido ler essa documentação. Desta vez li. Tudo abaixo tem o nome do campo como está na doc, com o link e a data de atualização que a página mostra.

A margem da venda não está no pedido. No Mercado Livre, receita, comissão, frete, desconto e devolução moram em recursos diferentes. Quem soma só o /orders mede faturamento bruto e chama de venda.

Qual é o sintoma?

O relatório de vendas do Mercado Livre não fecha com o repasse, e a diferença não cabe na comissão que alguém tem de cabeça. Ou a contagem de pedidos da integração não bate com a de “vendas” do painel do vendedor, e os dois números parecem certos.

Os dois vêm do mesmo erro: a integração leu um recurso só e o tratou como a venda inteira.

O que o /orders devolve, campo por campo?

O pedido responde em GET https://api.mercadolibre.com/orders/$ORDER_ID. A documentação lista estes campos de resposta, entre outros (Orders):

CampoO que a doc dizO que isso significa para o número
total_amount"valor total da order"É o valor do produto. Frete do vendedor não entra
order_items[].unit_pricepreço unitário, "após aplicar os descontos"Já é líquido de desconto
order_items[].gross_price(unit_price + discounts.full) × quantityPreço cheio. "Pode não estar presente em pedidos antigos"
order_items[].sale_fee"comissão de vendas"Calculada "no momento da acreditação do pagamento"
shipping.id"ID do envio para esta order"Só o ID. O custo está em outro recurso
buyer.idinformações do compradorNo exemplo da doc, só o ID numérico
context.channelproximity | mp-channel | marketplaceCanal de venda do Mercado Livre, não origem de tráfego
cancel_detailgroup, code, requested_by, dateQuem cancelou e por quê

Duas notas mudam a extração. A primeira: o recurso pode responder 206 Partial Content, com o cabeçalho X-Content-Missing listando os campos vazios; o exemplo publicado mostra buyer e feedback faltando. Quem aceita essa resposta sem ler o cabeçalho grava pedido com comprador nulo.

A segunda: context.channel não responde “de onde veio a venda”. Entre os campos documentados do pedido não há nenhum de origem de tráfego, campanha ou clique. É o mesmo desenho que descrevi em marketplace como buraco negro de dados: o canal entrega volume e não entrega procedência.

O que precisa de mais de uma chamada?

Quase tudo o que transforma faturamento em margem. A tabela é o mapa mínimo de recursos para fechar uma venda:

DadoRecursoCampo
Itens do carrinho/packs/$PACK_IDpedidos do pack (relação 1 para N)
Frete pago pelo vendedor/shipments/$SHIPMENT_ID/costssenders[].cost, gross_amount
Envios e devoluções de um pedido/orders/$ORDER_ID/shipmentstype: forward, return
Descontos e quem os pagou/orders/$ORDER_ID/discountsamounts.total, amounts.seller
Documento fiscal do comprador/orders/billing-info/{site_id}/{billing_info_id}doc_type, doc_number
Devolução e dinheiro/post-purchase/v2/claims/$CLAIM_ID/returnsstatus_money, refund_at
Cobranças do mês/billing/integration/periods/key/{key}/summary/detailscharges[].type, amount

Carrinho. A doc de Packs (atualizada em 29/12/2025) diz que o pack “torna-se um componente obrigatório em todas as compras, pois todos os pedidos estarão associados a um pack_id”, com relação de 1 para N entre pack e pedidos. Contar order_id conta pedido, não compra. É um bom primeiro suspeito quando a contagem da integração não bate com a do painel.

Frete. O recurso /shipments/$SHIPMENT_ID/costs (atualizado em 18/09/2026) devolve gross_amount, descrito como “o custo total do shipment sem nenhum tipo de desconto”, e a lista senders com “os valores pagos pelo vendedor”. A mesma doc avisa que um envio “poderá conter produtos de diferentes vendedores”. Para chegar ao total com frete, a doc de Orders publica a fórmula total_amount_with_shipping = total_amount + taxes.amount + lead_time.cost, e o lead_time.cost só existe em /shipments.

Comprador. O documento fiscal saiu do pedido. O fluxo atual, segundo a FAQ de Billing info (atualizada em 14/08/2026), é ler buyer.billing_info.id no pedido e consultar /orders/billing-info/{site_id}/{billing_info_id}; a FAQ registra que o endpoint antigo, /orders/{order_id}/billing_info, responde 404. A mesma FAQ avisa que doc_type e doc_number podem vir nulos enquanto o documento fiscal está em PROCESSING, e que o endereço fiscal “pode ser diferente do endereço de entrega”, que mora em /shipments.

O pedido cancelado aparece?

Depende de como você pergunta, e a documentação tem uma armadilha de status.

A busca é GET /orders/search, que “não realiza nenhuma ação se não é seguido por um filtro”. Os filtros incluem order.status, order.date_created.from, order.date_closed.from e order.date_last_updated.from. A doc traz dois avisos que pesam na extração (Orders):

  • “os pedidos criados são salvos por até 12 meses e se você pesquisar como vendedor, continuará a filtrar os pedidos cancelados”;
  • o filtro de data “usa até a hora e descarta a informação dos minutos, segundos e milissegundos”.

A frase sobre cancelados é ambígua: não deixa claro se o cancelado some do resultado. Teste na sua conta. Se ele some, um pedido que você gravou como pago e foi cancelado depois nunca reaparece na busca para corrigir o seu registro.

A armadilha de status é mais séria. A lista oficial tem confirmed, payment_required, payment_in_process, partially_paid, paid, partially_refunded, pending_cancel, cancelled e invalid. E a doc registra: “uma order não concretizada pelo vendedor será visualizada como ‘Cancelada’ por front e por api terá ‘status = confirmed’”. O mesmo valor, confirmed, é o status inicial de um pedido ainda não pago. Um filtro que exclui só cancelled deixa passar venda que o painel mostra como cancelada.

É a mesma família de erro que vi no pedido cancelado dos ERPs: o cancelado volta pelo mesmo endereço, com cara de venda.

Onde fica a devolução?

Fora do pedido. A doc de Devoluções manda escutar o feed de reclamações, ler related_entities em /claims/$CLAIM_ID e, se houver return, consultar /post-purchase/v2/claims/$CLAIM_ID/returns.

Três campos interessam a quem fecha o mês. status_money admite retained (“dinheiro na conta mas retido”), refunded e available. refund_at diz quando o dinheiro volta ao comprador: shipped, delivered (“3 dias após o vendedor receber o envio”) ou n/a para casos low cost. O subtype separa return_total, return_partial e low_cost.

Para listar as reclamações, a doc de Reclamações documenta GET /post-purchase/v1/claims/search, que exige pelo menos um filtro e aceita stage (claim, dispute, recontact, stale, none). No pedido, o rastro é o status partially_refunded e o envio do tipo return em /orders/$ORDER_ID/shipments.

E as taxas do mês?

Ficam nos relatórios de faturamento, que a própria documentação pede para não usar como fonte de venda. A página de boas práticas dos relatórios de faturamento diz que os recursos são “estritamente destinados a operações de Pós-Venda” e “não devem ser utilizados como fonte de dados primária para gestão de vendas”.

O resumo /billing/integration/periods/key/{key}/summary/details traz as cobranças por type; o exemplo publicado mostra CV (“Cobrança por venda”), CXD (“Cobrança por Mercado Envios”) e PADS (“Campanhas de publicidade - Product Ads”). A regra de conciliação está escrita: a soma de detail_amount por detail_sub_type no detalhe “deve ser igual ao amount para o mesmo type” no resumo. A chave do período é sempre o primeiro dia do mês, YYYY-MM-01.

Como diagnosticar na sua integração?

Rode estas checagens num mês fechado:

VerificaçãoOnde olharO que indica divergência
Pedidos por packpack_id no /ordersContagem de pedidos maior que a de vendas do painel
Status confirmed antigoorder.status=confirmed com date_created de semanas atrásVenda não concretizada contada como pendente ou como venda
Comissão somadasoma de sale_fee × tipo CV do resumoDiferença indica pedido faltando ou estorno de comissão
Frete do vendedorsoma de senders[].cost × tipo CXDFrete tratado como zero no relatório
Respostas parciaislog do cabeçalho X-Content-MissingPedidos gravados com comprador nulo
Devoluçãostatus_money em /returnsReceita contada com dinheiro retained ou refunded

Como corrigir?

Escreva a definição antes de escrever a query. “Venda do Mercado Livre” pode ser total_amount dos pedidos paid, ou isso menos sale_fee, menos senders[].cost, menos amounts.seller dos descontos, menos o que voltou com status_money = refunded. São números diferentes e todos defensáveis. O erro é não ter decidido qual. Uma definição escrita e versionada, consultada sempre do mesmo jeito, é o que chamamos de camada semântica.

Na extração, quatro regras práticas tiradas da própria doc:

  1. Puxe por order.date_last_updated, não por data de criação. É o filtro que pega o pedido que mudou de status depois de carregado. Como a busca descarta minutos, sobreponha a janela em pelo menos uma hora.
  2. Guarde tudo. Pedido com mais de 12 meses sai do alcance da API, e o histórico passa a existir só se você o salvou.
  3. Renove o token antes de expirar. A doc de autenticação informa expires_in: 21600 (6 horas). O refresh_token é “de utilização única” e expira em 6 meses. Rotina noturna que perde o refresh para de carregar em silêncio.
  4. Não paralelize os relatórios de faturamento. A doc recomenda “uma chamada por seller, uma vez ao dia”, paginação por from_id (o offset para em 10.000) e trata o 429 desses endpoints como “bloqueio preventivo por IP”.

O limite geral não tem número publicado: a FAQ de rate limit (atualizada em 05/05/2026) diz que o controle é “por Client ID (aplicação) na maioria dos casos e por endpoint”.

A doc de Orders também avisa que a “vista atual” de /orders/$ORDER_ID/shipments “será descontinuada a partir do final de setembro de 2026”. A vista nova sempre devolve um array; integração que lia um objeto único “falhará automaticamente”. Se a sua carga de frete parou em outubro, comece por aí.

Quando isso não tem conserto?

Origem da venda. Nenhum campo documentado do pedido diz de qual anúncio, busca ou campanha a venda veio. Dá para saber quanto você pagou de Product Ads no mês pelo tipo PADS; não dá para ligar uma venda específica a um clique pela API de pedidos.

Cliente único entre canais. O comprador vem como buyer.id interno, e o documento fiscal pode estar nulo. Cruzar a mesma pessoa entre o site e o Mercado Livre continua sem chave confiável, como mostrei em deduplicar venda entre site e marketplace.

Histórico anterior a 12 meses. Se ninguém salvou, a API de pedidos não devolve mais.

Nota fiscal emitida fora do Mercado Livre. Os recursos de nota fiscal (/users/$USER_ID/invoices/orders/$ORDER_ID e afins) cobrem operações “que utilizam nosso emissor de notas fiscais”, segundo a doc de notas fiscais (atualizada em 19/10/2026). Quem emite pelo próprio ERP busca a nota no ERP.

Quando a Precisian não é a resposta: se você vende só no Mercado Livre e o faturamento mensal já fecha com o financeiro, uma plataforma de dados é custo sem problema para resolver. O problema aparece quando o Mercado Livre precisa conversar com o site, o ERP e a mídia. Conectamos qualquer fonte que tenha API aberta.

O que este artigo não cobre?

Não cobre o Mercado Pago. O dinheiro liberado e a data de liberação são domínio da API do Mercado Pago (/v1/payments/{id}, citada na doc de Packs). Não li essa documentação para este texto.

Não traz limite numérico de requisições. Não está publicado, e não repito número de fórum.

Registro de método: o portal developers.mercadolivre.com.br responde 403 a curl direto, então li cada página por um leitor que renderiza o HTML e conferi os nomes de campo no JSON de exemplo da própria página. As páginas de autenticação, de reclamações e de boas práticas de faturamento não exibiram data de atualização; para elas vale a data da leitura, 3 de novembro de 2026.

Se o faturamento do Mercado Livre na sua planilha não fecha com o repasse, o primeiro passo é medir a diferença entre total_amount e o que sobra depois de comissão, frete e devolução. Vale uma conversa sobre o seu caso, sem compromisso de contrato, mas sem promessa de resposta em 30 minutos também.