> ## 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.

# Charge with a boleto

> Issue a boleto that charges a customer, share its digitable line or PDF, and know when it's paid

To receive money by boleto, create a **boleto charge** (`boleto-billing`) on a wallet. Portão 3 registers the boleto at the bank and returns its digitable line and barcode, which you share with the payer — or send them the boleto's PDF. When they pay, the amount is credited to the wallet. A boleto charge has no webhook: read it back to follow it.

## Flow

```mermaid theme={null}
sequenceDiagram
  participant You
  participant P3 as Portão 3
  participant Payer
  participant Bank
  You->>P3: POST .../boleto-billing
  P3->>You: 201 CREATED (digitableLine, barcode)
  You->>P3: GET .../boleto-billing/{boletoId}/download/pdf
  You->>Payer: Digitable line or PDF
  Payer->>Bank: Pay
  Bank->>P3: Payment received
  You->>P3: GET .../boleto-billing/{boletoId} (until status PAID)
```

## Step 1: Create the charge

```bash theme={null}
curl -X POST \
  'https://api.banking.v2.portao3.com.br/realms/{realmId}/organizations/{organizationId}/accounts/{accountId}/wallets/{walletId}/boleto-billing' \
  -H 'Authorization: Bearer <accessToken>' \
  -H 'x-environment: LIVE' \
  -H 'Content-Type: application/json' \
  -d '{
    "txnCurrency": "986",
    "txnAmount": 150000,
    "txnDivergentAmountType": "NOT_ALLOW_DIFFERENT_AMOUNT",
    "dueDate": "2026-11-20",
    "expiresAt": "2026-12-20",
    "description": "Mensalidade de novembro",
    "customer": {
      "name": "Padaria Pão Dourado Ltda",
      "document": "11222333000181",
      "address": {
        "street": "Rua das Laranjeiras",
        "number": "250",
        "complement": "Loja 2",
        "neighborhood": "Centro",
        "postalCode": "01310-100",
        "city": "São Paulo",
        "state": "SP"
      }
    }
  }'
```

