Pular para o conteúdo principal

Visão Geral

Webhooks permitem que você receba notificações HTTP automáticas quando eventos importantes acontecem na sua conta, como pagamentos confirmados, reembolsos processados ou saques concluídos.

Eventos Disponíveis

EventoDescrição
payment_completedPagamento foi confirmado com sucesso
payment_expiredPagamento expirou sem confirmação
refund_completedReembolso foi processado
withdrawal_completedSaque foi processado com sucesso
withdrawal_failedSaque foi rejeitado ou falhou
withdrawal_reversedSaque foi estornado pelo PSP
balance_block_createdBloqueio de saldo criado (MED/judicial/administrativo)
balance_block_approvedBloqueio aprovado — valor devolvido ao pagador
balance_block_rejectedBloqueio rejeitado — valor retorna ao lojista

Estrutura do Payload

Todos os webhooks seguem a mesma estrutura base:
{
  "event": "payment_completed",
  "eventId": "a0b78f10-c7f4-4f5d-98dd-3e36eafeb812",
  "timestamp": "2026-01-11T19:03:28.280Z",
  "data": {
    // Dados específicos do evento
  }
}
CampoTipoDescrição
eventstringTipo do evento
eventIdstringID único do evento (geralmente o ID da transação)
timestampstringData/hora do evento em formato ISO 8601
dataobjectDados específicos do evento

Headers Enviados

Cada requisição de webhook inclui os seguintes headers:
HeaderDescrição
Content-Typeapplication/json
X-Webhook-SignatureAssinatura HMAC-SHA256 do payload
X-Webhook-TimestampTimestamp em milliseconds

Validando a Assinatura

Cada webhook é assinado com HMAC-SHA256 para garantir autenticidade. Siga estes passos para validar:
  1. Calcule a signing key: SHA256(seu_webhook_secret) em hex
  2. Calcule o HMAC-SHA256 do body da requisição usando a signing key
  3. Compare o resultado com o header X-Webhook-Signature usando comparação em tempo constante
import { verifyWebhookSignature, parseWebhook } from '@pague-dev/sdk-node';

app.post('/webhook', (req, res) => {
  const signature = req.headers['x-webhook-signature'] as string;
  const rawBody = req.body; // raw string body

  if (!verifyWebhookSignature(rawBody, signature, 'seu_webhook_secret')) {
    return res.status(401).send('Assinatura inválida');
  }

  const event = parseWebhook(rawBody);
  if (!event) {
    return res.status(400).send('Payload inválido');
  }

  // Processar o evento...
  res.status(200).send('OK');
});
Sempre use comparação em tempo constante (timingSafeEqual) para evitar ataques de timing. Nunca compare assinaturas com ===.

Exemplos de Payload

payment_completed

Enviado quando um pagamento PIX é confirmado.
{
  "event": "payment_completed",
  "eventId": "a0b78f10-c7f4-4f5d-98dd-3e36eafeb812",
  "timestamp": "2026-01-11T19:03:28.280Z",
  "data": {
    "transactionId": "a0b78f10-c7f4-4f5d-98dd-3e36eafeb812",
    "environment": "sandbox",
    "amount": 100.21,
    "feeAmount": 0.5,
    "netAmount": 99.71,
    "currency": "BRL",
    "paymentMethod": "pix",
    "status": "completed",
    "completedAt": "2026-01-11T19:03:28.277Z",
    "externalReference": "pedido-12345",
    "metadata": {
      "orderId": "ORDER-12345",
      "customerId": "CUST-67890"
    }
  }
}
CampoTipoDescrição
transactionIdstringID único da transação
environmentstringAmbiente (production ou sandbox)
amountnumberValor total do pagamento
feeAmountnumberTaxa cobrada
netAmountnumberValor líquido (amount - feeAmount)
currencystringMoeda (BRL)
paymentMethodstringMétodo de pagamento (pix)
statusstringStatus do pagamento (completed)
completedAtstringData/hora da conclusão em ISO 8601
externalReferencestringSua referência externa (opcional)
metadataobjectMetadados customizados enviados na criação do pagamento (opcional)

