API de PDV
Gestão de aberturas e fechamentos de caixa PDV via API.
Gerencie as aberturas e fechamentos de caixa do PDV (Ponto de Venda) do Bunto ERP. Este endpoint permite listar, consultar, criar, atualizar e fechar caixas via API.
Base URL
Produção:
https://api-backend.bunto.com.br/v1/pdv/
Autenticação
Todas as requisições exigem um Token de API no header Authorization:
Authorization: Bearer bnt_seu_token_aqui
Tokens são gerados em Integrações -> Tokens de API no painel do Bunto ERP. Escopo necessário: pdv com a ação correspondente (read, write ou delete).
Endpoints
Listar Aberturas de Caixa
GET /v1/pdv/
Escopo necessário: pdv: read
Retorna a lista paginada de aberturas de caixa da empresa.
Query Parameters
| 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 observação de abertura ou fechamento |
status | string | - | Filtrar por status: aberto ou fechado |
data_inicio | string | - | Filtrar a partir desta data (formato: YYYY-MM-DD) |
data_fim | string | - | Filtrar até esta data (formato: YYYY-MM-DD) |
ordenar | string | data_hora_ini | Campo de ordenação: data_hora_ini, valor_ini, status |
direcao | string | desc | Direção da ordenação: asc ou desc |
Exemplo com cURL
bashcurl 'https://api-backend.bunto.com.br/v1/pdv/?pagina=1&por_pagina=10&status=aberto' \ -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 caixas abertos resposta = requests.get( f"{BASE_URL}/pdv/", headers=headers, params={ "pagina": 1, "por_pagina": 25, "status": "aberto", "ordenar": "data_hora_ini", "direcao": "desc", }, ) dados = resposta.json() if dados["success"]: caixas = dados["data"]["resultados"] paginacao = dados["data"]["paginacao"] print(f"Total de caixas: {paginacao['total_registros']}") for caixa in caixas: print(f" - ID: {caixa['id']} | Status: {caixa['status']} | Valor inicial: R$ {caixa['valor_ini']} | Operador: {caixa['usuario_abertura_nome']}") else: print(f"Erro: {resposta.status_code}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const params = new URLSearchParams({ pagina: "1", por_pagina: "25", status: "aberto", ordenar: "data_hora_ini", direcao: "desc", }); const resposta = await fetch(`${BASE_URL}/pdv/?${params}`, { headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", }, }); const dados = await resposta.json(); if (dados.success) { const caixas = dados.data.resultados; const paginacao = dados.data.paginacao; console.log(`Total de caixas: ${paginacao.total_registros}`); caixas.forEach((caixa) => { console.log(` - ID: ${caixa.id} | Status: ${caixa.status} | Valor inicial: R$ ${caixa.valor_ini} | Operador: ${caixa.usuario_abertura_nome}`); }); } else { console.error(`Erro: ${resposta.status}`); }
Resposta (200 OK)
json{ "success": true, "message": "3 registros encontrados", "data": { "resultados": [ { "id": 45, "status": "aberto", "data_hora_ini": "2026-02-12T08:00:00-03:00", "valor_ini": "200.00", "usuario_abertura_nome": "Carlos Souza", "total_sangrias": "50.00", "total_reforcos": "100.00" }, { "id": 44, "status": "aberto", "data_hora_ini": "2026-02-12T07:30:00-03:00", "valor_ini": "150.00", "usuario_abertura_nome": "Ana Lima", "total_sangrias": "0.00", "total_reforcos": "0.00" } ], "paginacao": { "pagina_atual": 1, "total_paginas": 1, "total_registros": 3, "por_pagina": 25, "proxima": null, "anterior": null } } }
Campos da Listagem
| Campo | Tipo | Descrição |
|---|---|---|
id | integer | Identificador único da abertura de caixa |
status | string | Status do caixa: aberto ou fechado |
data_hora_ini | datetime | Data e hora da abertura do caixa |
valor_ini | string (decimal) | Valor inicial do caixa (formato: "200.00") |
usuario_abertura_nome | string / null | Nome do usuário que abriu o caixa |
total_sangrias | string (decimal) | Total de sangrias realizadas no caixa |
total_reforcos | string (decimal) | Total de reforços realizados no caixa |
Obter Abertura de Caixa
GET /v1/pdv/{id}/
Escopo necessário: pdv: read
Retorna os dados completos de uma abertura de caixa específica, incluindo data de fechamento, valor final e observações.
Exemplo com cURL
bashcurl https://api-backend.bunto.com.br/v1/pdv/45/ \ -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", } caixa_id = 45 resposta = requests.get(f"{BASE_URL}/pdv/{caixa_id}/", headers=headers) dados = resposta.json() if dados["success"]: caixa = dados["data"] print(f"Caixa #{caixa['id']} | Status: {caixa['status']}") print(f"Abertura: {caixa['data_hora_ini']} | Valor inicial: R$ {caixa['valor_ini']}") print(f"Operador: {caixa['usuario_abertura_nome']}") print(f"Sangrias: R$ {caixa['total_sangrias']} | Reforços: R$ {caixa['total_reforcos']}") if caixa["observacao_abertura"]: print(f"Observacao: {caixa['observacao_abertura']}") else: print(f"Erro: {dados}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const caixaId = 45; const resposta = await fetch(`${BASE_URL}/pdv/${caixaId}/`, { headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", }, }); const dados = await resposta.json(); if (dados.success) { const caixa = dados.data; console.log(`Caixa #${caixa.id} | Status: ${caixa.status}`); console.log(`Abertura: ${caixa.data_hora_ini} | Valor inicial: R$ ${caixa.valor_ini}`); console.log(`Operador: ${caixa.usuario_abertura_nome}`); console.log(`Sangrias: R$ ${caixa.total_sangrias} | Reforços: R$ ${caixa.total_reforcos}`); } else { console.error(`Erro: ${JSON.stringify(dados)}`); }
Resposta (200 OK)
json{ "success": true, "message": "Registro encontrado", "data": { "id": 45, "status": "aberto", "data_hora_ini": "2026-02-12T08:00:00-03:00", "valor_ini": "200.00", "usuario_abertura_nome": "Carlos Souza", "total_sangrias": "50.00", "total_reforcos": "100.00", "data_hora_fim": null, "valor_fim": null, "observacao_abertura": "Abertura do turno da manhã", "observacao_fechamento": null, "criado_em": "2026-02-12T08:00:00-03:00", "atualizado_em": "2026-02-12T12:30:00-03:00" } }
Campos do Detalhe (adicionais à listagem)
| Campo | Tipo | Descrição |
|---|---|---|
data_hora_fim | datetime / null | Data e hora do fechamento do caixa (null se ainda aberto) |
valor_fim | string (decimal) / null | Valor final no fechamento (null se ainda aberto) |
observacao_abertura | string / null | Observação registrada na abertura do caixa |
observacao_fechamento | string / null | Observação registrada no fechamento do caixa |
criado_em | datetime | Data e hora de criação do registro |
atualizado_em | datetime | Data e hora da última atualização |
Criar Abertura de Caixa
POST /v1/pdv/
Escopo necessário: pdv: write
Cria uma nova abertura de caixa na empresa do token autenticado.
Campos do Request Body
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
valor_ini | decimal | Não | Valor inicial do caixa (ex: "200.00") |
observacao_abertura | string | Não | Observação sobre a abertura do caixa |
observacao_fechamento | string | Não | Observação sobre o fechamento (pode ser preenchida na atualização) |
Exemplo com cURL
bashcurl -X POST https://api-backend.bunto.com.br/v1/pdv/ \ -H 'Authorization: Bearer bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4' \ -H 'Content-Type: application/json' \ -d '{ "valor_ini": "300.00", "observacao_abertura": "Abertura do turno da tarde" }'
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", } nova_abertura = { "valor_ini": "300.00", "observacao_abertura": "Abertura do turno da tarde", } resposta = requests.post(f"{BASE_URL}/pdv/", headers=headers, json=nova_abertura) dados = resposta.json() if dados["success"]: caixa = dados["data"] print(f"Caixa aberto com sucesso! ID: {caixa['id']}") print(f"Valor inicial: R$ {caixa['valor_ini']}") print(f"Operador: {caixa['usuario_abertura_nome']}") else: print(f"Erro ao abrir caixa: {dados}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const novaAbertura = { valor_ini: "300.00", observacao_abertura: "Abertura do turno da tarde", }; const resposta = await fetch(`${BASE_URL}/pdv/`, { method: "POST", headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify(novaAbertura), }); const dados = await resposta.json(); if (dados.success) { console.log(`Caixa aberto com sucesso! ID: ${dados.data.id}`); console.log(`Valor inicial: R$ ${dados.data.valor_ini}`); } else { console.error(`Erro ao abrir caixa:`, dados); }
Resposta (201 Created)
json{ "success": true, "message": "Abertura de caixa criada com sucesso", "data": { "id": 46, "status": "aberto", "data_hora_ini": "2026-02-12T13:00:00-03:00", "valor_ini": "300.00", "usuario_abertura_nome": "Carlos Souza", "total_sangrias": "0.00", "total_reforcos": "0.00", "data_hora_fim": null, "valor_fim": null, "observacao_abertura": "Abertura do turno da tarde", "observacao_fechamento": null, "criado_em": "2026-02-12T13:00:00-03:00", "atualizado_em": "2026-02-12T13:00:00-03:00" } }
Atualizar Abertura de Caixa
PUT /v1/pdv/{id}/
PATCH /v1/pdv/{id}/
Escopo necessário: pdv: write
Atualiza uma abertura de caixa existente. Use PUT para atualização completa ou PATCH para atualização parcial (apenas os campos enviados serão alterados).
Exemplo com cURL (PATCH - atualização parcial)
bashcurl -X PATCH https://api-backend.bunto.com.br/v1/pdv/46/ \ -H 'Authorization: Bearer bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4' \ -H 'Content-Type: application/json' \ -d '{ "observacao_abertura": "Abertura do turno da tarde - com troco extra" }'
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", } caixa_id = 46 atualizacao = { "observacao_abertura": "Abertura do turno da tarde - com troco extra", } resposta = requests.patch( f"{BASE_URL}/pdv/{caixa_id}/", headers=headers, json=atualizacao, ) dados = resposta.json() if dados["success"]: caixa = dados["data"] print(f"Caixa atualizado! Observacao: {caixa['observacao_abertura']}") 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 caixaId = 46; const atualizacao = { observacao_abertura: "Abertura do turno da tarde - com troco extra", }; const resposta = await fetch(`${BASE_URL}/pdv/${caixaId}/`, { method: "PATCH", headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify(atualizacao), }); const dados = await resposta.json(); if (dados.success) { console.log(`Caixa atualizado! Observacao: ${dados.data.observacao_abertura}`); } else { console.error(`Erro ao atualizar:`, dados); }
Resposta (200 OK)
json{ "success": true, "message": "Abertura de caixa atualizada com sucesso", "data": { "id": 46, "status": "aberto", "data_hora_ini": "2026-02-12T13:00:00-03:00", "valor_ini": "300.00", "usuario_abertura_nome": "Carlos Souza", "total_sangrias": "0.00", "total_reforcos": "0.00", "data_hora_fim": null, "valor_fim": null, "observacao_abertura": "Abertura do turno da tarde - com troco extra", "observacao_fechamento": null, "criado_em": "2026-02-12T13:00:00-03:00", "atualizado_em": "2026-02-12T14:20:00-03:00" } }
Fechar Caixa (Soft Delete)
DELETE /v1/pdv/{id}/
Escopo necessário: pdv: delete
Fecha o caixa (soft delete). O registro não é removido permanentemente do banco de dados -- o status é alterado para fechado, preservando o histórico de operações.
Exemplo com cURL
bashcurl -X DELETE https://api-backend.bunto.com.br/v1/pdv/46/ \ -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}"} caixa_id = 46 resposta = requests.delete(f"{BASE_URL}/pdv/{caixa_id}/", headers=headers) dados = resposta.json() if dados["success"]: print("Caixa fechado com sucesso!") else: print(f"Erro ao fechar caixa: {dados}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const caixaId = 46; const resposta = await fetch(`${BASE_URL}/pdv/${caixaId}/`, { method: "DELETE", headers: { Authorization: `Bearer ${TOKEN}`, }, }); const dados = await resposta.json(); if (dados.success) { console.log("Caixa fechado com sucesso!"); } else { console.error(`Erro ao fechar caixa:`, dados); }
Resposta (200 OK)
json{ "success": true, "message": "Caixa fechado com sucesso" }
Importante: Caixas fechados não são removidos do banco de dados. Para visualizar caixas fechados, filtre por status=fechado. As sangrias, reforços e vendas vinculadas ao caixa são preservadas para fins de auditoria.
Erros Comuns
| Código | Erro | Causa | Solução |
|---|---|---|---|
| 400 | VALIDATION_ERROR | Dados enviados são inválidos (formato incorreto, tipo de dado errado, etc.) | Verifique os campos e os tipos de dados |
| 401 | Token invalido | Token ausente, expirado, revogado ou mal formatado | Verifique se o header é Authorization: Bearer bnt_xxx |
| 403 | Token nao tem permissao | O token não possui o escopo pdv ou a ação necessária (read, write, delete) | Verifique os escopos do token no painel |
| 404 | Nao encontrado | Abertura de caixa não existe ou pertence a outra empresa | Confirme o ID e se o caixa pertence à empresa do token |
| 429 | Limite de requisicoes excedido | Rate limit ultrapassado para o tipo de operação | Implemente retry com backoff exponencial |
Exemplo de Resposta de Erro (400)
json{ "success": false, "error": { "code": "VALIDATION_ERROR", "message": "Erro de validacao", "details": { "valor_ini": ["Um numero valido é necessario."] } } }
Exemplo de Resposta de Erro (403)
json{ "detail": "Token nao tem permissao para este recurso" }
Rate Limiting
A API aplica limites de requisição por token (não por IP). Cada tipo de operação tem um limite diferente.
| Operação | Métodos HTTP | Limite |
|---|---|---|
| Leitura | GET, HEAD, OPTIONS | 120 requisições/minuto |
| Escrita | POST, PUT, PATCH | 30 requisições/minuto |
| Exclusão | DELETE | 10 requisições/minuto |
Ao exceder o limite, a API retorna 429 Too Many Requests:
json{ "detail": "Limite de requisicoes excedido. Tente novamente em 45 segundos." }
Boas práticas
- Use
por_pagina=100para reduzir o número de requisições ao listar aberturas de caixa - Implemente retry com backoff exponencial ao receber
429 - Armazene dados em cache local quando possível
- Para atualizações em lote, use
PATCHapenas com os campos alterados para economizar requisições de escrita - Filtre por
statuse período (data_inicio/data_fim) para reduzir o volume de dados retornados
Paginação
Todos os endpoints de listagem retornam dados paginados.
Parâmetros
| 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 |
Atenção: 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 / null | URL da próxima página (null se for a última) |
anterior | string / null | URL da página anterior (null se for a primeira) |
Exemplo: percorrer todas as páginas (Python)
pythonimport requests BASE_URL = "https://api-backend.bunto.com.br/v1" TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4" headers = {"Authorization": f"Bearer {TOKEN}"} todos_os_caixas = [] url = f"{BASE_URL}/pdv/?por_pagina=100&status=aberto" while url: resposta = requests.get(url, headers=headers) dados = resposta.json() if not dados["success"]: break todos_os_caixas.extend(dados["data"]["resultados"]) url = dados["data"]["paginacao"]["proxima"] print(f"Total obtido: {len(todos_os_caixas)} aberturas de caixa")