Pular para o conteúdo principal

Obter boleto de uma parcela de acordo

Cenário: o titular pediu o boleto da próxima parcela do acordo dele. Sua integração precisa baixar o PDF e entregar pelo canal de atendimento (download, WhatsApp, e-mail).

Escopo necessário: financeiro.read.

Existem dois endpoints:

EndpointQuando usar
GET /v1/acordos/{idAcordo}/parcelas/{idParcela}/boletoBoleto de uma parcela específica do acordo
GET /v1/acordos/{idAcordo}/boleto-consolidadoBoleto consolidado do acordo todo (uma cobrança única)

Ambos retornam o PDF como base64 inline no JSON, junto com o nome de arquivo sugerido:

{
"nomeArquivo": "Boleto_8aa4b425_parcela_1.pdf",
"conteudoPdf": "JVBERi0xLjQK..."
}

Rate limit pesado

Os dois endpoints são rate-limited com concorrência reduzida (categoria pesada em Pontos de atenção). Renderizar um PDF é mais custoso do que uma consulta simples ao banco. Em integrações que geram vários boletos:

  • Serialize as chamadas: uma de cada vez, ou no máximo duas em paralelo.
  • Se receber 429, respeite o Retry-After.
  • Não chame esses endpoints em background loops sem throttle.

Implementação

import base64
from banqer_client import call

def baixar_boleto_parcela(id_acordo: str, id_parcela: str, dir_destino: str = "."):
"""Baixa o PDF de uma parcela e salva em disco. Retorna o caminho do arquivo."""
resp = call("GET",
f"/v1/acordos/{id_acordo}/parcelas/{id_parcela}/boleto")

nome = resp["nomeArquivo"]
pdf_bytes = base64.b64decode(resp["conteudoPdf"])

caminho = f"{dir_destino}/{nome}"
with open(caminho, "wb") as f:
f.write(pdf_bytes)
return caminho


def baixar_boleto_consolidado(id_acordo: str, dir_destino: str = "."):
resp = call("GET", f"/v1/acordos/{id_acordo}/boleto-consolidado")
nome = resp["nomeArquivo"]
pdf_bytes = base64.b64decode(resp["conteudoPdf"])
caminho = f"{dir_destino}/{nome}"
with open(caminho, "wb") as f:
f.write(pdf_bytes)
return caminho


# Uso
arquivo = baixar_boleto_parcela(
id_acordo="20f4b12d-d603-471c-9254-fc52ae52cf44",
id_parcela="34190000-5dda-0015-aafb-08dcc60de8a6",
)
print(f"Salvo em: {arquivo}")

Listagem das parcelas para escolher qual baixar

Antes de baixar o boleto, normalmente você consulta as parcelas do acordo para mostrar ao titular qual está em aberto:

parcelas_resp = call("GET", f"/v1/acordos/{id_acordo}/parcelas")
em_aberto = [p for p in parcelas_resp["parcelas"]
if not p.get("quitada", False)]
print(f"Parcelas em aberto: {len(em_aberto)}")
for p in em_aberto:
print(f" Parcela {p['numeroParcela']} - "
f"venc {p['dataVencimento'][:10]} - "
f"R$ {p['valorParcela']:.2f}")

Pontos importantes

  • A API não emite boleto novo no banco. Esses endpoints projetam em PDF os dados de boletos já registrados pelo sistema Banqer no momento da quitação do acordo. Não há efeito colateral.
  • O conteúdo do PDF é o mesmo dentro de um mesmo acordo até alguma alteração legítima (reemissão pelo operador, mudança de banco). Você pode cachear localmente por algumas horas se isso for útil para reduzir chamadas.
  • Boleto consolidado vs parcela: o consolidado tem uma única linha digitável que liquida todas as parcelas em aberto de uma vez. A parcela tem a linha digitável específica daquele vencimento. Use o consolidado quando o titular quer quitar tudo, a parcela quando quer pagar uma específica.
  • Tamanho típico: cada PDF tem de 30 a 80 KB. Em base64, o JSON da resposta fica em torno de 40 a 110 KB.
  • Erros de validação: se a parcela já foi quitada ou está fora de uma janela emissível, a API retorna 412 Precondition Failed com reason: PRECONDITION_FAILED. Trate isso na interface para informar o titular sem confundir com erro técnico.