payment_expired

Enviado quando um pagamento PIX expira sem confirmação.
{
  "event": "payment_expired",
  "eventId": "payment_expired_d5e6f7a8-1234-5678-9abc-def012345678",
  "timestamp": "2026-01-11T19:30:00.000Z",
  "data": {
    "transactionId": "d5e6f7a8-1234-5678-9abc-def012345678",
    "environment": "sandbox",
    "amount": 75.50,
    "feeAmount": 0,
    "netAmount": 0,
    "currency": "BRL",
    "paymentMethod": "pix",
    "status": "expired",
    "expiredAt": "2026-01-11T19:30:00.000Z",
    "externalReference": "pedido-12345",
    "metadata": {
      "orderId": "ORDER-12345",
      "customerId": "CUST-67890"
    }
  }
}
CampoTipoDescrição
transactionIdstringID único da transação
environmentstringAmbiente (production ou sandbox)
amountnumberValor do pagamento
feeAmountnumberTaxa cobrada (sempre 0 para pagamentos expirados)
netAmountnumberValor líquido (sempre 0 para pagamentos expirados)
currencystringMoeda (BRL)
paymentMethodstringMétodo de pagamento (pix)
statusstringStatus do pagamento (expired)
expiredAtstringData/hora da expiração em ISO 8601
externalReferencestringSua referência externa (opcional)
metadataobjectMetadados customizados enviados na criação do pagamento (opcional)

refund_completed

Enviado quando um reembolso é processado.
{
  "event": "refund_completed",
  "eventId": "c92d45e6-8b33-4f12-a789-2e56f8901def",
  "timestamp": "2026-01-11T19:22:15.456Z",
  "data": {
    "refundTransactionId": "c92d45e6-8b33-4f12-a789-2e56f8901def",
    "originalTransactionId": "a0b78f10-c7f4-4f5d-98dd-3e36eafeb812",
    "environment": "sandbox",
    "amount": 50.00,
    "feeAmount": 0.25,
    "netAmount": 49.75,
    "currency": "BRL",
    "paymentMethod": "pix",
    "status": "completed",
    "refundedAt": "2026-01-11T19:22:15.400Z",
    "externalReference": "pedido-12345",
    "metadata": {
      "orderId": "ORDER-12345",
      "customerId": "CUST-67890"
    }
  }
}
CampoTipoDescrição
refundTransactionIdstringID único da transação de reembolso
originalTransactionIdstringID da transação original que foi reembolsada
environmentstringAmbiente (production ou sandbox)
amountnumberValor do reembolso
feeAmountnumberTaxa do reembolso
netAmountnumberValor líquido do reembolso
currencystringMoeda (BRL)
paymentMethodstringMétodo de pagamento da transação original
statusstringStatus do reembolso (completed)
refundedAtstringData/hora do reembolso em ISO 8601
externalReferencestringSua referência externa do pagamento original (opcional)
metadataobjectMetadados customizados do pagamento original (opcional)

withdrawal_completed

Enviado quando um saque é processado com sucesso.
{
  "event": "withdrawal_completed",
  "eventId": "e73775b5-70ee-4bad-be4c-4acff9890e27",
  "timestamp": "2026-01-11T19:08:21.953Z",
  "data": {
    "withdrawalId": "e73775b5-70ee-4bad-be4c-4acff9890e27",
    "environment": "sandbox",
    "amount": 500.00,
    "feeAmount": 2.50,
    "netAmount": 497.50,
    "currency": "BRL",
    "status": "completed",
    "completedAt": "2026-01-11T19:08:21.939Z",
    "metadata": {
      "batchId": "BATCH-001"
    }
  }
}
CampoTipoDescrição
withdrawalIdstringID único do saque
environmentstringAmbiente (production ou sandbox)
amountnumberValor do saque
feeAmountnumberTaxa do saque
netAmountnumberValor líquido transferido
currencystringMoeda (BRL)
statusstringStatus do saque (completed)
completedAtstringData/hora da conclusão em ISO 8601
metadataobjectMetadados customizados do saque (opcional)

