Boleto Pay

Pays a boleto someone else issued. The account is the payer. Issuing a boleto for your own account is Boleto Issuance Guide.

Boleto is the other cash out available on v2 (on v1 these endpoints answered 503). There are three routes: one to read the boleto before paying, one to pay, and one to check the outcome.

Step 1: Preview (read the boleto)

Resolves the payment line at the partner and returns 200 with the details of the bill (beneficiary, payer, amount, due date) so you can show it before debiting.

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" }'

The canonical field is line; barcode is accepted as an alias. A boleto the partner cannot find returns 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"
}

Pay totalUpdated, not amount

amount is the face value — the very number encoded in the barcode. totalUpdated is what the settlement bank accepts today: face + interest + fine − discount.

On an overdue slip the two differ, and the settlement bank rejects any value other than the updated one (boleto_amount_mismatch). Since charges accrue by the day, yesterday’s totalUpdated is already stale: run the preview on the day you pay, and fund the account for the updated amount, not the face value.

Step 2: Pay

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": "ACME supplier"
}'
ParameterRequiredDescription
line (or barcode)YesPayment line / barcode
amountYesAmount to pay — the preview’s totalUpdated, not the face value
taxIdNoPayer’s CNPJ/CPF
scheduledNoScheduling, where the partner supports it
descriptionNoFree-text description

A divergent amount comes back as boleto_amount_mismatch (422), and the message carries the amount the settlement bank expects — re-run the preview and resend with it.

The response is always 202, never 200: the payment runs asynchronously and the body carries paymentId (= boletoId, shaped bol_{uuid}), status: "PROCESSING" and a Location header pointing at the status lookup.

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

The boletoId is derived from (accountId, Idempotency-Key), so repeating the request with the same key returns the same paymentId and reuses the run in flight — no double debit.

Step 3: Check the outcome

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

Accepts both the canonical paymentId (bol_...) and the partner reference. While the partner has not returned a reference yet, the route answers 200 with the last known local status (PROCESSING) instead of an error.

The outcome also arrives by webhook: boleto.paid and boleto.failed (see Webhooks). Settling a boleto can take hours — up to the next business day — so treat PROCESSING as a normal, long-lived state rather than a failure.