Webhooks
Eventos e payloads
Todos os tipos de evento, quando cada um é enviado e o formato real do conteúdo.
Todo evento chega com o mesmo envelope:
| Campo | Descrição |
|---|---|
id | Id do evento (evt_...). Use para não processar o mesmo evento duas vezes. |
type | Tipo, ex.: charge.paid. |
version | Versão do formato (v1). |
created_at | Momento do fato (UTC). |
environment | production. O valor sandbox está reservado para o ambiente de testes, que ainda está em preparação. |
data | Conteúdo do evento (abaixo, por tipo). |
Valores em centavos vêm como string. Campos novos podem ser acrescentados ao data sem aviso prévio: ignore o que você não conhece.
Tipos de evento
| Tipo | Quando |
|---|---|
charge.pending | O QR foi emitido e a cobrança aguarda pagamento. |
charge.paid | Pagamento confirmado (também em pagamento tardio, com late_payment: true). |
charge.expired | A validade acabou sem pagamento, ou a cobrança foi cancelada antes do pagamento (data.status: "cancelled"). |
charge.failed | A emissão do Pix foi recusada ou não pôde ser feita. |
charge.refunded | Uma devolução foi concluída. |
charge.duplicate_payment | O mesmo QR foi pago de novo; o valor extra fica retido para devolução. |
case.opened | Um caso foi aberto: devolução, contestação (MED) ou revisão. |
case.resolved | Um caso foi resolvido. |
balance.available | Valores ficaram disponíveis para saque (por venda, na hora, ou por liquidação). |
payout.created | Você pediu um saque (pelo painel ou pela API); o valor pedido ficou reservado. |
payout.approved | A Wavewhite aprovou o saque e vai fazer a transferência. |
payout.rejected | A Wavewhite recusou o saque; o valor pedido voltou ao disponível. |
payout.channel_changed | A Wavewhite vai pagar o saque aprovado por outro meio (transferência feita pela Wavewhite); o valor segue reservado. |
payout.paid | A Wavewhite transferiu o saque para a sua conta. |
payout.failed | O saque foi encerrado sem pagamento: cancelado por você antes da análise ou, no envio automático, falhou. O valor pedido voltou ao disponível. |
reserve.released | Uma reserva contratual foi liberada para o seu saldo. |
pricing.policy_published | Uma nova tarifa foi publicada para a sua conta. |
reserve.policy_published | Uma nova regra de reserva contratual foi publicada. |
A lista oficial, com a versão e o formato da assinatura, sai em Listar tipos de evento.
Cobranças
charge.pending
charge.pending{
"id": "evt_1a7c3e9b5d2f4a8e9c6b0d3f7a1e5c92",
"type": "charge.pending",
"version": "v1",
"created_at": "2026-10-07T15:30:01.000Z",
"environment": "production",
"data": {
"charge_id": "8d3f6a12-4b9e-4c71-a2d5-6e0f1b3c9a47",
"order_reference": "PEDIDO-1001",
"status": "pending",
"amount_cents": "15990",
"expires_at": "2026-10-07T16:00:00.000Z"
}
}charge.paid
O evento mais importante: libere o pedido depois de confirmar pela consulta. Traz bruto (amount_cents), tarifa (fee_cents), líquido (net_cents), reserva, data do pagamento e o identificador fim a fim do Pix. Em pagamento tardio, late_payment vem true e case_id aponta o caso de revisão.
charge.paid{
"id": "evt_2f6b1c9e8a4d4e7f9b3c5a1d0e6f8b27",
"type": "charge.paid",
"version": "v1",
"created_at": "2026-10-07T15:32:11.000Z",
"environment": "production",
"data": {
"charge_id": "8d3f6a12-4b9e-4c71-a2d5-6e0f1b3c9a47",
"order_reference": "PEDIDO-1001",
"amount_cents": "15990",
"fee_cents": "320",
"net_cents": "15670",
"reserve_cents": "0",
"paid_at": "2026-10-07T15:32:10.000Z",
"end_to_end_id": "E12345678202610071532a1B2c3D4e5F",
"late_payment": false,
"case_id": null
}
}charge.expired
Enviado quando a cobrança deixa de aceitar pagamento: data.status vem expired (a validade acabou) ou cancelled (a cobrança foi cancelada antes do pagamento). Não há evento separado para o cancelamento.
charge.expired{
"id": "evt_3b9d5f1a7c2e4b6d8f0a2c4e6b8d1f37",
"type": "charge.expired",
"version": "v1",
"created_at": "2026-10-07T16:00:05.000Z",
"environment": "production",
"data": {
"charge_id": "b2e7c4d1-9a36-4f58-8c0e-1d5a7f3b6e92",
"order_reference": "PEDIDO-1002",
"status": "expired"
}
}charge.failed
reason sempre vem e é um código estável do motivo, bom para decidir no código. Para exibir, use failure_message da cobrança (consulta), que é um texto fixo da Wavewhite.
reason | Significado |
|---|---|
rejected:fraud | Recusada pela análise de risco. |
rejected:invalid_request | Dados da cobrança ou do pagador inválidos ou incompletos. |
rejected:compliance | Recusada pela análise de conformidade. |
rejected:limit | Limite de recebimento da conta atingido. |
rejected:sector | Segmento da venda não aceito para a conta. |
rejected:registration | Pendência no cadastro da conta. |
rejected:blocked ou rejected:account_suspended | Recebimentos bloqueados ou suspensos para a conta. |
rejected:other | Outra recusa definitiva. |
not_created:<motivo> | Falha técnica na emissão; nada foi criado (ex.: not_created:transient_error). |
unknown_resolved_not_created | A emissão ficou sem resposta e, depois de conferida, não tinha sido criada. |
expired_before_issue | A validade acabou antes de a emissão ser confirmada. |
Em todos os casos, nenhum QR Code válido foi entregue: crie uma nova cobrança com outro order_reference.
charge.failed{
"id": "evt_4c0e6a2b8d3f4c7e9a1b3d5f7c9e2a48",
"type": "charge.failed",
"version": "v1",
"created_at": "2026-10-07T15:40:02.000Z",
"environment": "production",
"data": {
"charge_id": "e41a9c7b-2d58-4e06-b3f1-7c9d0a2e5b18",
"order_reference": "PEDIDO-1003",
"status": "failed",
"reason": "rejected:fraud"
}
}charge.refunded
refunded_cents é o valor desta devolução.
charge.refunded{
"id": "evt_5d1f7b3c9e4a4d8f0b2c4e6a8d0f3b59",
"type": "charge.refunded",
"version": "v1",
"created_at": "2026-10-08T12:00:04.000Z",
"environment": "production",
"data": {
"charge_id": "8d3f6a12-4b9e-4c71-a2d5-6e0f1b3c9a47",
"case_id": "3c7e1b95-6d2a-4f80-9e4b-a1d5c8f20e63",
"refunded_cents": "5000"
}
}charge.duplicate_payment
charge.duplicate_payment{
"id": "evt_6e2a8c4d0f5b4e9a1c3d5f7b9e1a4c60",
"type": "charge.duplicate_payment",
"version": "v1",
"created_at": "2026-10-07T15:35:20.000Z",
"environment": "production",
"data": {
"charge_id": "8d3f6a12-4b9e-4c71-a2d5-6e0f1b3c9a47",
"order_reference": "PEDIDO-1001",
"payment_id": "f2c8a5e1-3b7d-4e90-a6c4-8d1f5b2e9a73",
"classification": "duplicate",
"amount_cents": "15990",
"end_to_end_id": "E12345678202610071535f6G7h8J9k0L",
"case_id": "6a2f9d14-8e3b-4c57-b1d0-5e9a7c3f2b81"
}
}Casos
case.opened
case.opened{
"id": "evt_7f3b9d5e1a6c4f0b2d4e6a8c0f2b5d71",
"type": "case.opened",
"version": "v1",
"created_at": "2026-10-08T12:00:00.000Z",
"environment": "production",
"data": {
"case_id": "3c7e1b95-6d2a-4f80-9e4b-a1d5c8f20e63",
"case_type": "refund",
"charge_id": "8d3f6a12-4b9e-4c71-a2d5-6e0f1b3c9a47",
"amount_cents": "5000",
"reason": "Cliente devolveu um item"
}
}case.resolved
resolution diz o desfecho (ex.: refunded) e uncovered_cents a parte que não tinha saldo para cobrir, quando houver.
case.resolved{
"id": "evt_8a4c0e6f2b7d4a1c3e5f7b9d1a3c6e82",
"type": "case.resolved",
"version": "v1",
"created_at": "2026-10-08T12:00:04.000Z",
"environment": "production",
"data": {
"case_id": "3c7e1b95-6d2a-4f80-9e4b-a1d5c8f20e63",
"case_type": "refund",
"charge_id": "8d3f6a12-4b9e-4c71-a2d5-6e0f1b3c9a47",
"amount_cents": "5000",
"resolution": "refunded",
"uncovered_cents": "0"
}
}Saldo
balance.available
amount_cents é o total que ficou disponível. Há dois formatos: por liquidação (settlement_id preenchido; charge_id e payment_id ausentes) e por venda, quando a adquirente libera na hora (settlement_id é null e vêm charge_id e payment_id da venda). Trate settlement_id como opcional.
balance.available{
"id": "evt_9b5d1f7a3c8e4b2d4f6a8c0e2b4d7f93",
"type": "balance.available",
"version": "v1",
"created_at": "2026-10-08T08:00:02.000Z",
"environment": "production",
"data": {
"settlement_id": "9e2d5b7a-3c18-4f6e-b0a4-7d1c9e5f2a83",
"amount_cents": "15670"
}
}Saques
Os saques são pedidos pelo painel ou pela API, a qualquer hora (veja Saques). Todos os eventos de saque trazem payout_id, o valor pedido (requested_cents), a taxa de saque (fee_cents) e o valor enviado à sua conta (amount_cents = pedido − taxa).
payout.created
O pedido foi registrado e o valor pedido saiu do disponível. Ele aguarda a aprovação da Wavewhite (approval_status: "pending").
payout.created{
"id": "evt_a1c6e2b8d4f04a9c8e2b6d0f4a8c1e57",
"type": "payout.created",
"version": "v1",
"created_at": "2026-10-10T17:00:00.000Z",
"environment": "production",
"data": {
"payout_id": "a4c81e5d-7f2b-4d39-9e06-3b5f8c1d2e74",
"requested_cents": "5000",
"fee_cents": "500",
"amount_cents": "4500",
"approval_status": "pending",
"execution_status": "reserved",
"scheduled_for": null
}
}payout.approved
A Wavewhite aprovou o pedido e vai fazer a transferência.
payout.approved{
"id": "evt_b2d7f3c9e5a14b0d9f3c7e1a5b9d2f68",
"type": "payout.approved",
"version": "v1",
"created_at": "2026-10-12T12:10:00.000Z",
"environment": "production",
"data": {
"payout_id": "a4c81e5d-7f2b-4d39-9e06-3b5f8c1d2e74",
"requested_cents": "5000",
"fee_cents": "500",
"amount_cents": "4500",
"approval_mode": "manual",
"scheduled_for": null
}
}payout.rejected
A Wavewhite recusou o pedido. reason é o motivo informado pela Wavewhite; o valor pedido voltou ao disponível.
payout.rejected{
"id": "evt_d4f9b5e1a7c34d2f1b5e9a3c7d1f4b80",
"type": "payout.rejected",
"version": "v1",
"created_at": "2026-10-12T12:15:00.000Z",
"environment": "production",
"data": {
"payout_id": "c9e2a7f4-1d6b-4a83-b5e0-6f3d9a2c8b15",
"requested_cents": "2000",
"fee_cents": "500",
"amount_cents": "1500",
"reason": "Conta de destino diferente da combinada no contrato",
"execution_status": "cancelled"
}
}payout.failed
O saque foi encerrado sem pagamento e o valor pedido voltou ao disponível (execution_status: "cancelled"). Quando você cancela o pedido (Cancelar um saque ou o painel), reason é o motivo que você informou (ou um texto padrão); no envio automático, é o motivo da falha em texto fixo da Wavewhite.
payout.failed{
"id": "evt_f6b2d8e4a0c15f7b3d9e1a5c7b3f6d02",
"type": "payout.failed",
"version": "v1",
"created_at": "2026-10-13T09:31:00.000Z",
"environment": "production",
"data": {
"payout_id": "d0b4f8a2-6c1e-4f7b-9a35-2e8c5d1f7b46",
"requested_cents": "1000",
"fee_cents": "500",
"amount_cents": "500",
"reason": "Pedido feito por engano",
"execution_status": "cancelled"
}
}payout.channel_changed
A Wavewhite aprovou o saque para envio pela conta de saída, mas vai pagá-lo por outro meio: execution_channel passa a manual_transfer (transferência feita pela Wavewhite). O motivo interno não vai no evento (desde 20/10/2026). Nada muda no valor nem na reserva: o saque continua aprovado e termina com payout.paid.
payout.channel_changed{
"id": "evt_e5a1c7d3b9f24e6a2c8d0b4f6a2e5c91",
"type": "payout.channel_changed",
"version": "v1",
"created_at": "2026-10-12T12:40:00.000Z",
"environment": "production",
"data": {
"payout_id": "a4c81e5d-7f2b-4d39-9e06-3b5f8c1d2e74",
"requested_cents": "5000",
"fee_cents": "500",
"amount_cents": "4500",
"execution_channel": "manual_transfer"
}
}payout.paid
A Wavewhite transferiu o valor enviado para a sua conta. transfer_reference é a referência da transferência e paid_at, quando ela foi feita.
payout.paid{
"id": "evt_c3e8a4d0f6b24c1e0a4d8f2b6c0e3a79",
"type": "payout.paid",
"version": "v1",
"created_at": "2026-10-12T13:04:00.000Z",
"environment": "production",
"data": {
"payout_id": "a4c81e5d-7f2b-4d39-9e06-3b5f8c1d2e74",
"requested_cents": "5000",
"fee_cents": "500",
"amount_cents": "4500",
"transfer_reference": "E98765432202610121300Sq4Ke7Mn2Pw",
"paid_at": "2026-10-12T13:00:00.000Z"
}
}Recuperando eventos
Todos os eventos ficam disponíveis pela API, independentemente da entrega. Use para conferir o que pode ter se perdido enquanto o seu endpoint estava fora do ar:
curl -X GET 'https://api.wavewhite.com/v1/webhooks/events?type=charge.paid&limit=20' \
-H "Authorization: Bearer $API_KEY"const response = await fetch('https://api.wavewhite.com/v1/webhooks/events?type=charge.paid&limit=20', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.API_KEY}`,
},
});
const data = await response.json();
console.log(response.status, data);import os
import requests
response = requests.request(
"GET",
"https://api.wavewhite.com/v1/webhooks/events?type=charge.paid&limit=20",
headers={
"Authorization": f"Bearer {os.environ['API_KEY']}",
},
timeout=30,
)
print(response.status_code, response.json())<?php
$ch = curl_init('https://api.wavewhite.com/v1/webhooks/events?type=charge.paid&limit=20');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('API_KEY'),
],
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo $status, PHP_EOL;
print_r($data);{
"items": [
{
"id": "evt_2f6b1c9e8a4d4e7f9b3c5a1d0e6f8b27",
"type": "charge.paid",
"version": "v1",
"environment": "production",
"object_type": "charge",
"object_id": "8d3f6a12-4b9e-4c71-a2d5-6e0f1b3c9a47",
"created_at": "2026-10-07T15:32:11.000Z",
"data": {
"charge_id": "8d3f6a12-4b9e-4c71-a2d5-6e0f1b3c9a47",
"order_reference": "PEDIDO-1001",
"amount_cents": "15990",
"fee_cents": "320",
"net_cents": "15670",
"reserve_cents": "0",
"paid_at": "2026-10-07T15:32:10.000Z",
"end_to_end_id": "E12345678202610071532a1B2c3D4e5F",
"late_payment": false,
"case_id": null
}
}
],
"next_cursor": null
}