withdrawal_failed

Enviado quando um saque é rejeitado ou falha.
{
  "event": "withdrawal_failed",
  "eventId": "b84f12c3-9a21-4e67-bc88-1d45f6789abc",
  "timestamp": "2026-01-11T19:15:42.123Z",
  "data": {
    "withdrawalId": "b84f12c3-9a21-4e67-bc88-1d45f6789abc",
    "environment": "sandbox",
    "amount": 1000.00,
    "feeAmount": 5.00,
    "netAmount": 995.00,
    "currency": "BRL",
    "status": "failed",
    "failedAt": "2026-01-11T19:15:42.100Z",
    "failureReason": "insufficient_funds",
    "metadata": {
      "batchId": "BATCH-001"
    }
  }
}
CampoTipoDescrição
withdrawalIdstringID único do saque
environmentstringAmbiente (production ou sandbox)
amountnumberValor do saque
feeAmountnumberTaxa do saque
netAmountnumberValor líquido que seria transferido
currencystringMoeda (BRL)
statusstringStatus do saque (failed)
failedAtstringData/hora da falha em ISO 8601
failureReasonstringMotivo da falha (insufficient_funds, invalid_account, etc.)
metadataobjectMetadados customizados do saque (opcional)

withdrawal_reversed

Enviado quando um saque é estornado pelo PSP.
{
  "event": "withdrawal_reversed",
  "eventId": "f12a34b5-6c78-9d01-ef23-456789abcdef",
  "timestamp": "2026-01-11T20:00:00.000Z",
  "data": {
    "reversalTransactionId": "f12a34b5-6c78-9d01-ef23-456789abcdef",
    "originalTransactionId": "e73775b5-70ee-4bad-be4c-4acff9890e27",
    "environment": "sandbox",
    "amount": 500.00,
    "feeAmount": 0,
    "netAmount": 500.00,
    "currency": "BRL",
    "paymentMethod": "pix",
    "status": "completed",
    "reversedAt": "2026-01-11T20:00:00.000Z",
    "metadata": {
      "batchId": "BATCH-001"
    }
  }
}
CampoTipoDescrição
reversalTransactionIdstringID único da transação de estorno
originalTransactionIdstringID do saque original que foi estornado
environmentstringAmbiente (production ou sandbox)
amountnumberValor do estorno
feeAmountnumberTaxa do estorno
netAmountnumberValor líquido do estorno
currencystringMoeda (BRL)
paymentMethodstringMétodo de pagamento (pix)
statusstringStatus do estorno (completed)
reversedAtstringData/hora do estorno em ISO 8601
externalReferencestringSua referência externa do saque original (opcional)
metadataobjectMetadados customizados do saque original (opcional)

balance_block_created

Enviado quando um bloqueio de saldo é criado (MED, judicial ou administrativo).
{
  "event": "balance_block_created",
  "eventId": "d4e5f6a7-8b9c-0d1e-2f3a-456789abcdef",
  "timestamp": "2026-01-11T19:30:00.000Z",
  "data": {
    "blockId": "d4e5f6a7-8b9c-0d1e-2f3a-456789abcdef",
    "transactionId": "a0b78f10-c7f4-4f5d-98dd-3e36eafeb812",
    "environment": "production",
    "amount": 1500.00,
    "currency": "BRL",
    "blockType": "med",
    "referenceNumber": "MED-2026-001234",
    "reason": "Notificação de infração Pix recebida",
    "status": "awaiting_response",
    "createdAt": "2026-01-11T19:30:00.000Z"
  }
}
CampoTipoDescrição
blockIdstringID único do bloqueio
transactionIdstringID da transação original bloqueada
environmentstringAmbiente (production ou sandbox)
amountnumberValor bloqueado em reais
currencystringMoeda (BRL)
blockTypestringTipo do bloqueio (med, judicial ou administrative)
referenceNumberstringNúmero de referência do bloqueio
reasonstringMotivo do bloqueio
statusstringStatus inicial (awaiting_response)
createdAtstringData/hora da criação em ISO 8601

