> ## Documentation Index
> Fetch the complete documentation index at: https://developers.portao3.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Pay a boleto

> Pay a bank boleto or a utility bill from a wallet: create the payment from its barcode, set its details, then confirm it

Paying a boleto is a flow of separate steps. You **create** the payment from the boleto's barcode, which looks the boleto up at the bank and tells you who you're paying and how much; you **set its details** if any are missing; then you **confirm** it, and only then the money moves. If your organization's business policies require approval for the payment, you **send it for approval** instead of confirming it — see [Business policies and approvals](https://developers.portao3.com.br/guides/policies-and-approvals.md).

## Flow

```mermaid theme={null}
sequenceDiagram
  participant You
  participant P3 as Portão 3
  You->>P3: POST .../boleto (create, with the barcode)
  P3->>You: _id, beneficiary, amount, policy — status REQUESTED
  opt category still missing, or another amount or day
    You->>P3: PUT .../boleto/{boletoId}
    P3->>You: details set, updated policy
  end
  You->>P3: POST .../boleto/{boletoId}/confirm
  P3->>You: status PAID
```

## Step 1: Create the payment

Send the boleto's **digitable line** (*linha digitável* — 47 digits for a bank boleto, 48 for a utility or tax bill) or its **barcode** (44 digits) in `barcode`. Send the digits; the check digits must be right.

```bash theme={null}
curl -X POST \
  'https://api.banking.v2.portao3.com.br/realms/{realmId}/organizations/{organizationId}/accounts/{accountId}/wallets/{walletId}/boleto' \
  -H 'Authorization: Bearer <accessToken>' \
  -H 'x-environment: LIVE' \
  -H 'Content-Type: application/json' \
  -d '{
    "barcode": "34191790011010435100147910201509416260000150000",
    "category": "FLEX_INTERNATIONAL",
    "description": "Folders da campanha de novembro"
  }'
```

