API de NFS-e
Consulta de notas fiscais de serviço via API (somente leitura).
Consulte as notas fiscais de serviço eletrônicas (NFS-e) emitidas no Bunto ERP. Este endpoint permite listar e consultar NFS-e via API.
Endpoint somente leitura. Não é possível criar, atualizar ou excluir NFS-e por esta API. A emissão de notas fiscais de serviço é realizada exclusivamente pelo painel do Bunto ERP.
Base URL
Produção:
https://api-backend.bunto.com.br/v1/nfse/
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: nfse com a ação read.
Endpoints
Listar NFS-e
GET /v1/nfse/
Escopo necessário: nfse: read
Retorna a lista paginada de notas fiscais de serviço 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 número da NFS-e, número do RPS ou código de verificação |
status | string | - | Filtrar por status: PENDENTE, PROCESSANDO, EMITIDA, REJEITADA, CANCELADA |
cliente_id | integer | - | Filtrar por ID do cliente vinculado |
data_inicio | date | - | Data inicial do período (formato: AAAA-MM-DD) |
data_fim | date | - | Data final do período (formato: AAAA-MM-DD) |
ordenar | string | criado_em | Campo de ordenação: numero_nfse, criado_em, status |
direcao | string | desc | Direção da ordenação: asc ou desc |
Exemplo com cURL
bashcurl 'https://api-backend.bunto.com.br/v1/nfse/?pagina=1&por_pagina=10&status=EMITIDA&ordenar=criado_em&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 NFS-e emitidas ordenadas por data de criacao resposta = requests.get( f"{BASE_URL}/nfse/", headers=headers, params={ "pagina": 1, "por_pagina": 25, "status": "EMITIDA", "ordenar": "criado_em", "direcao": "desc", }, ) dados = resposta.json() if dados["success"]: notas = dados["data"]["resultados"] paginacao = dados["data"]["paginacao"] print(f"Total de NFS-e: {paginacao['total_registros']}") for nota in notas: print(f" - NFS-e {nota['numero_nfse']} | RPS {nota['numero_rps']} | {nota['status']} | R$ {nota['valor_servico']} | {nota['cliente_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: "EMITIDA", ordenar: "criado_em", direcao: "desc", }); const resposta = await fetch(`${BASE_URL}/nfse/?${params}`, { headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", }, }); const dados = await resposta.json(); if (dados.success) { const notas = dados.data.resultados; const paginacao = dados.data.paginacao; console.log(`Total de NFS-e: ${paginacao.total_registros}`); notas.forEach((nota) => { console.log(` - NFS-e ${nota.numero_nfse} | RPS ${nota.numero_rps} | ${nota.status} | R$ ${nota.valor_servico} | ${nota.cliente_nome}`); }); } else { console.error(`Erro: ${resposta.status}`); }
Resposta (200 OK)
json{ "success": true, "message": "3 registros encontrados", "data": { "resultados": [ { "id": 78, "numero_rps": 456, "serie_rps": "RPS", "numero_nfse": 1234, "codigo_verificacao": "ABC1D2E3", "status": "EMITIDA", "cliente_id": 42, "cliente_nome": "Loja Centro Ltda", "valor_servico": "2500.00", "data_emissao": "2026-02-10T14:30:00-03:00", "data_autorizacao": "2026-02-10T14:31:45-03:00" }, { "id": 72, "numero_rps": 455, "serie_rps": "RPS", "numero_nfse": 1233, "codigo_verificacao": "XYZ9W8V7", "status": "EMITIDA", "cliente_id": 18, "cliente_nome": "Maria Silva Confecções ME", "valor_servico": "850.00", "data_emissao": "2026-02-08T10:15:00-03:00", "data_autorizacao": "2026-02-08T10:16:30-03:00" }, { "id": 65, "numero_rps": 454, "serie_rps": "RPS", "numero_nfse": null, "codigo_verificacao": null, "status": "PENDENTE", "cliente_id": 55, "cliente_nome": "Tech Solutions SA", "valor_servico": "4200.00", "data_emissao": "2026-02-05T09:00:00-03:00", "data_autorizacao": null } ], "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 NFS-e |
numero_rps | integer / null | Número do RPS (Recibo Provisório de Serviço) |
serie_rps | string | Série do RPS |
numero_nfse | integer / null | Número da NFS-e atribuído pela prefeitura (null se ainda não emitida) |
codigo_verificacao | string / null | Código de verificação da NFS-e (null se ainda não emitida) |
status | string | Status atual: PENDENTE, PROCESSANDO, EMITIDA, REJEITADA, CANCELADA |
cliente_id | integer / null | ID do cliente vinculado (null se não houver) |
cliente_nome | string / null | Nome do cliente vinculado |
valor_servico | string | Valor do serviço em formato decimal (ex: "2500.00") |
data_emissao | datetime / null | Data e hora de emissão (extraída dos dados do RPS) |
data_autorizacao | datetime / null | Data e hora da autorização pela prefeitura |
Obter NFS-e
GET /v1/nfse/{id}/
Escopo necessário: nfse: read
Retorna os dados completos de uma nota fiscal de serviço específica, incluindo dados do serviço e totais.
Exemplo com cURL
bashcurl https://api-backend.bunto.com.br/v1/nfse/78/ \ -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", } nfse_id = 78 resposta = requests.get(f"{BASE_URL}/nfse/{nfse_id}/", headers=headers) dados = resposta.json() if dados["success"]: nfse = dados["data"] print(f"NFS-e {nfse['numero_nfse']} - RPS {nfse['numero_rps']}") print(f"Status: {nfse['status']}") print(f"Valor do servico: R$ {nfse['valor_servico']}") print(f"Codigo de verificacao: {nfse['codigo_verificacao']}") if nfse["dados_servico"]: print(f"Descricao do servico: {nfse['dados_servico'].get('descricao', '')}") else: print(f"Erro: {dados}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const nfseId = 78; const resposta = await fetch(`${BASE_URL}/nfse/${nfseId}/`, { headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", }, }); const dados = await resposta.json(); if (dados.success) { const nfse = dados.data; console.log(`NFS-e ${nfse.numero_nfse} - RPS ${nfse.numero_rps}`); console.log(`Status: ${nfse.status}`); console.log(`Valor do servico: R$ ${nfse.valor_servico}`); console.log(`Codigo de verificacao: ${nfse.codigo_verificacao}`); if (nfse.dados_servico) { console.log(`Descricao do servico: ${nfse.dados_servico.descricao ?? ""}`); } } else { console.error(`Erro: ${JSON.stringify(dados)}`); }
Resposta (200 OK)
json{ "success": true, "message": "Registro encontrado", "data": { "id": 78, "numero_rps": 456, "serie_rps": "RPS", "numero_nfse": 1234, "codigo_verificacao": "ABC1D2E3", "status": "EMITIDA", "cliente_id": 42, "cliente_nome": "Loja Centro Ltda", "valor_servico": "2500.00", "data_emissao": "2026-02-10T14:30:00-03:00", "data_autorizacao": "2026-02-10T14:31:45-03:00", "chave_acesso": "NFSe-SP-2026-ABC1D2E3", "origem_tipo": "ORDEM_SERVICO", "protocolo_autorizacao": "SP20260210143145", "dados_servico": { "codigo_servico": "1.05", "descricao":"Servico de consultoria em tecnologia da informacao", "cnae": "6201500", "codigo_tributacao_municipio": "010500", "aliquota_iss": "5.00" }, "totais": { "valor_servico": "2500.00", "valor_deducoes": "0.00", "valor_pis": "16.25", "valor_cofins": "75.00", "valor_ir": "37.50", "valor_csll": "25.00", "valor_iss": "125.00", "valor_liquido": "2221.25" }, "data_criacao": "2026-02-10T14:28:00-03:00", "data_atualizacao": "2026-02-10T14:31:45-03:00" } }
Campos do Detalhe (adicionais à listagem)
| Campo | Tipo | Descrição |
|---|---|---|
chave_acesso | string / null | Chave de acesso da NFS-e (formato varia por município) |
origem_tipo | string | Origem da NFS-e: ORDEM_SERVICO, MANUAL, etc. |
protocolo_autorizacao | string / null | Protocolo de autorização retornado pela prefeitura |
dados_servico | object | Dados do serviço prestado (código, descrição, CNAE, alíquota ISS, etc.) |
totais | object | Valores totais da NFS-e (serviço, deduções, impostos retidos, valor líquido) |
data_criacao | datetime | Data e hora de criação do registro |
data_atualizacao | datetime | Data e hora da última atualização |
Erros Comuns
| Código | Erro | Causa | Solução |
|---|---|---|---|
| 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 nfse ou a ação read | Verifique os escopos do token no painel |
| 404 | Nao encontrado | NFS-e não existe ou pertence a outra empresa | Confirme o ID e se a NFS-e pertence à empresa do token |
| 429 | Limite de requisicoes excedido | Rate limit ultrapassado | Implemente retry com backoff exponencial |
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).
| Operação | Métodos HTTP | Limite |
|---|---|---|
| Leitura | GET, HEAD, OPTIONS | 120 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 NFS-e - Implemente retry com backoff exponencial ao receber
429 - Armazene dados em cache local quando possível
- Utilize os filtros
data_inicioedata_fimpara limitar 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}"} todas_as_nfse = [] url = f"{BASE_URL}/nfse/?por_pagina=100&status=EMITIDA" while url: resposta = requests.get(url, headers=headers) dados = resposta.json() if not dados["success"]: break todas_as_nfse.extend(dados["data"]["resultados"]) url = dados["data"]["paginacao"]["proxima"] print(f"Total obtido: {len(todas_as_nfse)} NFS-e")