balance_block_approved

Enviado quando um bloqueio de saldo é aprovado e o valor é devolvido ao pagador original.
{
  "event": "balance_block_approved",
  "eventId": "d4e5f6a7-8b9c-0d1e-2f3a-456789abcdef",
  "timestamp": "2026-01-12T14:00:00.000Z",
  "data": {
    "blockId": "d4e5f6a7-8b9c-0d1e-2f3a-456789abcdef",
    "transactionId": "a0b78f10-c7f4-4f5d-98dd-3e36eafeb812",
    "environment": "production",
    "amount": 1500.00,
    "currency": "BRL",
    "blockType": "med",
    "referenceNumber": "MED-2026-001234",
    "reason": "Notificação de infração Pix recebida",
    "resolutionReason": "Devolução confirmada pelo BACEN",
    "status": "approved",
    "createdAt": "2026-01-11T19:30:00.000Z",
    "resolvedAt": "2026-01-12T14:00:00.000Z"
  }
}
CampoTipoDescrição
blockIdstringID único do bloqueio
transactionIdstringID da transação original bloqueada
environmentstringAmbiente (production ou sandbox)
amountnumberValor bloqueado em reais
currencystringMoeda (BRL)
blockTypestringTipo do bloqueio (med, judicial ou administrative)
referenceNumberstringNúmero de referência do bloqueio
reasonstringMotivo original do bloqueio
resolutionReasonstringMotivo da resolução (opcional)
statusstringStatus do bloqueio (approved)
createdAtstringData/hora da criação em ISO 8601
resolvedAtstringData/hora da resolução em ISO 8601

balance_block_rejected

Enviado quando um bloqueio de saldo é rejeitado e o valor retorna ao saldo disponível do lojista.
{
  "event": "balance_block_rejected",
  "eventId": "e5f6a7b8-9c0d-1e2f-3a4b-567890abcdef",
  "timestamp": "2026-01-12T14:00:00.000Z",
  "data": {
    "blockId": "e5f6a7b8-9c0d-1e2f-3a4b-567890abcdef",
    "transactionId": "b1c89f20-d8e5-5f6a-99ee-4f47eafeb923",
    "environment": "production",
    "amount": 250.00,
    "currency": "BRL",
    "blockType": "med",
    "referenceNumber": "MED-2026-005678",
    "reason": "Notificação de infração Pix recebida",
    "resolutionReason": "Defesa aceita - transação legítima comprovada",
    "status": "rejected",
    "createdAt": "2026-01-11T19:30:00.000Z",
    "resolvedAt": "2026-01-12T14:00:00.000Z"
  }
}
CampoTipoDescrição
blockIdstringID único do bloqueio
transactionIdstringID da transação original bloqueada
environmentstringAmbiente (production ou sandbox)
amountnumberValor bloqueado em reais
currencystringMoeda (BRL)
blockTypestringTipo do bloqueio (med, judicial ou administrative)
referenceNumberstringNúmero de referência do bloqueio
reasonstringMotivo original do bloqueio
resolutionReasonstringMotivo da resolução (opcional)
statusstringStatus do bloqueio (rejected)
createdAtstringData/hora da criação em ISO 8601
resolvedAtstringData/hora da resolução em ISO 8601

Boas Práticas

Retorne um status 200 OK o mais rápido possível. Processe o webhook de forma assíncrona se necessário.
Use o eventId para evitar processar o mesmo evento duas vezes. Webhooks podem ser reenviados em caso de falha.
Configure seu endpoint apenas com HTTPS para garantir a segurança dos dados.

Retentativas

Se o seu endpoint não responder com status 2xx, tentaremos reenviar o webhook:
  • 5 tentativas com backoff exponencial
  • Intervalo inicial: 2 segundos
  • Intervalo máximo: ~30 segundos entre tentativas
Após 5 tentativas sem sucesso, o webhook é marcado como falho.