# Testando com o Sandbox

Testar uma integração de boleto contra um banco real é lento e parcialmente impossível. Você precisa de uma conta empresarial, um pagador real disposto a pagar uma cobrança real e, para qualquer coisa que envolva uma data de vencimento, você teria que esperar a data chegar.

O conector Sandbox remove tudo isso. Ele emite boletos que parecem reais e os move pelo status que você escolher por conta própria, disparando os mesmos webhooks que um banco real faria.

<Callout variant="warning" title="Formatado, não utilizável">
Boletos do Sandbox possuem uma linha digitável, código de barras e carga PIX corretamente formatados — os comprimentos e a estrutura de campo corretos, para que seu parsing e rendering sejam realmente testados. Eles **não** são instrumentos de pagamento válidos: os dígitos de verificação não são calculados deliberadamente. Nada emitido aqui pode ser pago em um banco real.
</Callout>

## O que ele permite testar

```mermaid
graph TD
  A[Criar um boleto] --> B{Os centavos do valor<br/>escolha o cenário}
  B --> C[PAGO<br/>total ou parcial]
  B --> D[VENCIDO<br/>sem esperar pela data]
  B --> E[CANCELADO]
  D --> F[PROTESTADO]
  D --> C
  C --> G[Seu manipulador de webhook é executado<br/>em cada caminho]
  E --> G
  F --> G
```

Você não envia nenhuma solicitação para mover um boleto. O Sandbox realiza cada etapa por conta própria, **5 minutos** de intervalo, e dispara um webhook `boleto/updated` toda vez, exatamente como uma notificação de liquidação de um banco.

As transições que a API real recusa também são recusadas aqui. Um boleto `PAGO` não pode ser cancelado, e nada retorna para `ABERTO` — assim, um manipulador que assume que um status só pode avançar é validado em vez de passar acidentalmente.

## Escolhendo um cenário

O cenário é definido pelos **centavos do boleto `amount`**:

| Centavos terminam em | O que acontece |
|---|---|
| `,00` (ex: `100.00`) | Após 5 minutos → `PAGO` pelo valor total |
| `,01` | Após 5 minutos → `PAGO` pela metade do valor (pagamento parcial: `amountPaid` é menor que `amount`) |
| `,02` | Após 5 minutos → `VENCIDO`; 5 minutos depois → `PAGO` (pago após a data de vencimento) |
| `,03` | Após 5 minutos → `VENCIDO`; 5 minutos depois → `PROTESTADO` |
| `,04` | Após 5 minutos → `CANCELADO` |
| `,05` | Após 5 minutos → `VENCIDO`, e permanece assim |
| Qualquer outro centavo | Permanece `ABERTO` — use para testar seu próprio cancelamento com [POST /boletos/{id}/cancel](/reference/boleto-cancel) |

Cancelar um boleto antes que uma etapa programada ocorra interrompe seu cenário.

## Começando

<Callout variant="info" title="Prefere clicar primeiro?">
O [Dashboard da Pluggy](https://dashboard.pluggy.ai) faz tudo isso sem código, em **Pagamentos → Boletos** (Beta): crie uma conexão Sandbox, emita um boleto com os centavos do cenário que você deseja e veja seu status mudar. As solicitações abaixo são as mesmas que ele envia.
</Callout>

<StepList>
<Step title="Criar uma Conexão de Boleto Sandbox">
Use o conector `8` (Pluggy Bank Business) e [POST /boleto-connections](/reference/boleto-connection-create). Nenhuma credencial real está envolvida:

```json
{
  "connectorId": 8,
  "credentials": {}
}
```
</Step>

<Step title="Emitir um boleto com o valor para seu cenário">
Idêntico a qualquer outra instituição — mesma solicitação, mesma forma de resposta. Os valores estão em reais, e os centavos escolhem o cenário. Este termina em `,01`, então será pago parcialmente:

```json
{
  "boletoConnectionId": "{YOUR-SANDBOX-CONNECTION-ID}",
  "boleto": {
    "seuNumero": "TEST-001",
    "amount": 123.01,
    "dueDate": "2026-03-01",
    "payer": {
      "taxNumber": "12345678000199",
      "name": "Example SA",
      "addressState": "SP",
      "addressZipCode": "01239030",
      "addressCity": "São Paulo",
      "addressStreet": "Rua Example"
    }
  }
}
```
</Step>

<Step title="Aguarde os webhooks">
Cinco minutos depois, o Sandbox liquida o boleto e um webhook `boleto/updated` chega ao seu endpoint, o mesmo que a notificação de um banco real produziria. Cenários com duas etapas enviam um segundo webhook cinco minutos após o primeiro.
</Step>

<Step title="Verifique se seu manipulador foi executado">
[GET /boletos/{id}](/reference/boleto-get) retorna o boleto em seu novo estado, com `amountPaid`, `paidAt` e `paymentOrigin` preenchidos para boletos pagos — os mesmos campos, nos mesmos lugares, que um boleto liquidado em um banco real.
</Step>
</StepList>

## Um teste que vale a pena escrever

O modo de falha que mais custa é um manipulador de webhook que reconcilia contra o campo errado ou assume que o pagamento é sempre integral. O Sandbox torna ambos baratos de cobrir:

| Caso | Como produzi-lo |
|---|---|
| Pago integralmente | Emitir com um valor terminando em `,00` |
| Pago parcialmente | Emitir com um valor terminando em `,01` |
| Pago após a data de vencimento | Emitir com um valor terminando em `,02` |
| Protestado | Emitir com um valor terminando em `,03` |
| Cancelado pelo banco | Emitir com um valor terminando em `,04` |
| Vencido e não pago | Emitir com um valor terminando em `,05` |
| Cancelado por você antes do pagamento | Emitir com qualquer outro centavo, depois chamar [POST /boletos/{id}/cancel](/reference/boleto-cancel) |
| Webhook duplicado | Torne seu endpoint idempotente e entregue o mesmo evento a ele duas vezes você mesmo |

<Callout variant="info" title="Avance para um banco real">
Quando seu manipulador sobreviver a todos esses, aponte o mesmo código para uma [conexão Inter](/docs/boleto/inter). Nada além do ID da conexão muda.
</Callout>