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

# withdrawal.*

> Solicitado, pago, negado ou falhou. Os momentos em que o seu saldo muda de lado.

Cada mudança de estado de um saque dispara um evento na URL configurada na conta, em
[Dashboard → Equipe & API → Developer API](https://purin.cash/dashboard/api).

| Evento | Quando |
| - | - |
| `withdrawal.requested` | O saque foi solicitado |
| `withdrawal.completed` | O dinheiro saiu, confirmado |
| `withdrawal.denied` | O saque foi recusado antes de sair e o valor voltou pro saldo |
| `withdrawal.failed` | O saque foi tentado e não se concretizou. O valor voltou pro saldo |

Em sandbox entra a marca de teste no nome: `withdrawal.test.requested`,
`withdrawal.test.completed`, e assim por diante.

> [!NOTE]
>
> [Pagar um código copia e cola](https://docs.purin.cash/guias/saques.md#pagar-um-codigo-copia-e-cola) chega nas
> mesmas URLs, mas com nome próprio: `pix_payment.completed` e `pix_payment.failed`. Esses
> dois trazem `paymentId` no lugar de `withdrawalId`, e o `method` é `pix_payment`. O resto
> dos campos é igual ao desta página. Pagamento que você faz não é saque, e misturar os
> dois na mesma família quebraria a sua conciliação de saques.

```json Solicitado theme={null}
{
  "event": "withdrawal.requested",
  "withdrawalId": "665f1a2b3c4d5e6f7a8b9c0d",
  "code": "SAQ-A1B2C3",
  "amount": 150.00,
  "method": "pix",
  "walletAddress": "chave-pix-ou-carteira",
  "status": "pendente",
  "requestedAt": "2026-03-18T14:00:00.000Z",
  "sandbox": false
}
```

```json Pago theme={null}
{
  "event": "withdrawal.completed",
  "withdrawalId": "665f1a2b3c4d5e6f7a8b9c0d",
  "code": "SAQ-A1B2C3",
  "amount": 150.00,
  "method": "pix",
  "walletAddress": "chave-pix-ou-carteira",
  "status": "concluido",
  "endToEndId": "E12345678202603181530abcdef01234",
  "recipientName": "JOAO DA SILVA",
  "recipientTaxId": "12345678909",
  "receiptUrl": "https://api.purin.cash/uploads/img/9f8e7d6c1a2b....webp",
  "processedAt": "2026-03-18T15:30:00.000Z"
}
```

```json Negado theme={null}
{
  "event": "withdrawal.denied",
  "withdrawalId": "665f1a2b3c4d5e6f7a8b9c0d",
  "code": "SAQ-A1B2C3",
  "amount": 150.00,
  "method": "pix",
  "walletAddress": "chave-pix-ou-carteira",
  "status": "negado",
  "reason": "Chave PIX inválida",
  "receiptUrl": "https://api.purin.cash/uploads/img/1a2b3c4d5e6f....webp",
  "processedAt": "2026-03-18T15:30:00.000Z"
}
```

```json Pagamento de código theme={null}
{
  "event": "pix_payment.completed",
  "paymentId": "665f1a2b3c4d5e6f7a8b9c0d",
  "code": "PAY-A1B2C3D4",
  "amount": 100.00,
  "method": "pix_payment",
  "walletAddress": "financeiro@fornecedor.com",
  "status": "concluido",
  "endToEndId": "E12345678202603181200abcdef01234",
  "recipientName": "FORNECEDOR LTDA",
  "recipientTaxId": "12345678000199",
  "receiptUrl": "https://api.purin.cash/uploads/img/5e6f7a8b9c0d....webp",
  "processedAt": "2026-03-18T12:00:03.000Z"
}
```

## Campos

**event** `string` *required*

O evento da tabela acima, ou `pix_payment.completed` / `pix_payment.failed` quando é
pagamento de código.

**withdrawalId** `string` *required*

Identificador do saque. Em `pix_payment.*` o campo se chama `paymentId`, e é o mesmo
`payment.id` que o pagamento devolveu.

**code** `string` *required*

Código legível da operação: `SAQ-A1B2C3` no saque comum, `TURBO-...` no PIX enviado na
hora e `PAY-...` no pagamento de código. É por ele que o suporte localiza a operação.

**amount** `number` *required*

Valor em reais, decimal.

**method** `string` *required*

`pix`, `pix_turbo`, `ltc`, `usd` ou `pix_payment` (pagamento de código copia e cola).

**walletAddress** `string` *required*

Destino. Chave PIX, endereço LTC ou endereço USDT, conforme o método. No pagamento de
código, a chave que o código apontava.

**status** `string` *required*

`pendente`, `concluido`, `negado` ou `falhou`.

**reason** `string`

Só quando não deu certo: o motivo, em texto pronto pra mostrar. Não vem em
`concluido`.

**endToEndId** `string`

O E2E do PIX, o mesmo número que aparece no extrato de quem recebeu. É o que resolve
contestação com o outro banco. Ausente quando ainda não veio ou quando o método não é
PIX.

**recipientName** `string`

Nome de quem recebeu, como o banco confirmou.

**recipientTaxId** `string`

CPF ou CNPJ de quem recebeu, **inteiro**, pra você amarrar o saque a um cadastro seu.
Nome sozinho não fecha conciliação, porque nome se repete. Pode vir mascarado quando é
assim que a informação chega. É dado pessoal de terceiro: receba em HTTPS e guarde só o
que precisar.

**receiptUrl** `string`

URL do comprovante desenhado, em imagem, o mesmo papel que o painel mostra. Serve pra
repassar ao seu cliente ou anexar num chamado: dá pra embutir direto num `<img>`. É
imutável, então pode cachear. O campo some quando não foi possível gerar, então trate a
ausência como normal.

**requestedAt** `string`

Presente em `withdrawal.requested`.

**processedAt** `string`

Presente nos eventos de desfecho.

> [!NOTE]
>
> Repare que o `status` aqui vem em português (`pendente`, `concluido`, `negado`), enquanto
> as cobranças usam inglês (`pending`, `paid`). São domínios diferentes da API e cada um
> manteve o vocabulário da sua área.

> [!WARNING]
>
> No comprovante em imagem o documento do recebedor sai mascarado, mesmo quando o
> `recipientTaxId` do JSON vem inteiro. A imagem é feita pra ser repassada adiante; o JSON
> vai só pra sua URL.

## Um uso que compensa

Saque que não sai devolve o valor pro saldo, mas ninguém fica olhando o painel esperando
isso. Um alerta em `withdrawal.denied` e `withdrawal.failed` costuma ser a diferença entre
resolver no mesmo dia e descobrir na semana seguinte:

```js theme={null}
if (evento.event === "withdrawal.denied" || evento.event === "withdrawal.failed") {
  await avisarFinanceiro({
    titulo: `Saque ${evento.code} não saiu`,
    valor: evento.amount,
    metodo: evento.method,
    em: evento.processedAt,
  });
}
```

> [!WARNING]
>
> Este webhook não cobre todos os estados. O `processing` do [PIX enviado na
> hora](https://docs.purin.cash/guias/saques.md#quando-o-pix-sai-na-hora), que significa "o dinheiro saiu e o banco ainda não
> confirmou", é visto por `GET /v1/payouts`. Não trate ausência de
> `withdrawal.completed` como saque não realizado.

As garantias são as mesmas dos outros: assinatura HMAC em `X-Webhook-Signature`,
idempotência em `X-Webhook-Id` e reentrega com backoff.


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