Skip to main content

Como funciona

Toda transação eventualmente envia um POST para a postbackUrl que você forneceu na criação. O envelope é sempre tipado:
  • Cash-in (cobrança recebida) → { "cashin": { ... } }
  • Cash-out (pagamento enviado) → { "cashout": { ... } }

Cash-in (recebimento confirmado)

{
  "cashin": {
    "reference_code": "PSR-9c8f7a1e-...",
    "external_reference": "pedido-001",
    "value_cents": 5000,
    "status": "paid",
    "payer_name": "João da Silva",
    "payer_document": "12345678900",
    "payment_date": "2026-05-13T10:13:01-03:00",
    "registration_date": "2026-05-13T10:12:15-03:00",
    "end_to_end": "E18236120202605131013...",
    "content": "00020126580014br.gov.bcb.pix..."
  }
}

Status possíveis

StatusSignificado
paidCliente pagou. Saldo da conta é creditado.
refundedCliente fez devolução (BACEN) ou transação entrou em revisão MED. Saldo estornado.
expiredQR Code expirou sem pagamento (após 24h, status terminal).

MED / Bloqueio por infração BACEN

Quando uma transação paid entra em revisão MED (chargeback), você recebe um webhook adicional com status=refunded e um campo extra event indicando o motivo:
{
  "cashin": {
    "reference_code": "PSR-9c8f7a1e-...",
    "external_reference": "pedido-001",
    "value_cents": 10000,
    "status": "refunded",
    "event": "med_block",
    "reason": "Transação em revisão MED — saldo bloqueado",
    "occurred_at": "2026-06-02T15:36:40-03:00",
    "end_to_end": "E18236120202606021536...",
    "payer_name": "João da Silva",
    "payer_document": "12345678900",
    "payment_date": "2026-06-01T02:04:46-03:00"
  }
}
  • value_cents reflete o valor bruto da transação (não o líquido creditado) — é o que o BACEN tira da Paysure.
  • A devolução é irreversível pelo seu sistema: bloqueie/estorne o saldo do cliente final imediatamente.
  • Atualizações posteriores da disputa (vitória, derrota, cancelamento) não disparam novo webhook — são tratadas internamente.
Webhooks de MED só são enviados pra contas marcadas como sub-gateway (PSPs que repassam transações pra clientes finais). Se você opera direto com pagadores e não gerencia clientes finais, ignore essa seção. Pra habilitar como sub-gateway, fale com suporte@paysurebr.com.

Cash-out (pagamento enviado)

{
  "cashout": {
    "reference_code": "PSR-1234abcd-...",
    "external_reference": "withdraw-001",
    "status": "paid",
    "end_to_end": "E29477089202605131013...",
    "occurred_at": "2026-05-13T10:13:01-03:00"
  }
}

Status possíveis

StatusSignificado
paidPagamento concluído pelo banco do destinatário.
refundedNão foi possível concluir. Saldo é estornado automaticamente — você não precisa fazer nada.

Boas práticas

Qualquer status diferente de 200 faz a Paysure retentar. Mesmo se você não reconhece o evento, devolva 200 com {"ok": true}.
Webhooks podem ser entregues mais de uma vez (em caso de retry após timeout). Use cashin.reference_code ou cashout.reference_code pra deduplicar do seu lado.
if (await db.webhookAlreadyProcessed(payload.cashin.reference_code)) {
  return res.status(200).json({ ok: true });
}
A Paysure envia webhooks de IPs Cloudflare. Se quiser camada extra de segurança, valide o IP de origem ou implemente uma assinatura HMAC compartilhada (em breve).
Respondemos em até 10 segundos antes de considerar timeout e retentar. Mantenha o handler rápido — processe em background se precisar de operações pesadas.

Política de retry

Em caso de falha (HTTP != 200 ou timeout), retentamos com backoff:
  • 1ª tentativa: imediata
  • 2ª tentativa: ~5 minutos
  • 3ª tentativa: ~30 minutos
Após 3 falhas, o webhook é marcado como client_error e fica disponível pra retry manual via painel.