Orçamento no Mercos pela API: o caminho híbrido
Vitor Ayres (abre em nova aba)
O post sobre a API do Mercos registra que a API não cria orçamento: todo pedido criado pela rota de pedidos nasce com o status Gerado, e as rotas de pedido recusam o campo status. Para um app que precisava deixar um orçamento pronto para o vendedor revisar, isso era o problema inteiro.
Este texto registra o que mais tentamos pela API, o que o suporte respondeu, como a tela do Mercos cria um orçamento, e o caminho híbrido que funcionou: o rascunho nasce na tela e a API oficial o preenche. Tudo foi medido no sandbox do Mercos, em 22 e 25 de setembro de 2026.
Resumo
- Testamos 39 nomes de campo no
POSTe 15 noPUT, nas versões 1 e 2. Todos recusados. - 9 rotas inventadas deram 404, igual a uma rota inexistente. O
PATCHdeu 405, e parâmetros na URL foram ignorados. - Um truque com uma chave inventada mostra quais campos a API aceita sem criar nada.
- O suporte confirmou que é limitação do sistema, não bug. Chamado 561366, 22 de setembro.
- A tela cria o orçamento num
GETe o converte em pedido numPOSTsem corpo. As duas rotas exigem login. - Caminho híbrido: a tela cria o rascunho, o
PUTda API oficial preenche. O status continua 1. - Riscos: a rota não tem documentação, cada abertura cria um rascunho, e a conversão por código não foi testada.
O que mais tentamos pela API
A hipótese era um campo ou uma rota não documentada. Em 25 de setembro, numa rodada de scripts com 6 segundos entre as chamadas:
| Tentativa | Resultado |
|---|---|
39 nomes de campo no POST, v1 e v2 |
422, todos listados como inválidos |
15 nomes de campo no PUT, v1 e v2 |
422, todos listados como inválidos |
| 7 rotas de ação inventadas, como “reabrir” e “orçamento” | 404 com página HTML, igual a 2 rotas de controle que não existem |
GET /v1/orcamentos e GET /v2/orcamentos |
404 com página HTML |
PATCH /v2/pedidos/{id} |
405 |
?status=1&orcamento=1&rascunho=1 na URL do POST |
ignorado, o pedido nasceu com status 2 |
POST sem data_emissao ou com null |
422, o campo é obrigatório e só aceita texto |
PUT num pedido cancelado |
200, e o pedido continua cancelado |
Os 39 nomes eram os campos que o GET devolve, como status_b2b e pedido_origem_id, mais palpites, como orcamento, rascunho, gerar_pedido, draft e quote. A rota de status, POST /v1/pedidos/{id}/status, só troca o status personalizado, que é outro campo. E um tipo de pedido chamado “Orçamento”, testado em 21 de setembro, também produziu um pedido com status 2.
Um detalhe que a listagem mostrou: a conta tinha 5 orçamentos com status 1, 4 deles sem itens. A explicação está mais abaixo.
Como achar campo não documentado sem criar nada
Mande os candidatos junto com uma chave que com certeza não existe. Essa chave garante um 422, então nada é criado. A v2 lista todos os atributos inválidos numa mensagem só, e a v1 dá um erro por chave. Qualquer candidato que não apareça na lista de inválidos é um campo aceito.
Foi assim que os 39 nomes foram testados em duas requisições. De brinde, a v1 mostrou que os itens exigem preco_bruto e recusam preco_tabela.
O que o suporte respondeu
Perguntamos pelo chat em 21 de setembro, fora do horário. Em 22 de setembro, de manhã, a primeira resposta explicou os status padrão, Orçamento, Concluído e Cancelado, e que um status personalizado só entra depois de o pedido ser concluído. Pedimos para confirmar se era bug ou limite. À tarde, a resposta: “essa é uma limitação atual do sistema e não se trata de um bug”. O time de integração estava em cópia e não tinha respondido até 25 de setembro.
O “Concluído” do suporte é o status 2 da API, que a documentação chama de Gerado. O suporte respondeu nos termos da tela.
Como a tela cria o orçamento
Capturamos as chamadas da tela do Mercos em 25 de setembro, com uma extensão do Chrome, porque o leitor de rede do navegador não mostra as requisições do próprio Mercos. A sequência:
- Abrir “Criar pedido / orçamento” faz um
GETque já cria o orçamento no servidor e redireciona para a página dele, com o id no endereço. - Cliente, itens e condição de pagamento vão em formulários comuns do Django, um
POSTcada. - “Gerar pedido” é um
POSTsem corpo, que responde com o endereço de redirecionamento. O botão fica desabilitado até o orçamento ter condição de pagamento.
Como o GET cria o registro, cada abertura da tela deixa um rascunho. É por isso que a conta tinha orçamentos sem cliente e sem itens.
Com só os dois tokens da integração, as três rotas da tela que testamos responderam 302 para a página de login. Elas exigem a sessão de um usuário. O formulário de login tem só usuário e senha, e o HTML não cita captcha, o que não descarta verificação em duas etapas nem bloqueio depois de erros.
O caminho híbrido
Se a tela cria com status 1 e a API cria com status 2, e o PUT não mexe no status, basta trocar quem cria.
Testado em 25 de setembro, num rascunho recém-criado na tela, sem cliente, sem itens e sem condição de pagamento:
| Passo | Resultado |
|---|---|
PUT /v2/pedidos/{id} pela API oficial, com cliente, condição e um item de 2 unidades |
200 |
Leitura depois do PUT |
status 1, cliente preenchido, condição “30 / 60 / 90”, um item, total R$ 536,90 |
Uma segunda rodada, no mesmo dia e noutro rascunho, mediu o que o app precisava saber:
- Um
PUTsem condição de pagamento é aceito num rascunho, ao contrário doPOST. - Um
PUTcom um item num rascunho que já tem quatro acrescenta o quinto. Os quatro ficam intactos, com os mesmos ids. - O
PUTmoveultima_alteracao, então a listagem por data encontra o rascunho antes e depois. - Desconto com 7 casas decimais dá 422. Com 4 casas é aceito, e o preço líquido volta com 5 casas, sem arredondar ao centavo.
- O Mercos grava o preço que mandamos sem conferir pelo cadastro: 138 num produto de 137 ficou 138. Catálogo velho vira preço errado no orçamento.
- A tela recarregada mostra os itens. Editar na tela sem recarregar não foi testado.
- Um
PUTleva de 0,5 a 0,7 segundo. Ler, gravar e ler de novo levou 19 segundos no sandbox, por causa dos 429 entre as chamadas.
No app, a escolha foi deixar a criação com a pessoa. Ela abre o orçamento na tela do Mercos, como já fazia, uma extensão lê o id no endereço da página e manda a lista de itens ao nosso servidor, e o servidor preenche o rascunho pelo PUT da API, com os tokens da integração e o mercos-sdk. Quando o preenchimento vem de um assistente de IA, o mesmo PUT passa pelo servidor MCP do app, com uma prévia obrigatória antes de gravar. Nenhuma senha guardada, o orçamento fica no nome de quem o abriu, e a escrita passa só pela API oficial. A alternativa, um usuário só para a integração fazendo login por código, ficou guardada para o dia em que o orçamento precisar nascer sem ninguém com o Mercos aberto.
Riscos e o que não medimos
A rota que cria o rascunho não tem documentação e pode mudar em qualquer deploy do Mercos. Os termos de uso não foram lidos com esse uso em mente. Por isso o app não a chama: quem a chama é a pessoa, pela tela.
O GET de criação não é idempotente. Uma chamada repetida por engano deixou um rascunho vazio na conta. Se o preenchimento falhar, o rascunho precisa ser cancelado.
Não testamos: se criador_id no PUT troca o vendedor; gerar o pedido por código, que provavelmente exige o token CSRF; quanto dura a sessão e se a conta pode exigir verificação em duas etapas; um PUT num rascunho de outra representada, que o sandbox não permite medir; e nada disso em produção, onde a leitura por id é bloqueada e o app encontra o pedido pela listagem.
Como verificamos
Sandbox do Mercos, uma conta, 22 e 25 de setembro de 2026. Cinco rodadas de scripts, com 6 segundos entre as chamadas: leitura dos status e dos orçamentos existentes; a sonda de campos no POST, sem criar nada; dois pedidos criados e cancelados para a sonda no PUT, as rotas, o PATCH e os parâmetros na URL; as rotas da tela só com os tokens; e o PUT no rascunho. Os pedidos de teste ficaram cancelados na conta. O cliente usado nos testes é fictício.
O que não medimos está na seção anterior. O projeto não tem vínculo com a Mercos.
Se a sua empresa precisa que um sistema converse com um ERP que a API não cobre inteiro, é esse o trabalho que fazemos em integrações e em engenharia reversa.
Perguntas
- Existe algum campo ou rota escondida para criar orçamento pela API do Mercos?
- Não achamos. Testamos 39 nomes de campo no POST e 15 no PUT, nas versões 1 e 2 da API, e 9 rotas inventadas. Tudo foi recusado com 422, 404 ou 405.
- O suporte do Mercos confirma que a API não cria orçamento?
- Sim. Em 22 de setembro de 2026, no chamado 561366, a resposta foi que é uma limitação atual do sistema e não se trata de um bug.
- Como a tela do Mercos cria um orçamento?
- Abrir a tela de criar pedido já grava um rascunho com status 1, antes de qualquer preenchimento. Cada abertura cria um rascunho novo, e a rota exige a sessão de um usuário logado.
- Dá para preencher pela API um orçamento criado na tela?
- Sim. O PUT /v2/pedidos/{id} num rascunho criado na tela respondeu 200, e o status continuou 1. No teste, o orçamento ficou com cliente, condição de pagamento, um item e total de R$ 536,90.
- As rotas da tela funcionam só com os tokens da API?
- Não. Com os dois tokens da integração, as três rotas da tela que testamos responderam 302 para a página de login. Elas precisam da sessão de um usuário.