API de Vendas
CRUD completo de pedidos de venda via API. Crie pedidos com itens, gerencie situações e cancele vendas.
Gerencie pedidos de venda e orçamentos da sua empresa via API. Consulte, crie, atualize e cancele pedidos de forma programática.
Visão Geral
| Propriedade | Valor |
|---|---|
| Base URL (produção) | https://api-backend.bunto.com.br/v1/vendas/ |
| Autenticação | Authorization: Bearer bnt_xxx |
| Formato | JSON |
| Escopo necessário (leitura) | vendas: read |
| Escopo necessário (escrita) | vendas: write |
| Escopo necessário (cancelamento) | vendas: delete |
Endpoints
| Método | Endpoint | Descrição | Escopo |
|---|---|---|---|
| GET | /v1/vendas/ | Listar vendas | vendas: read |
| GET | /v1/vendas/{id}/ | Detalhar venda | vendas: read |
| POST | /v1/vendas/ | Criar venda | vendas: write |
| PUT | /v1/vendas/{id}/ | Atualizar venda (completo) | vendas: write |
| PATCH | /v1/vendas/{id}/ | Atualizar venda (parcial) | vendas: write |
| DELETE | /v1/vendas/{id}/ | Cancelar venda | vendas: delete |
Nota: O endpoint DELETE não exclui o registro. Ele altera o status do pedido para cancelado, preservando o histórico completo.
Listar Vendas
GET /v1/vendas/
Escopo necessário: vendas: read
Retorna uma lista paginada de pedidos de venda da empresa.
Parâmetros de consulta
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
pagina | integer | 1 | Número da página |
por_pagina | integer | 25 | Registros por página (máximo: 100) |
busca | string | - | Busca por número do pedido ou número do pedido da loja virtual |
status | string | - | Filtrar por status (veja tabela de status abaixo) |
tipo_pedido | string | - | Filtrar por tipo: venda ou orcamento |
data_inicio | date | - | Filtrar vendas a partir desta data (formato: YYYY-MM-DD) |
data_fim | date | - | Filtrar vendas até esta data (formato: YYYY-MM-DD) |
ordenar | string | data_venda | Campo de ordenação: data_venda, total_venda, numero_pedido |
direcao | string | desc | Direção da ordenação: asc ou desc |
Campos retornados na listagem
| Campo | Tipo | Descrição |
|---|---|---|
id | integer | Identificador único do pedido |
numero_pedido | string ou null | Número do pedido gerado pelo sistema |
data_venda | datetime | Data e hora da venda |
tipo_pedido | string | Tipo do pedido: venda ou orcamento |
status | string | Código do status atual (ex: em_aberto, aprovado) |
status_display | string | Texto formatado do status (ex: "Em Aberto", "Aprovado") |
cliente_nome | string ou null | Nome do cliente associado |
vendedor_nome | string ou null | Nome do vendedor responsável |
total_itens | decimal | Soma dos valores dos itens (antes de descontos e acréscimos) |
desconto | decimal | Valor total de desconto aplicado |
total_venda | decimal | Valor final do pedido |
numero_itens | integer | Quantidade de itens no pedido |
origem_pedido_canal_venda | string ou null | Canal de origem do pedido (ex: "Wix", "Mercado Livre") |
Exemplo com cURL
bashcurl 'https://api-backend.bunto.com.br/v1/vendas/?pagina=1&por_pagina=10&status=em_aberto&tipo_pedido=venda&ordenar=data_venda&direcao=desc' \ -H 'Authorization: Bearer bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4' \ -H 'Content-Type: application/json'
Exemplo com Python
pythonimport requests BASE_URL = "https://api-backend.bunto.com.br/v1" TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4" headers = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json", } # Listar vendas em aberto do mês atual resposta = requests.get( f"{BASE_URL}/vendas/", headers=headers, params={ "status": "em_aberto", "tipo_pedido": "venda", "data_inicio": "2026-02-01", "data_fim": "2026-02-28", "ordenar": "data_venda", "direcao": "desc", "por_pagina": 25, }, ) dados = resposta.json() if dados["success"]: vendas = dados["data"]["resultados"] paginacao = dados["data"]["paginacao"] print(f"Total de vendas: {paginacao['total_registros']}") for venda in vendas: print(f" - [{venda['numero_pedido']}] {venda['cliente_nome']} - R$ {venda['total_venda']} ({venda['status_display']})") else: print(f"Erro: {dados}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const params = new URLSearchParams({ status: "em_aberto", tipo_pedido: "venda", data_inicio: "2026-02-01", data_fim: "2026-02-28", ordenar: "data_venda", direcao: "desc", por_pagina: "25", }); const resposta = await fetch(`${BASE_URL}/vendas/?${params}`, { headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", }, }); const dados = await resposta.json(); if (dados.success) { const vendas = dados.data.resultados; const paginacao = dados.data.paginacao; console.log(`Total de vendas: ${paginacao.total_registros}`); vendas.forEach((venda) => { console.log( ` - [${venda.numero_pedido}] ${venda.cliente_nome} - R$ ${venda.total_venda} (${venda.status_display})` ); }); }
Resposta de sucesso (200)
json{ "success": true, "message": "38 registros encontrados", "data": { "resultados": [ { "id": 1523, "numero_pedido": "PV-001523", "data_venda": "2026-02-11T16:45:00-03:00", "tipo_pedido": "venda", "status": "em_aberto", "status_display": "Em Aberto", "cliente_nome": "Ana Carolina da Silva", "vendedor_nome": "Carlos Eduardo Mendes", "total_itens": "1250.00", "desconto": "62.50", "total_venda": "1187.50", "numero_itens": 3, "origem_pedido_canal_venda": null }, { "id": 1522, "numero_pedido": "PV-001522", "data_venda": "2026-02-11T14:20:00-03:00", "tipo_pedido": "venda", "status": "em_aberto", "status_display": "Em Aberto", "cliente_nome": "Distribuidora Santos Ltda", "vendedor_nome": "Carlos Eduardo Mendes", "total_itens": "4890.00", "desconto": "0.00", "total_venda": "4890.00", "numero_itens": 8, "origem_pedido_canal_venda": "Wix" } ], "paginacao": { "pagina_atual": 1, "total_paginas": 2, "total_registros": 38, "por_pagina": 25, "proxima": "https://api-backend.bunto.com.br/v1/vendas/?pagina=2&por_pagina=25&status=em_aberto", "anterior": null } } }
Detalhar Venda
GET /v1/vendas/{id}/
Escopo necessário: vendas: read
Retorna todos os dados de um pedido de venda, incluindo a lista completa de itens.
Parâmetros de rota
| Parâmetro | Tipo | Descrição |
|---|---|---|
id | integer | ID do pedido de venda |
Campos retornados no detalhe
Além de todos os campos da listagem, o detalhe inclui:
| Campo | Tipo | Descrição |
|---|---|---|
numero_manual | integer ou null | Número manual do pedido |
data_saida | date ou null | Data de saída da mercadoria (formato: YYYY-MM-DD) |
data_prevista | date ou null | Data prevista de entrega (formato: YYYY-MM-DD) |
pedido_compra | string ou null | Número do pedido de compra do cliente |
numero_proposta | string ou null | Número da proposta comercial vinculada |
numero_pedido_loja_virtual | string ou null | Número do pedido na loja virtual/marketplace |
origem_pedido_loja_virtual | string ou null | Nome da loja virtual de origem (ex: "Shopify", "WooCommerce") |
desconto_tipo | string | Tipo de desconto aplicado: percentual ou valor |
outras_despesas | decimal | Valor de outras despesas adicionais |
frete_pago_cliente | decimal | Valor do frete cobrado do cliente |
condicao_pagamento | string ou null | Descrição da condição de pagamento (ex: "30/60/90 dias") |
peso_bruto | decimal ou null | Peso bruto total em kg |
qtd_volumes | integer ou null | Quantidade de volumes para transporte |
transportador_nome | string ou null | Nome do transportador responsável |
observacoes | string ou null | Observações gerais do pedido |
itens | array | Lista de itens do pedido (veja tabela abaixo) |
Objeto itens[]
| Campo | Tipo | Descrição |
|---|---|---|
id | integer | ID do item |
produto_nome | string | Nome/descrição do produto |
codigo | string | Código (SKU) do produto |
quantidade | decimal | Quantidade do item |
preco_unitario | decimal | Preço unitário do item |
desconto | decimal | Valor de desconto no item |
total | decimal | Valor total do item (quantidade x preco_unitario - desconto) |
Exemplo com cURL
bashcurl https://api-backend.bunto.com.br/v1/vendas/1523/ \ -H 'Authorization: Bearer bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4' \ -H 'Content-Type: application/json'
Exemplo com Python
pythonimport requests BASE_URL = "https://api-backend.bunto.com.br/v1" TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4" headers = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json", } venda_id = 1523 resposta = requests.get(f"{BASE_URL}/vendas/{venda_id}/", headers=headers) dados = resposta.json() if dados["success"]: venda = dados["data"] print(f"Pedido: {venda['numero_pedido']}") print(f"Cliente: {venda['cliente_nome']}") print(f"Status: {venda['status_display']}") print(f"Total: R$ {venda['total_venda']}") print(f"Itens ({len(venda['itens'])}):") for item in venda["itens"]: print(f" - [{item['codigo']}] {item['produto_nome']} x{item['quantidade']} = R$ {item['total']}") else: print(f"Erro: {dados}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const vendaId = 1523; const resposta = await fetch(`${BASE_URL}/vendas/${vendaId}/`, { headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", }, }); const dados = await resposta.json(); if (dados.success) { const venda = dados.data; console.log(`Pedido: ${venda.numero_pedido}`); console.log(`Cliente: ${venda.cliente_nome}`); console.log(`Status: ${venda.status_display}`); console.log(`Total: R$ ${venda.total_venda}`); console.log(`Itens (${venda.itens.length}):`); venda.itens.forEach((item) => { console.log( ` - [${item.codigo}] ${item.produto_nome} x${item.quantidade} = R$ ${item.total}` ); }); }
Resposta de sucesso (200)
json{ "success": true, "message": "Registro encontrado", "data": { "id": 1523, "numero_pedido": "PV-001523", "data_venda": "2026-02-11T16:45:00-03:00", "tipo_pedido": "venda", "status": "em_aberto", "status_display": "Em Aberto", "cliente_nome": "Ana Carolina da Silva", "vendedor_nome": "Carlos Eduardo Mendes", "total_itens": "1250.00", "desconto": "62.50", "total_venda": "1187.50", "numero_itens": 3, "origem_pedido_canal_venda": null, "numero_manual": null, "data_saida": null, "data_prevista": "2026-02-18", "pedido_compra": null, "numero_proposta": "PC-000089", "numero_pedido_loja_virtual": null, "origem_pedido_loja_virtual": null, "desconto_tipo": "percentual", "outras_despesas": "0.00", "frete_pago_cliente": "35.00", "condicao_pagamento": "30/60 dias", "peso_bruto": "4.500", "qtd_volumes": 2, "transportador_nome": "Transportadora Rápido SP", "observacoes":"Entregar no horário comercial. Portaria B.", "itens": [ { "id": 4501, "produto_nome": "Camiseta Básica Algodão", "codigo":"CAM-001", "quantidade": "10.000", "preco_unitario": "49.90", "desconto": "24.50", "total": "474.50" }, { "id": 4502, "produto_nome": "Bermuda Jeans Masculina", "codigo":"BER-002", "quantidade": "5.000", "preco_unitario": "129.90", "desconto": "32.25", "total": "617.25" }, { "id": 4503, "produto_nome": "Meia Esportiva Cano Alto", "codigo":"MEI-015", "quantidade": "10.000", "preco_unitario": "15.80", "desconto": "5.75", "total": "152.25" } ] } }
Criar Venda
POST /v1/vendas/
Escopo necessário: vendas: write
Cria um novo pedido de venda ou orcamento. O pedido é criado com status em_aberto e o número do pedido é gerado automaticamente pelo sistema.
Campos do body
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
cliente_id | integer | Sim | ID do cliente (deve existir no cadastro da empresa) |
itens | array | Sim | Lista de itens do pedido (veja tabela abaixo) |
vendedor_id | integer | Não | ID do vendedor responsável |
tipo_pedido | string | Não | Tipo do pedido: venda (padrão) ou orcamento |
data_saida | date | Não | Data de saída da mercadoria (formato: YYYY-MM-DD) |
data_prevista | date | Não | Data prevista de entrega (formato: YYYY-MM-DD) |
observacoes | string | Não | Observações gerais do pedido |
condicao_pagamento | string | Não | Descrição da condição de pagamento |
desconto | decimal | Não | Valor ou percentual de desconto (padrão: 0) |
desconto_tipo | string | Não | Tipo de desconto: percentual (padrão) ou valor |
outras_despesas | decimal | Não | Valor de outras despesas (padrão: 0) |
frete_pago_cliente | decimal | Não | Valor do frete cobrado do cliente (padrão: 0) |
numero_pedido_loja_virtual | string | Não | Número do pedido na loja virtual (máximo 50 caracteres) |
origem_pedido_loja_virtual | string | Não | Nome da loja virtual de origem (máximo 50 caracteres) |
origem_pedido_canal_venda | string | Não | Canal de venda de origem (máximo 50 caracteres) |
deposito_id | integer | Não | ID do depósito para reserva de estoque |
Objeto itens[] (criação)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
produto_id | integer | Sim | ID do produto (deve existir no cadastro da empresa) |
quantidade | decimal | Sim | Quantidade do item |
preco_unitario | decimal | Sim | Preço unitário do item em R$ |
desconto | decimal | Não | Valor de desconto no item (padrão: 0) |
Exemplo com cURL
bashcurl -X POST https://api-backend.bunto.com.br/v1/vendas/ \ -H 'Authorization: Bearer bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4' \ -H 'Content-Type: application/json' \ -d '{ "cliente_id": 142, "vendedor_id": 5, "tipo_pedido": "venda", "data_prevista": "2026-02-25", "condicao_pagamento": "30/60 dias", "desconto": 5, "desconto_tipo": "percentual", "frete_pago_cliente": 45.00, "observacoes":"Entregar no horário comercial. Confirmar por telefone.", "deposito_id": 1, "itens": [ { "produto_id": 1, "quantidade": 20, "preco_unitario": 49.90, "desconto": 0 }, { "produto_id": 2, "quantidade": 10, "preco_unitario": 129.90, "desconto": 15.00 }, { "produto_id": 45, "quantidade": 5, "preco_unitario": 299.90, "desconto": 0 } ] }'
Exemplo com Python
pythonimport requests BASE_URL = "https://api-backend.bunto.com.br/v1" TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4" headers = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json", } novo_pedido = { "cliente_id": 142, "vendedor_id": 5, "tipo_pedido": "venda", "data_prevista": "2026-02-25", "condicao_pagamento": "30/60 dias", "desconto": 5, "desconto_tipo": "percentual", "frete_pago_cliente": 45.00, "observacoes":"Entregar no horário comercial. Confirmar por telefone.", "deposito_id": 1, "itens": [ { "produto_id": 1, "quantidade": 20, "preco_unitario": 49.90, "desconto": 0, }, { "produto_id": 2, "quantidade": 10, "preco_unitario": 129.90, "desconto": 15.00, }, { "produto_id": 45, "quantidade": 5, "preco_unitario": 299.90, "desconto": 0, }, ], } resposta = requests.post(f"{BASE_URL}/vendas/", headers=headers, json=novo_pedido) dados = resposta.json() if dados["success"]: venda = dados["data"] print(f"Pedido criado com sucesso!") print(f"Numero: {venda['numero_pedido']}") print(f"Total: R$ {venda['total_venda']}") print(f"Itens: {len(venda['itens'])}") else: print(f"Erro ao criar pedido: {dados}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const novoPedido = { cliente_id: 142, vendedor_id: 5, tipo_pedido: "venda", data_prevista: "2026-02-25", condicao_pagamento: "30/60 dias", desconto: 5, desconto_tipo: "percentual", frete_pago_cliente: 45.0, observacoes: "Entregar no horário comercial. Confirmar por telefone.", deposito_id: 1, itens: [ { produto_id: 1, quantidade: 20, preco_unitario: 49.9, desconto: 0, }, { produto_id: 2, quantidade: 10, preco_unitario: 129.9, desconto: 15.0, }, { produto_id: 45, quantidade: 5, preco_unitario: 299.9, desconto: 0, }, ], }; const resposta = await fetch(`${BASE_URL}/vendas/`, { method: "POST", headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify(novoPedido), }); const dados = await resposta.json(); if (dados.success) { const venda = dados.data; console.log(`Pedido criado com sucesso!`); console.log(`Numero: ${venda.numero_pedido}`); console.log(`Total: R$ ${venda.total_venda}`); console.log(`Itens: ${venda.itens.length}`); } else { console.error(`Erro ao criar pedido:`, dados); }
Resposta de sucesso (201)
json{ "success": true, "message": "Pedido criado com sucesso", "data": { "id": 1524, "numero_pedido": "PV-001524", "data_venda": "2026-02-12T10:30:00-03:00", "tipo_pedido": "venda", "status": "em_aberto", "status_display": "Em Aberto", "cliente_nome": "Ana Carolina da Silva", "vendedor_nome": "Carlos Eduardo Mendes", "total_itens": "3296.50", "desconto": "164.83", "total_venda": "3176.68", "numero_itens": 3, "origem_pedido_canal_venda": null, "numero_manual": null, "data_saida": null, "data_prevista": "2026-02-25", "pedido_compra": null, "numero_proposta": null, "numero_pedido_loja_virtual": null, "origem_pedido_loja_virtual": null, "desconto_tipo": "percentual", "outras_despesas": "0.00", "frete_pago_cliente": "45.00", "condicao_pagamento": "30/60 dias", "peso_bruto": null, "qtd_volumes": null, "transportador_nome": null, "observacoes":"Entregar no horário comercial. Confirmar por telefone.", "itens": [ { "id": 4510, "produto_nome": "Camiseta Básica Algodão", "codigo":"CAM-001", "quantidade": "20.000", "preco_unitario": "49.90", "desconto": "0.00", "total": "998.00" }, { "id": 4511, "produto_nome": "Bermuda Jeans Masculina", "codigo":"BER-002", "quantidade": "10.000", "preco_unitario": "129.90", "desconto": "15.00", "total": "1284.00" }, { "id": 4512, "produto_nome": "Tênis Esportivo Running Pro", "codigo":"TEN-045", "quantidade": "5.000", "preco_unitario": "299.90", "desconto": "0.00", "total": "1499.50" } ] } }
Atualizar Venda
Atualização completa
PUT /v1/vendas/{id}/
Atualização parcial
PATCH /v1/vendas/{id}/
Escopo necessário: vendas: write
Atualiza os campos do pedido de venda. Use PUT para atualização completa ou PATCH para atualização parcial (apenas os campos enviados serão alterados).
Importante: Este endpoint atualiza apenas os campos do pedido (datas, observações, condição de pagamento, etc.). Ele não atualiza os itens do pedido. Para alterar itens, utilize a criação de um novo pedido.
Campos atualizáveis
Todos os campos do body de criação podem ser enviados, exceto itens.
Exemplo com cURL (PATCH)
bashcurl -X PATCH https://api-backend.bunto.com.br/v1/vendas/1524/ \ -H 'Authorization: Bearer bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4' \ -H 'Content-Type: application/json' \ -d '{ "data_prevista": "2026-03-05", "condicao_pagamento": "A vista", "observacoes":"Cliente solicitou antecipação do prazo de entrega." }'
Exemplo com Python
pythonimport requests BASE_URL = "https://api-backend.bunto.com.br/v1" TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4" headers = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json", } venda_id = 1524 # Atualização parcial (PATCH) - apenas os campos que mudaram atualizacao = { "data_prevista": "2026-03-05", "condicao_pagamento": "A vista", "observacoes":"Cliente solicitou antecipação do prazo de entrega.", } resposta = requests.patch( f"{BASE_URL}/vendas/{venda_id}/", headers=headers, json=atualizacao, ) dados = resposta.json() if dados["success"]: venda = dados["data"] print(f"Pedido {venda['numero_pedido']} atualizado com sucesso") print(f"Nova data prevista: {venda['data_prevista']}") else: print(f"Erro ao atualizar: {dados}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const vendaId = 1524; const atualizacao = { data_prevista: "2026-03-05", condicao_pagamento: "A vista", observacoes: "Cliente solicitou antecipação do prazo de entrega.", }; const resposta = await fetch(`${BASE_URL}/vendas/${vendaId}/`, { method: "PATCH", headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify(atualizacao), }); const dados = await resposta.json(); if (dados.success) { const venda = dados.data; console.log(`Pedido ${venda.numero_pedido} atualizado com sucesso`); console.log(`Nova data prevista: ${venda.data_prevista}`); } else { console.error(`Erro ao atualizar:`, dados); }
Resposta de sucesso (200)
json{ "success": true, "message": "Pedido atualizado com sucesso", "data": { "id": 1524, "numero_pedido": "PV-001524", "data_venda": "2026-02-12T10:30:00-03:00", "tipo_pedido": "venda", "status": "em_aberto", "status_display": "Em Aberto", "cliente_nome": "Ana Carolina da Silva", "vendedor_nome": "Carlos Eduardo Mendes", "total_itens": "3296.50", "desconto": "164.83", "total_venda": "3176.68", "numero_itens": 3, "origem_pedido_canal_venda": null, "numero_manual": null, "data_saida": null, "data_prevista": "2026-03-05", "pedido_compra": null, "numero_proposta": null, "numero_pedido_loja_virtual": null, "origem_pedido_loja_virtual": null, "desconto_tipo": "percentual", "outras_despesas": "0.00", "frete_pago_cliente": "45.00", "condicao_pagamento": "A vista", "peso_bruto": null, "qtd_volumes": null, "transportador_nome": null, "observacoes":"Cliente solicitou antecipação do prazo de entrega.", "itens": [ { "id": 4510, "produto_nome": "Camiseta Básica Algodão", "codigo":"CAM-001", "quantidade": "20.000", "preco_unitario": "49.90", "desconto": "0.00", "total": "998.00" }, { "id": 4511, "produto_nome": "Bermuda Jeans Masculina", "codigo":"BER-002", "quantidade": "10.000", "preco_unitario": "129.90", "desconto": "15.00", "total": "1284.00" }, { "id": 4512, "produto_nome": "Tênis Esportivo Running Pro", "codigo":"TEN-045", "quantidade": "5.000", "preco_unitario": "299.90", "desconto": "0.00", "total": "1499.50" } ] } }
Cancelar Venda
DELETE /v1/vendas/{id}/
Escopo necessário: vendas: delete
Cancela um pedido de venda. O registro não é excluído do banco de dados -- o status do pedido é alterado para cancelado, preservando o histórico completo.
Exemplo com cURL
bashcurl -X DELETE https://api-backend.bunto.com.br/v1/vendas/1524/ \ -H 'Authorization: Bearer bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4'
Exemplo com Python
pythonimport requests BASE_URL = "https://api-backend.bunto.com.br/v1" TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4" headers = {"Authorization": f"Bearer {TOKEN}"} venda_id = 1524 resposta = requests.delete(f"{BASE_URL}/vendas/{venda_id}/", headers=headers) dados = resposta.json() if dados["success"]: print("Pedido cancelado com sucesso!") else: print(f"Erro ao cancelar: {dados}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const vendaId = 1524; const resposta = await fetch(`${BASE_URL}/vendas/${vendaId}/`, { method: "DELETE", headers: { Authorization: `Bearer ${TOKEN}`, }, }); const dados = await resposta.json(); if (dados.success) { console.log("Pedido cancelado com sucesso!"); } else { console.error(`Erro ao cancelar:`, dados); }
Resposta de sucesso (200)
json{ "success": true, "message": "Pedido cancelado com sucesso" }
Importante: Após o cancelamento, o pedido continuará aparecendo nas listagens com status=cancelado. Pedidos cancelados não podem ser reabertos via API.
Erros
Validação (400)
Retornado quando os dados enviados são inválidos.
json{ "success": false, "error": { "code": "VALIDATION_ERROR", "message": "Erro de validacao", "details": { "cliente_id": ["Este campo e obrigatorio."], "itens": ["Este campo e obrigatorio."] } } }
Item inválido (400)
Retornado quando um item do pedido possui dados inválidos.
json{ "success": false, "error": { "code": "VALIDATION_ERROR", "message": "Erro de validacao", "details": { "itens": [ { "produto_id": ["Produto com ID 999 nao encontrado."], "quantidade": ["Certifique-se de que este valor seja maior que 0."] } ] } } }
Cliente não encontrado (400)
json{ "success": false, "error": { "code": "VALIDATION_ERROR", "message": "Cliente com ID 999 nao encontrado", "details": { "cliente_id": ["Cliente com ID 999 nao encontrado"] } } }
Não autenticado (401)
json{ "detail": "Token invalido" }
Sem permissão (403)
Retornado quando o token não possui o escopo necessário.
json{ "detail": "Token nao tem permissao para este recurso" }
Não encontrado (404)
Retornado quando o pedido não existe ou pertence a outra empresa.
json{ "success": false, "error": { "code": "NOT_FOUND", "message": "Registro nao encontrado" } }
Rate limit excedido (429)
json{ "detail": "Limite de requisicoes excedido. Tente novamente em 45 segundos." }
Rate Limiting
Os limites de requisição são aplicados por token (não por IP).
| Operação | Métodos | Limite |
|---|---|---|
| Leitura | GET, HEAD, OPTIONS | 120 requisições/minuto |
| Escrita | POST, PUT, PATCH | 30 requisições/minuto |
| Cancelamento | DELETE | 10 requisições/minuto |
Ao exceder o limite, a API retorna 429 Too Many Requests. Implemente retry com backoff exponencial para lidar com esses casos.
Paginação
Endpoints de listagem retornam dados paginados.
| Parâmetro | Tipo | Padrão | Máximo | Descrição |
|---|---|---|---|---|
pagina | integer | 1 | - | Número da página |
por_pagina | integer | 25 | 100 | Registros por página |
Nota: Os parâmetros são pagina e por_pagina (em português), não page e per_page.
Objeto paginacao na resposta
| Campo | Tipo | Descrição |
|---|---|---|
pagina_atual | integer | Número da página atual |
total_paginas | integer | Total de páginas disponíveis |
total_registros | integer | Total de registros encontrados |
por_pagina | integer | Registros por página |
proxima | string ou null | URL da próxima página (null se for a última) |
anterior | string ou null | URL da página anterior (null se for a primeira) |
Navegação entre páginas (Python)
pythonimport requests BASE_URL = "https://api-backend.bunto.com.br/v1" TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4" headers = {"Authorization": f"Bearer {TOKEN}"} todas_vendas = [] url = f"{BASE_URL}/vendas/?por_pagina=100&status=finalizado" while url: resposta = requests.get(url, headers=headers) dados = resposta.json() if not dados["success"]: break todas_vendas.extend(dados["data"]["resultados"]) url = dados["data"]["paginacao"]["proxima"] print(f"Total obtido: {len(todas_vendas)} vendas finalizadas")
Valores de Referência
Status do Pedido
| Valor | Descrição |
|---|---|
em_aberto | Em Aberto |
aprovado | Aprovado |
preparando_envio | Preparando Envio |
faturado | Faturado |
pronto_envio | Pronto para Envio |
enviado | Enviado |
entregue | Entregue |
nao_entregue | Não Entregue |
dados_incompletos | Dados Incompletos |
em_processamento | Em Processamento |
finalizado | Finalizado |
cancelado | Cancelado |
Tipo de Pedido
| Valor | Descrição |
|---|---|
venda | Pedido de Venda |
orcamento | Orçamento |
Tipo de Desconto
| Valor | Descrição |
|---|---|
percentual | Desconto em percentual sobre o total de itens |
valor | Desconto em valor absoluto (R$) |
Exemplos Completos
Importar pedidos de marketplace (Python)
pythonimport os import time import requests class BuntoVendas: """Cliente para o endpoint de vendas da API v1 do Bunto ERP.""" def __init__(self, token=None): self.token = token or os.environ["BUNTO_API_TOKEN"] self.base_url = "https://api-backend.bunto.com.br/v1" self.session = requests.Session() self.session.headers.update({ "Authorization": f"Bearer {self.token}", "Content-Type": "application/json", }) def _requisicao(self, metodo, endpoint, **kwargs): """Executa requisição com retry para rate limit.""" url = f"{self.base_url}/{endpoint.lstrip('/')}" for tentativa in range(3): resposta = self.session.request(metodo, url, **kwargs) if resposta.status_code == 429: tempo = 2 ** tentativa * 15 print(f"Rate limit. Aguardando {tempo}s...") time.sleep(tempo) continue return resposta raise Exception("Limite de tentativas excedido") def listar(self, **filtros): """Lista vendas com filtros opcionais.""" resposta = self._requisicao("GET", "/vendas/", params=filtros) return resposta.json() def obter(self, venda_id): """Obtém detalhes de uma venda.""" resposta = self._requisicao("GET", f"/vendas/{venda_id}/") return resposta.json() def criar(self, dados): """Cria um novo pedido de venda.""" resposta = self._requisicao("POST", "/vendas/", json=dados) return resposta.json() def atualizar(self, venda_id, dados): """Atualiza parcialmente uma venda.""" resposta = self._requisicao("PATCH", f"/vendas/{venda_id}/", json=dados) return resposta.json() def cancelar(self, venda_id): """Cancela uma venda.""" resposta = self._requisicao("DELETE", f"/vendas/{venda_id}/") return resposta.json() def listar_todas(self, **filtros): """Lista todas as vendas com paginação automática.""" filtros["por_pagina"] = 100 filtros["pagina"] = 1 todas = [] while True: resultado = self.listar(**filtros) if not resultado["success"]: break todas.extend(resultado["data"]["resultados"]) paginacao = resultado["data"]["paginacao"] if paginacao["proxima"] is None: break filtros["pagina"] += 1 return todas # Uso: importar pedidos de marketplace externo api = BuntoVendas() # Dados vindos do marketplace pedidos_marketplace = [ { "cliente_id": 142, "tipo_pedido": "venda", "numero_pedido_loja_virtual": "WIX-78901", "origem_pedido_loja_virtual": "Wix", "origem_pedido_canal_venda": "Wix", "frete_pago_cliente": 25.90, "itens": [ {"produto_id": 1, "quantidade": 2, "preco_unitario": 49.90}, {"produto_id": 45, "quantidade": 1, "preco_unitario": 299.90}, ], }, { "cliente_id": 87, "tipo_pedido": "venda", "numero_pedido_loja_virtual": "WIX-78902", "origem_pedido_loja_virtual": "Wix", "origem_pedido_canal_venda": "Wix", "frete_pago_cliente": 0, "itens": [ {"produto_id": 2, "quantidade": 3, "preco_unitario": 129.90}, ], }, ] for pedido in pedidos_marketplace: resultado = api.criar(pedido) if resultado["success"]: venda = resultado["data"] print( f"Pedido {venda['numero_pedido']} criado - " f"Origem: {pedido['numero_pedido_loja_virtual']} - " f"Total: R$ {venda['total_venda']}" ) else: print(f"Erro ao importar {pedido['numero_pedido_loja_virtual']}: {resultado}") # Respeitar rate limit de escrita (30/min) time.sleep(2.1)
Consultar vendas por período (JavaScript/Node.js)
javascriptclass BuntoVendas { constructor(token) { this.token = token ?? process.env.BUNTO_API_TOKEN; this.baseUrl = "https://api-backend.bunto.com.br/v1"; this.headers = { Authorization: `Bearer ${this.token}`, "Content-Type": "application/json", }; } async requisicao(metodo, endpoint, opcoes = {}) { const url = `${this.baseUrl}/${endpoint.replace(/^\//, "")}`; for (let tentativa = 0; tentativa < 3; tentativa++) { const resposta = await fetch(url, { method: metodo, headers: this.headers, ...opcoes, }); if (resposta.status === 429) { const tempo = 2 ** tentativa * 15 * 1000; console.log(`Rate limit. Aguardando ${tempo / 1000}s...`); await new Promise((resolve) => setTimeout(resolve, tempo)); continue; } return resposta.json(); } throw new Error("Limite de tentativas excedido"); } async listar(filtros = {}) { const params = new URLSearchParams(filtros); return this.requisicao("GET", `/vendas/?${params}`); } async listarTodas(filtros = {}) { filtros.por_pagina = "100"; filtros.pagina = "1"; const todas = []; while (true) { const resultado = await this.listar(filtros); if (!resultado.success) break; todas.push(...resultado.data.resultados); if (resultado.data.paginacao.proxima === null) break; filtros.pagina = String(Number(filtros.pagina) + 1); } return todas; } } // Relatório de vendas do mês const api = new BuntoVendas(); const vendasMes = await api.listarTodas({ status: "finalizado", data_inicio: "2026-02-01", data_fim: "2026-02-28", ordenar: "total_venda", direcao: "desc", }); let totalFaturado = 0; for (const venda of vendasMes) { totalFaturado += parseFloat(venda.total_venda); } console.log(`Vendas finalizadas em fevereiro: ${vendasMes.length}`); console.log(`Total faturado: R$ ${totalFaturado.toFixed(2)}`); // Top 5 vendas do mês console.log("\nTop 5 vendas:"); vendasMes.slice(0, 5).forEach((venda, i) => { console.log( ` ${i + 1}. [${venda.numero_pedido}] ${venda.cliente_nome} - R$ ${venda.total_venda}` ); });
Códigos de Status HTTP
| Código | Significado | Quando ocorre |
|---|---|---|
| 200 | Sucesso | Consulta, atualização ou cancelamento bem-sucedido |
| 201 | Criado | Pedido criado com sucesso via POST |
| 400 | Erro de validação | Dados invalidos, cliente não encontrado, produto inválido |
| 401 | Não autenticado | Token ausente, inválido, expirado ou revogado |
| 403 | Sem permissão | Token não tem escopo para vendas |
| 404 | Não encontrado | Pedido não existe ou pertence a outra empresa |
| 429 | Muitas requisições | Rate limit excedido |
| 500 | Erro interno | Erro inesperado no servidor |