| Field | Notes |
| - | - |
| `barcode` | The digitable line or the barcode. Required. |
| `amount` | In centavos. Leave it out to pay what the boleto asks for today (`txnUpdatedAmount`). |
| `category` | The wallet balance category to charge. With it, you can confirm right after creating. |
| `description` | A note kept with the payment. It isn't sent to the beneficiary. |
| `scheduledAt` | A later day to pay on (`YYYY-MM-DD`) — see [Pay on a later day](#pay-on-a-later-day). |
| `customFields` | Your organization's transaction custom fields, by `slug`. |

The boleto is looked up at the bank and the payment is created as `REQUESTED` — nothing is paid yet. Review who you're paying (`payee`, `payeeDocument`) and how much (`txnUpdatedAmount`) before going on:

```json theme={null}
{
  "_id": "6726b1c2b4d3e80012c9a4a1",
  "status": "REQUESTED",
  "type": "GENERIC",
  "barcode": "34194162600001500001790010104351004791020150",
  "payee": "Gráfica Aurora Ltda",
  "payeeDocument": "12345678000195",
  "issuer": "Itaú Unibanco S.A.",
  "dueDate": "2026-11-10T00:00:00.000Z",
  "txnOriginalAmount": 150000,
  "txnDiscountAmount": 0,
  "txnFineAmount": 0,
  "txnInterestAmount": 0,
  "txnUpdatedAmount": 150000,
  "pendingConfirmation": { "amount": 150000, "category": "FLEX_INTERNATIONAL", "description": "Folders da campanha de novembro" },
  "policy": { "actions": { "autoAction": "APPROVE" } }
}
```

Keep the payment's **`_id`** — it is the `{boletoId}` of every next step. `txnUpdatedAmount` is the face value (`txnOriginalAmount`) with today's discount, fine and interest applied. `pendingConfirmation` holds what will be paid, and `policy` what your organization's business policies say about it.

`type` tells the two kinds of boleto apart: `GENERIC` is a bank boleto, with a due date; `UTILITY_BILL` is a utility or tax bill (energy, water, phone, taxes).

> [!WARNING]
>
> A boleto that was already paid can't be paid again: creating the payment answers `422 ALREADY_PAID`, and nothing is created.

Reference: [Create a boleto payment](https://developers.portao3.com.br/api-reference/banking/boleto-payments/create-a-boleto-payment.md)

## Step 2: Set the details, if any are missing

Confirming pays exactly what `pendingConfirmation` holds, so it needs the **amount** and the **balance category**. The amount is usually known after creating — the one you sent, or else the one the boleto asks for (`txnUpdatedAmount`, or its face value when that is `0`); only a boleto that states no amount at all leaves it out. If the payment has both, skip this step. Otherwise — or to pay another amount, change the day or fill in custom fields — set them:

```bash theme={null}
curl -X PUT \
  'https://api.banking.v2.portao3.com.br/realms/{realmId}/organizations/{organizationId}/accounts/{accountId}/wallets/{walletId}/boleto/{boletoId}' \
  -H 'Authorization: Bearer <accessToken>' \
  -H 'x-environment: LIVE' \
  -H 'Content-Type: application/json' \
  -d '{
    "amount": 150000,
    "category": "FLEX_INTERNATIONAL"
  }'
```

`amount` and `category` are required here, and what you send replaces what was stored. A boleto that accepts a range of amounts takes one between `txnMinAmount` and `txnMaxAmount`; the bank checks the amount when the payment is confirmed. The answer carries an updated `policy`.

Reference: [Set a boleto payment's details](https://developers.portao3.com.br/api-reference/banking/boleto-payments/set-a-boleto-payments-details.md)

## Step 3: Confirm the payment

When `policy.actions.autoAction` is `APPROVE`, confirm the payment — with no body:

```bash theme={null}
curl -X POST \
  'https://api.banking.v2.portao3.com.br/realms/{realmId}/organizations/{organizationId}/accounts/{accountId}/wallets/{walletId}/boleto/{boletoId}/confirm' \
  -H 'Authorization: Bearer <accessToken>' \
  -H 'x-environment: LIVE'
```

A successful confirmation answers `200` with the payment `PAID`: the money left the wallet, and `confirmedAmount` and `confirmedAt` record it. If the bank refuses it — for insufficient funds or a limit, for example — the payment becomes `FAILED`, with the reason in `failReason`, and you get the error. A `FAILED` payment can't be retried: create another one.

When `autoAction` is `NONE`, the payment needs approval: [send it for approval](https://developers.portao3.com.br/guides/policies-and-approvals.md#step-3b-send-the-payment-for-approval) instead of confirming it. With `DENY`, the policies refuse it.

Reference: [Confirm a boleto payment](https://developers.portao3.com.br/api-reference/banking/boleto-payments/confirm-a-boleto-payment.md)

## Pay on a later day

Send `scheduledAt` (`YYYY-MM-DD`) when creating the payment, or with `PUT`, to pay on a later day. The confirmation then answers `201` with the schedule, and the payment becomes `SCHEDULED`; on that day a new payment is created from the same barcode and paid.

* A **bank boleto** (`GENERIC`) can only be scheduled for its due date — or, when the due date falls on a weekend or holiday, the next business day. Any other later day is refused with `422 SCHEDULED_AT_NOT_ALLOWED`, whose message names the allowed day. A bank boleto with no due date can be scheduled for any business day.
* A **utility or tax bill** (`UTILITY_BILL`) can be scheduled for any later day.
* A day before today is refused with `422 INVALID_SCHEDULED_AT`. At creation, today or no `scheduledAt` pays as soon as the payment is confirmed. With `PUT`, leaving `scheduledAt` out keeps the day already set; send today to pay as soon as it is confirmed again.
* On that day the new payment is charged to the general-purpose balance category (`FLEX_INTERNATIONAL`), whatever `category` you set, and it carries none of the payment's custom fields — so it fails if your organization has a required transaction custom field. Pay those boletos on the day instead.
* A later-day payment's amount must be one the boleto accepts (between `txnMinAmount` and `txnMaxAmount`, when it states them); otherwise the confirmation is refused with `400 INVALID_AMOUNT` and nothing is scheduled.

## Cancel a payment

A payment that wasn't paid yet — `REQUESTED`, waiting for approval, or `SCHEDULED` — can be [cancelled](https://developers.portao3.com.br/api-reference/banking/boleto-payments/cancel-a-boleto-payment.md). Cancelling a scheduled payment cancels its schedule too:

```bash theme={null}
curl -X POST \
  'https://api.banking.v2.portao3.com.br/realms/{realmId}/organizations/{organizationId}/accounts/{accountId}/wallets/{walletId}/boleto/{boletoId}/cancel' \
  -H 'Authorization: Bearer <accessToken>' \
  -H 'x-environment: LIVE'
```

## Common errors

Errors come in the [error envelope](https://developers.portao3.com.br/index.md#errors) with a stable `code`. When the bank refuses a boleto, `code` carries the bank's reason — some reasons come in lowercase, with the message `Unknown error`, so branch on `code`, not on the message.

| Status | `code` | When | What to do |
| - | - | - | - |
| `422` | `BAD_REQUEST` | A field is invalid — for example a `barcode` with wrong check digits. `fields` lists each one. | Fix the request. |
| `422` | `ALREADY_PAID` | The boleto was already paid. | Nothing to pay. |
| `422` | `barcode_not_found` | The bank found no boleto with this barcode. | Check the barcode. |
| `422` | `cannot_be_paid_after_expiration_date` | The boleto's last day to be paid has passed. | Ask the beneficiary for a new boleto. |
| `422` | `SCHEDULED_AT_NOT_ALLOWED` | A bank boleto scheduled for a day other than its due date. | Use the day the message names, or pay today. |
| `422` | `PAYMENT_PARAMETERS_MISSING` | The amount or the balance category isn't set yet. | Set them with `PUT`. |
| `422` | `CUSTOM_FIELD_INVALID_VALUE` | A custom field value is invalid, or a required one is empty. | Fix it with `PUT`. |
| `403` | `BOLETO_REQUIRES_APPROVAL` | A policy requires approval. | [Send it for approval](https://developers.portao3.com.br/guides/policies-and-approvals.md#step-3b-send-the-payment-for-approval). |
| `422` | `INSUFFICIENT_FUNDS` | The wallet's balance doesn't cover the amount. The payment is now `FAILED`. | Fund the wallet and create another payment. |
| `422` | `LIMIT_EXCEEDED` | The payment is above a transaction limit. The payment is now `FAILED`. | Create another payment within the limit. |
| `409` | `INVALID_BANK_SLIP_STATE` | The payment was already paid, scheduled, cancelled or failed. | Read the payment. |
| `500` / `502` / `503` / `504` | `BANKING_PROVIDER_UNAVAILABLE` | The bank didn't answer. | Retry. If it happened while confirming, check the wallet's statement before paying again. |

Each endpoint's reference page lists every error it can return.

## Follow a payment

[Read the payment](https://developers.portao3.com.br/api-reference/banking/boleto-payments/get-a-boleto-payment.md) to see its `status`, or [list a wallet's boleto payments](https://developers.portao3.com.br/api-reference/banking/boleto-payments/list-a-wallets-boleto-payments.md) — filter by `status`, for example `?status=PAID,FAILED`. To be notified, subscribe to the `BANK_SLIP_PAID` [webhook](https://developers.portao3.com.br/guides/webhooks.md), sent when a boleto is paid from a wallet.

## Next steps

> [card] [Business policies and approvals](https://developers.portao3.com.br/guides/policies-and-approvals.md)
>
> Send payments for approval when your organization's policies require it.

> [card] [Send a Pix payment](https://developers.portao3.com.br/guides/send-pix.md)
>
> Pay by Pix key, QR code or bank details.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.