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

# Boleto best practices

> Understand how a boleto behaves after creation, from the embedded Pix QR code and the document lifecycle to webhooks, due dates, refunds and rate limits.

This guide collects the behaviors of a Trio boleto that go beyond creating the document: the embedded Pix QR code, payer data, the lifecycle, webhooks, due date versus expiration date, refunds and rate limits. It complements the [Create a boleto](https://docs.trio.com.br/v2/guides/boleto/create-boleto.md) guide and does not replace the [Create boleto](https://docs.trio.com.br/v2/api-reference/banking-api/receivables/boletos/post.md) API reference. All endpoints use the sandbox base URL `https://api.sandbox.trio.com.br`.

## Hybrid boleto: boleto and Pix

Every boleto created through Trio also carries an embedded Pix QR code. The payer chooses between paying with the traditional boleto data (barcode or digitable line) or through Pix.

### Getting the Pix code of a boleto

`POST /v2/in/boletos` does not return the BR code (the Pix copy-and-paste code) directly. After creating the boleto:

1. Take the `id` returned in `data.id`.
2. Read the QR code with [`GET /v2/in/pix/qrcodes/{id}`](https://docs.trio.com.br/v2/api-reference/banking-api/receivables/pix/qrcode-dynamic/get), using that same `id`.

```http theme={null}
GET /v2/in/pix/qrcodes/{id}
```

The BR code comes in the `data.hash` field of the response.

### Identifying a payment made through Pix

When the boleto is paid through its Pix QR code, the in document Trio creates for the payment (the receivable, returned by [`GET /v2/documents/in/{id}`](https://docs.trio.com.br/v2/api-reference/banking-api/documents/receivables/get-receivable)) has the type `pix_boleto`. The document `type` tells the two payment methods apart: `boleto` and `pix_boleto` are distinct values of the enum.

The payment is delivered through the `in_document` webhook with:

```json theme={null}
{
  "type": "pix_boleto"
}
```

This lets you tell a payment made through the boleto's Pix QR code from a traditional boleto payment.

**Best practice:** treat `type = pix_boleto` as a payment that originated through Pix, and keep reconciling by `id` and `external_id`.

## Payer data

The `counterparty` object carries the address fields the boleto document needs:

* `address`
* `district`
* `city`
* `state`
* `postal_code`

All of them are required at creation, together with `name` and `tax_number`. In the response, the payer comes back as `counterparty.id`, the identifier Trio assigns to it.

### Is the address validated?

No. Trio does not validate whether the address in `counterparty` exists or matches the payer. The fields are there to fill in the information the document requires. Even so, send the payer's real and correct data whenever you have it.

**Best practice:** do not use generic addresses or made-up data just to satisfy the schema. If your checkout does not collect an address today, decide how you will obtain it before issuing boletos.

## Boleto lifecycle

A boleto follows the document lifecycle Trio uses for every document, described in [Document lifecycle](https://docs.trio.com.br/v2/guides/pix/document-lifecycle.md):

```text theme={null}
Created
   ↓
Confirmed
   ↓
Settled
```

### Main statuses

| Status | Meaning |
| - | - |
| `created` | Boleto created |
| `confirmed` | Boleto registered and confirmed |
| `settled` | Boleto paid (settled) |
| `onhold` | Boleto on hold |
| `refunded` | Boleto payment refunded |
| `failed` | Boleto processing failed |
| `cancelled` | Boleto cancelled (through [`POST /v2/in/boletos/{id}/cancel`](https://docs.trio.com.br/v2/api-reference/banking-api/receivables/boletos/cancel) or by recreation) |

`settled` is the status of a paid boleto.

After the `expiration_date`, the boleto moves to `expired` and can no longer be paid.

> [!WARNING]
>
> Do not treat the existence of a boleto as confirmation of payment. Confirm payment from the settlement status or event your integration receives.

## Webhooks

Webhooks are registered through [`POST /v2/webhooks`](https://docs.trio.com.br/v2/api-reference/banking-api/developers/webhooks/create-webhook). The `api_version` field (`v100` or `v200`) sets the version of the event payloads you receive. The examples below are from version `v100`; the [events overview](https://docs.trio.com.br/v2/webhooks/events/overview.md) lists the available events.

The `in_document` webhook communicates events related to receiving the boleto.

When the boleto is paid through the embedded Pix, the `type` you receive is:

```text theme={null}
pix_boleto
```

The `external_id` you sent when creating the boleto also comes back in the webhooks.

### Does expiration trigger a webhook?

No. There is no webhook event whose only purpose is to tell you a boleto has expired. Track expiration in your own integration when you need it.

After the `expiration_date`, the boleto status changes to:

```text theme={null}
expired
```

**Best practice:** keep a polling routine for documents you need to follow until expiration, especially when your business must tell customers about overdue or expired boletos. Read the boleto with [`GET /v2/in/boletos/{id}`](https://docs.trio.com.br/v2/api-reference/banking-api/receivables/boletos/get).

## Due date versus expiration date

The two fields have different roles.

### Due date

`due_date` is the due date of the boleto. After it, the configured charges may apply:

* fine;
* interest.

### Expiration date

`expiration_date` is the payment deadline of the boleto.

After it, the boleto stops accepting payments and moves to `expired`.

### Example

```text theme={null}
due_date:        2026-09-10
expiration_date: 2026-09-30
```

In this scenario:

```text theme={null}
Sep 10 ─────────────── Sep 30
  ↑                       ↑
Due date              Expiration
  │                       │
  │                       └─ No longer accepts payment
  │
  └─ From this date, the configured
     interest and fine may apply
```

So a boleto can still be paid after its due date, as long as it is within the validity period set by `expiration_date`.

## Updating the due date

Update the due date of a boleto with [`PUT /v2/in/boletos/{id}`](https://docs.trio.com.br/v2/api-reference/banking-api/receivables/boletos/update):

```http theme={null}
PUT /v2/in/boletos/{id}
```

```json theme={null}
{
  "due_detail": {
    "due_date": "2026-12-16"
  }
}
```

When you change the due date:

* `due_detail` is updated;
* the response is `204 No Content` with no body: read `GET /v2/in/boletos/{id}` to see the updated data;
* the `barcode` does not change;
* the Pix QR code does not change.

Only the due date can be changed through this endpoint. To change the amount, recreate the boleto as described below.

### Changing the amount: recreation

To change the amount of a boleto, use [`POST /v2/in/boletos/{id}/recreate`](https://docs.trio.com.br/v2/api-reference/banking-api/receivables/boletos/recreate):

```http theme={null}
POST /v2/in/boletos/{id}/recreate
```

```json theme={null}
{
  "amount": 15000,
  "due_detail": {
    "due_date": "2026-12-16"
  }
}
```

The original boleto is cancelled and a new one is created with the same fields, the new amount and the new due date (or the current due date, when `due_detail` is omitted). The response is `201` with the new boleto, which has a new `id`.

**Best practice:** when you recreate a boleto, replace the `id`, `barcode`, `digitable_line` and `boleto_url` stored in your system, and discard those of the cancelled boleto.

### Cancellation

Cancel a boleto with [`POST /v2/in/boletos/{id}/cancel`](https://docs.trio.com.br/v2/api-reference/banking-api/receivables/boletos/cancel):

```http theme={null}
POST /v2/in/boletos/{id}/cancel
```

The response is `204 No Content`.

### Protest

The API also lets you add and remove the protest of a boleto:

```http theme={null}
PUT /v2/in/boletos/{id}/protest/add
PUT /v2/in/boletos/{id}/protest/remove
```

Both respond `204 No Content`. See the [Add protest](https://docs.trio.com.br/v2/api-reference/banking-api/receivables/boletos/add-protest.md) and [Remove protest](https://docs.trio.com.br/v2/api-reference/banking-api/receivables/boletos/remove-protest.md) references.

### Overdue versus expired boleto

There is an important difference:

* **Overdue boleto:** its due date can still be updated.
* **Expired boleto:** it can no longer be updated.

**Best practice:** if your business renegotiates boletos, make the change before the document reaches the expired state.

## Refunding a boleto

[`POST /v2/documents/in/{id}/refund`](https://docs.trio.com.br/v2/api-reference/banking-api/receivables/pix/refunds/post) applies to transactions that originated through Pix. This includes a boleto that was paid through its Pix QR code.

```http theme={null}
POST /v2/documents/in/{id}/refund
```

The `{id}` is the identifier of the in document (the payment, returned by `GET /v2/documents/in/{id}`), not the `id` of the boleto. The body carries the amount in cents (BRL 100.00 = `10000`) and a description:

```json theme={null}
{
  "amount": 10,
  "description": "Refund description"
}
```

The response returns the identifier of the refund, which is created asynchronously:

```json theme={null}
{
  "data": {
    "in_refund_id": "01a12175-3994-6649-4e0b-f645e45459ea"
  }
}
```

Read the refund with [`GET /v2/documents/in/refunds/{id}`](https://docs.trio.com.br/v2/api-reference/banking-api/documents/receivables-refunds/get-receivable-refund) to follow its details and final state.

### Examples

**Boleto paid through the digitable line**

```text theme={null}
Boleto
  ↓
Traditional payment
  ↓
Do not use /refund as a Pix refund
```

**Boleto paid through the Pix QR code**

```text theme={null}
Boleto
  ↓
Pix QR code
  ↓
Pix payment (type = pix_boleto)
  ↓
/refund available
```

**Best practice:** when you implement a refund routine, identify the origin of the payment first. A boleto paid through Pix is a Pix transaction for refund purposes.

## Boleto URL

When you create a boleto, the API returns a `boleto_url`. You can hand this URL directly to the payer. The link:

* is public;
* requires no authentication;
* suits e-mails, checkout pages and apps.

Example:

```text theme={null}
https://receipts.sandbox.trio.com.br/.../boleto/...
```

**Best practice:** store the `boleto_url` with the boleto record in your system, so you can reach it quickly when talking to the customer.

## Costs

Agree the cost per boleto directly with Trio's commercial team. This matters most for operations that work with:

* installment books (*carnês*, a series of boletos for one order);
* multiple installments;
* several boletos issued in advance;
* high issuing volumes.

Do not assume the cost from the number of paid or unpaid boletos alone; validate the commercial terms of your project. This cost is separate from the fee you can charge the payer in `options.fee`, described in [Fees](https://docs.trio.com.br/v2/guides/receivables/fees.md).

## Rate limit and installment books

Boleto creation follows the default rate limit of the create route: 60 requests per second. See [Rate limit](https://docs.trio.com.br/v2/developers/rate-limit.md).

Beyond that limit there is no specific cap on how many boletos you can issue. You can, for example, create the installments of an installment book in sequence.

### Keep `external_id` unique

Each boleto must have an `external_id` that is unique within your operation. The field takes up to 40 characters.

Example:

```json theme={null}
{
  "external_id": "pedido-123-parcela-01"
}
```

```json theme={null}
{
  "external_id": "pedido-123-parcela-02"
}
```

```json theme={null}
{
  "external_id": "pedido-123-parcela-03"
}
```

Avoid reusing the same `external_id` for different boletos.

> [!TIP]
>
> In installment books, put the installment number in the `external_id`. It simplifies reconciliation, tracking and finding the right boleto in your system. [`GET /v2/in/boletos`](https://docs.trio.com.br/v2/api-reference/banking-api/receivables/boletos/list) accepts an `external_id` filter.

## Recommended practices

For a safer and more predictable integration:

### Use `external_id` for reconciliation

`external_id` should be a reference your system knows, such as an order, an invoice or an installment.

```text theme={null}
Order 123
 ├── Installment 01 → pedido-123-parcela-01
 ├── Installment 02 → pedido-123-parcela-02
 └── Installment 03 → pedido-123-parcela-03
```

### Do not confuse due date with expiration date

`due_date` says when the boleto is due. `expiration_date` says until when it can be paid. They are different concepts.

### Do not rely on webhooks alone to control expiration

There is no "boleto expired" webhook. If your application must act when a boleto expires, keep your own control or read the document status.

### Handle both payment methods

The same boleto can be paid:

* through the digitable line or barcode;
* through the embedded Pix QR code.

Your reconciliation must be ready for both.

### Identify the origin of the payment

For payments through the boleto's Pix QR code, the in document and the webhook carry:

```text theme={null}
type: pix_boleto
```

Use it to separate traditional payments from Pix payments.

### Respect the rate limit

For batch issuing, such as installment books, pace your requests within the limit of 60 requests per second.

### Store the important identifiers

For each boleto, keep at least:

* the Trio `id`;
* `external_id`;
* the amount (`amount.amount`, in cents);
* `due_date`;
* `expiration_date`;
* `boleto_url`;
* the current status.

This simplifies support, reconciliation and payment tracking.

## Quick summary

| Topic | Behavior |
| - | - |
| Embedded Pix | Yes, every boleto has a Pix QR code |
| BR code (copy and paste) | Read with `GET /v2/in/pix/qrcodes/{id}`, field `data.hash` |
| Payment through Pix | In document and `in_document` webhook with `type = pix_boleto` |
| Paid boleto | `settled` |
| Cancelled boleto | `cancelled` |
| Expired boleto | `expired` |
| Expiration webhook | No specific event |
| `external_id` in the webhook | Yes |
| Payer address | Required by the schema, but not validated |
| Payment after `due_date` | Possible until the `expiration_date`, with the configured charges when applicable |
| Updating an overdue boleto | Allowed |
| Updating an expired boleto | Not allowed |
| Due-date update response | `204 No Content`, no body |
| Barcode after a due-date update | Does not change |
| Pix QR code after a due-date update | Does not change |
| Changing the amount | `POST /v2/in/boletos/{id}/recreate`: cancels the boleto and creates a new one |
| Refund | Available when the payment originated through Pix, via `POST /v2/documents/in/{id}/refund` |
| `boleto_url` | Public, no authentication |
| Creation rate limit | 60 requests per second |
| Quantity limit | No additional issuing limit |
| Installment books | Allowed, with a unique `external_id` per boleto |

## Next steps

* [Create a boleto](https://docs.trio.com.br/v2/guides/boleto/create-boleto.md): build the request body.
* [Boleto types](https://docs.trio.com.br/v2/guides/boleto/boleto-types.md): choose `invoice_type` and `wallet_type`.
* [Document lifecycle](https://docs.trio.com.br/v2/guides/pix/document-lifecycle.md): statuses and stages of an in document.
* [Events](https://docs.trio.com.br/v2/webhooks/events/overview.md): the webhook events you can receive.


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