Boleto Pay

Paga um boleto emitido por outra pessoa. A conta é o pagador. Emitir um boleto da própria conta é Boleto Charge.

Boleto é o outro cash out disponível na v2 (na v1 esses endpoints respondiam 503). São três rotas: uma para ler o boleto antes de pagar, uma para pagar e uma para consultar o resultado.

Passo 1: Preview (ler o boleto)

Resolve a linha digitável no parceiro e devolve 200 com os dados do título (beneficiário, pagador, valores, vencimento) para você exibir antes de debitar.

curl -X POST "${API_URL}/v1/accounts/${ACCOUNT_ID}/boleto/preview" \
-H "Authorization: Bearer ${JWT}" \
-H "X-Tenant-Id: ${TENANT_ID}" \
-H "Content-Type: application/json" \
-d '{ "line": "34191790010104351004791020150008291070026000" }'

O campo canônico é line; barcode é aceito como alias. Boleto não encontrado no parceiro devolve 404 not_found.

{
"type": "boleto-payment",
"bank": "Itaú Unibanco S.A.",
"bankCode": "341",
"receiverName": "FORNECEDOR EXEMPLO LTDA",
"receiverTaxId": "12345678000190",
"dueDate": "2026-08-10",
"amount": 1430.63,
"discountAmount": 0,
"interestAmount": 3.29,
"fineAmount": 28.61,
"totalUpdated": 1462.53,
"status": "PAYABLE"
}

Pague o totalUpdated, não o amount

amount é o valor de face — o mesmo número que está gravado no código de barras. totalUpdated é o que o liquidante aceita hoje: face + juros + multa − desconto.

Em título vencido os dois diferem, e o liquidante recusa qualquer valor que não seja o atualizado (boleto_amount_mismatch). Como os encargos correm por dia, o totalUpdated de ontem já não serve: faça o preview no dia do pagamento, e garanta saldo para o valor atualizado, não para o de face.

Passo 2: Pagar

curl -X POST "${API_URL}/v1/accounts/${ACCOUNT_ID}/boleto/pay" \
-H "Authorization: Bearer ${JWT}" \
-H "X-Tenant-Id: ${TENANT_ID}" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"line": "34191790010104351004791020150008291070026000",
"amount": 1462.53,
"taxId": "12345678000199",
"description": "Fornecedor ACME"
}'
ParâmetroObrigatórioDescrição
line (ou barcode)SimLinha digitável / código de barras
amountSimValor a pagar — o totalUpdated do preview, não o valor de face
taxIdNãoCNPJ/CPF do pagador
scheduledNãoAgendamento (quando o parceiro suportar)
descriptionNãoDescrição livre

Valor divergente volta como boleto_amount_mismatch (422), e a mensagem traz o valor que o liquidante espera — refaça o preview e reenvie com ele.

A resposta é sempre 202, nunca 200: o pagamento roda de forma assíncrona e o corpo traz paymentId (= boletoId, no formato bol_{uuid}), status: "PROCESSING" e um header Location apontando para a consulta de status.

{
"paymentId": "bol_aabbccdd-...",
"boletoId": "bol_aabbccdd-...",
"idempotencyKey": "...",
"amount": 250.00,
"status": "PROCESSING"
}

O boletoId é derivado de (accountId, Idempotency-Key), então repetir a requisição com a mesma chave devolve o mesmo paymentId e reaproveita a execução em curso — sem débito duplicado.

Passo 3: Consultar o resultado

curl -X GET "${API_URL}/v1/accounts/${ACCOUNT_ID}/boleto/payments/bol_aabbccdd-..." \
-H "Authorization: Bearer ${JWT}" \
-H "X-Tenant-Id: ${TENANT_ID}"

Aceita tanto o paymentId canônico (bol_...) quanto a referência do parceiro. Enquanto o parceiro ainda não devolveu a referência, a rota responde 200 com o último status local conhecido (PROCESSING) em vez de erro.

O desfecho também chega por webhook: boleto.paid e boleto.failed (ver Webhooks). A compensação de um boleto pode levar horas — até o dia útil seguinte — então trate PROCESSING como estado normal e prolongado, não como falha.