| Field | Notes |
| - | - |
| `txnCurrency` | `986` (Brazilian real) — the only currency a boleto takes. |
| `txnAmount` | In centavos, up to `24999900` (R\$ 249,999.00). |
| `txnDivergentAmountType` | Send `NOT_ALLOW_DIFFERENT_AMOUNT`. The boleto is always issued for exactly `txnAmount`: the payer can't pay a different amount, whatever you send. |
| `dueDate` | The due date (`YYYY-MM-DD`): today or later. |
| `expiresAt` | The last day the boleto can be paid (`YYYY-MM-DD`), after `dueDate`. |
| `description` | A description of the charge. |
| `customer` | The payer: `name`, `document` (a CPF or CNPJ) and `address`, with the CEP formatted `00000-000` and the two-letter state code. |
| `txnDiscountAmount`, `txnFineAmount`, `txnInterestAmount` | Optional — see [Discount, fine and interest](#discount-fine-and-interest). |

The bank registers the boleto right away, so the charge comes back `CREATED`, with the `digitableLine` and `barcode`:

```json theme={null}
{
  "_id": "6727c3d4b4d3e80012c9b5c2",
  "status": "CREATED",
  "digitableLine": "34191090080123456789001234567890116210000150000",
  "barcode": "34191162100001500001090000012345678901234567",
  "txnAmount": 150000,
  "txnDivergentAmountType": "NOT_ALLOW_DIFFERENT_AMOUNT",
  "dueDate": "2026-11-20T00:00:00.000Z",
  "expiresAt": "2026-12-20T00:00:00.000Z",
  "customer": {
    "name": "Padaria Pao Dourado Ltda",
    "document": "11222333000181",
    "address": { "street": "Rua das Laranjeiras", "number": "250", "complement": "Loja 2", "neighborhood": "Centro", "postalCode": "01310-100", "city": "Sao Paulo", "state": "SP" }
  },
  "confirmedAmount": 0
}
```

The payer's name and address are printed on the boleto as the bank keeps them — without accents, with the name cut to 50 characters, the street to 40 and the neighborhood to 20 — and the charge shows them that way.

Rarely, the charge comes back `INITIATED`, still without `digitableLine` and `barcode`: [read it back](https://developers.portao3.com.br/api-reference/banking/boleto-billing/get-a-boleto-charge.md) until it is `CREATED`.

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

## Step 2: Share the boleto

Show the payer the `digitableLine` (*linha digitável*), which they type into their bank app, or render the `barcode`. To send them the boleto itself, download its PDF. The response is the PDF file encoded in base64, as plain text — decode it to save the file:

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

In a browser, prefix the text with `data:application/pdf;base64,` to open or download it.

Reference: [Download a boleto charge's PDF](https://developers.portao3.com.br/api-reference/banking/boleto-billing/download-a-boleto-charges-pdf.md)

## Step 3: Know when it's paid

There is no webhook for a boleto charge. [Read the charge](https://developers.portao3.com.br/api-reference/banking/boleto-billing/get-a-boleto-charge.md) to follow its `status`, or [list the wallet's charges](https://developers.portao3.com.br/api-reference/banking/boleto-billing/list-a-wallets-boleto-charges.md) filtered by status — for example `?status=PAID`. A paid charge carries what was credited to the wallet in `confirmedAmount` (with any discount, fine or interest applied) and when in `confirmedAt`; the payment also appears in the wallet's transactions.

| Status | Meaning |
| - | - |
| `CREATED` | Registered and payable. |
| `PAID` | Paid, and credited to the wallet. |
| `CANCELED` | Written off unpaid by the bank, some weeks after `expiresAt`. It can't be paid anymore. |
| `INITIATED`, `REQUESTED`, `ENQUEUED` | Being registered at the bank, without a barcode yet. |
| `PROCESSING` | Being issued. A charge left `PROCESSING` after its creation answered an error never gets a barcode — see [Errors](#errors) before creating it again. |
| `PROCESSING_PAYMENT` | Paid and being credited. |
| `ERROR` | The bank couldn't issue it. |

A charge can't be cancelled through the API: an unpaid boleto stays payable until `expiresAt`, and the bank then writes it off (`CANCELED`).

## Discount, fine and interest

Amounts are in centavos. Percentages are **fractions** of `txnAmount`: `0.02` is 2%, from `0.01` (1%) to `1` (100%).

```json theme={null}
{
  "txnDiscountAmount": [
    { "date": "2026-11-15", "amount": 0.05, "amountType": "PERCENT_UNTIL_INFORMED_DATE" }
  ],
  "txnFineAmount": { "date": "2026-11-21", "amount": 0.02, "amountType": "PERCENT" },
  "txnInterestAmount": { "date": "2026-11-21", "amount": 0.01, "amountType": "PERCENT_POINT_PER_MONTH_CALENDAR_DAYS" }
}
```

| Rule | Types | Notes |
| - | - | - |
| Discount (a list) | `FIXED_AMOUNT_UNTIL_INFORMED_DATE`, `PERCENT_UNTIL_INFORMED_DATE` — when paid by `date`. `AMOUNT_PER_ANTICIPATION_*`, `PERCENT_PER_ANTICIPATION_*` — per calendar or working day paid early. | Each `date` must be before `dueDate`. |
| Fine | `PERCENT`, `FIXED_VALUE` | Charged once, from `date`, which must be after `dueDate`. |
| Interest | `AMOUNT_CALENDAR_DAYS`, `AMOUNT_WORKING_DAYS` — centavos per day late, below 3.3% of `txnAmount`. `PERCENT_POINT_PER_MONTH_CALENDAR_DAYS`, `PERCENT_POINT_PER_MONTH_WORKING_DAYS` — a monthly rate. | Accrues from `date`, which must be after `dueDate`. |

> [!WARNING]
>
> `PERCENT_POINT_PER_DAY_CALENDAR_DAYS` and `PERCENT_POINT_PER_DAY_WORKING_DAYS` are accepted, but the boleto is issued with the same number as a rate **per month**: `0.01` is charged as 1% a month, not 1% a day. The charge comes back with the matching `PERCENT_POINT_PER_MONTH_*` type. Send a monthly rate instead.

## Errors

| Status | `code` | Meaning | What to do |
| - | - | - | - |
| `422` | `BAD_REQUEST` | A field is invalid; `fields` lists each one. | Fix the request. |
| `400` | `ACCOUNT_LIMITS_EXCEEDED` | Receiving by boleto is turned off for the account, or `txnAmount` is above its maximum per boleto. | Lower the amount, or contact support. |
| `400` | `ACCOUNT_NOT_OPEN` · `WALLET_NOT_ACTIVE` | The account isn't open, or the wallet isn't `ACTIVE`. | Use an active wallet. |
| `422` | `BANKING_PROVIDER_VALIDATION_ERROR` | The bank rejected a field; `fields` names it when the bank says which. | Fix the field and create the charge again. |
| `500` / `502` / `503` / `504` | `BANKING_PROVIDER_UNAVAILABLE` · `BANKING_PROVIDER_INTEGRATION_ERROR` | The bank didn't answer, or its answer couldn't be read. The charge is left `PROCESSING`, without a barcode — but the bank may have registered the boleto anyway, and the payer could find it in their bank's app. | Contact support before creating the charge again, so the payer isn't charged twice. |

When the bank refuses the boleto (a `4xx`), the charge is also left `PROCESSING`; creating it again is safe. Each endpoint's reference page lists every error it can return.

## Next steps

> [card] [Charge with PIX](https://developers.portao3.com.br/guides/collect-pix.md)
>
> Generate a Pix QR Code instead.

> [card] [Recurring billing with Pix Automático](https://developers.portao3.com.br/guides/pix-automatico.md)
>
> Charge a customer every month, with a boleto as the fallback.


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