Skip to main content
Webhooks permitem que sua aplicação seja notificada automaticamente quando eventos ocorrem — como um pagamento confirmado ou uma transação expirada. Em vez de fazer polling, a Bob Payments avisa você.

Configurando um webhook

1

Acesse o Dashboard

Vá em Webhooks → Adicionar webhook no seu projeto.
2

Informe a URL

Insira a URL HTTPS da sua aplicação que receberá os eventos (ex: https://suaapi.com/webhooks/bob).
3

Copie o secret

Um secret é gerado automaticamente. Guarde-o para verificar a autenticidade das requisições.
Webhooks funcionam normalmente no sandbox. Use-os para testar o fluxo completo antes de ir a produção.

Eventos disponíveis

Disparado quando uma cobrança PIX é criada. Inclui pixCode e expirationDate.
{
  "event": "transaction.created",
  "type": "transaction",
  "title": "Transação Criada",
  "message": "Nova transação de R$ 150,00 aguardando pagamento",
  "data": {
    "transactionId": "clx1abc123",
    "externalId": "pedido-001",
    "amount": 150.00,
    "product": "Plano Premium",
    "customerName": "João Silva",
    "customer": {
      "name": "João Silva",
      "email": "[email protected]",
      "phone": "11999990000",
      "document": "12345678901",
      "documentType": "CPF",
      "address": {
        "street": "Rua das Flores",
        "streetNumber": "123",
        "neighborhood": "Centro",
        "complement": "",
        "zipCode": "01310100",
        "city": "São Paulo",
        "state": "SP",
        "country": "BR"
      }
    },
    "gateway": "meu-gateway",
    "pixCode": "00020126580014br.gov.bcb.pix...",
    "expirationDate": "2026-03-10T15:30:00.000Z",
    "createdAt": "2026-03-10T14:30:00.000Z"
  },
  "timestamp": "2026-03-10T14:30:00.000Z"
}
Disparado quando um pagamento PIX é confirmado. Use para liberar o produto ou serviço ao cliente. Inclui fee quando há taxa.
{
  "event": "transaction.paid",
  "type": "transaction",
  "title": "Transação Paga",
  "message": "Transação de R$ 150,00 confirmada",
  "data": {
    "transactionId": "clx1abc123",
    "externalId": "pedido-001",
    "amount": 150.00,
    "product": "Plano Premium",
    "customer": {
      "name": "João Silva",
      "email": "[email protected]",
      "phone": "11999990000",
      "document": "12345678901",
      "documentType": "CPF",
      "address": {
        "street": "Rua das Flores",
        "streetNumber": "123",
        "neighborhood": "Centro",
        "complement": "",
        "zipCode": "01310100",
        "city": "São Paulo",
        "state": "SP",
        "country": "BR"
      }
    },
    "gateway": "meu-gateway",
    "originDomain": "meusite.com.br",
    "isSandbox": false,
    "fee": { "amount": 3.50 }
  },
  "timestamp": "2026-03-10T14:35:00.000Z"
}
Disparado quando uma transação expira sem pagamento. Use para notificar o cliente ou criar nova cobrança. Não inclui gateway.
{
  "event": "transaction.expired",
  "type": "transaction",
  "title": "Transação Expirada",
  "message": "Transação de R$ 150,00 expirou",
  "data": {
    "transactionId": "clx1abc123",
    "externalId": "pedido-001",
    "amount": 150.00,
    "product": "Plano Premium",
    "customer": {
      "name": "João Silva",
      "email": "[email protected]",
      "phone": "11999990000",
      "document": "12345678901",
      "documentType": "CPF",
      "address": { "...": "..." }
    },
    "originDomain": "meusite.com.br",
    "isSandbox": true
  },
  "timestamp": "2026-03-11T03:00:00.000Z"
}
Disparado quando uma transação é estornada.
{
  "event": "transaction.refunded",
  "type": "transaction",
  "title": "Transação Reembolsada",
  "message": "Transação de R$ 150,00 reembolsada",
  "data": {
    "transactionId": "clx1abc123",
    "externalId": "pedido-001",
    "amount": 150.00,
    "product": "Plano Premium",
    "customer": { "...": "igual ao paid" },
    "gateway": "meu-gateway",
    "originDomain": "meusite.com.br",
    "isSandbox": false
  },
  "timestamp": "2026-03-10T15:00:00.000Z"
}
Disparado quando uma transação é cancelada manualmente.
{
  "event": "transaction.cancelled",
  "type": "transaction",
  "title": "Transação Cancelada",
  "message": "Transação de R$ 150,00 cancelada",
  "data": {
    "transactionId": "clx1abc123",
    "externalId": "pedido-001",
    "amount": 150.00,
    "product": "Plano Premium",
    "customer": { "...": "igual ao paid" },
    "gateway": "meu-gateway",
    "originDomain": "meusite.com.br",
    "isSandbox": false
  },
  "timestamp": "2026-03-10T14:40:00.000Z"
}
Disparado quando uma transação falha no processamento.
{
  "event": "transaction.failed",
  "type": "transaction",
  "title": "transaction_failed",
  "message": "transaction_failed",
  "data": {
    "transactionId": "clx1abc123",
    "externalId": "pedido-001",
    "amount": 150.00,
    "product": "Plano Premium",
    "customer": { "...": "igual ao paid" },
    "gateway": "meu-gateway",
    "originDomain": "meusite.com.br",
    "isSandbox": false
  },
  "timestamp": "2026-03-10T14:33:00.000Z"
}

Verificando a assinatura

Cada requisição inclui dois headers de segurança:
HeaderDescrição
X-Webhook-SignatureHMAC-SHA256 do payload em hex
X-Webhook-TimestampISO 8601 do momento do envio
Verifique a assinatura sempre para garantir que a requisição veio da Bob Payments.
const crypto = require('crypto');

app.post('/webhooks/bob', (req, res) => {
  const sig = req.headers['x-webhook-signature'];
  const secret = process.env.BOB_WEBHOOK_SECRET;

  const expected = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(req.body))
    .digest('hex');

  const sigBuffer = Buffer.from(sig ?? '', 'utf8');
  const expectedBuffer = Buffer.from(expected, 'utf8');

  if (
    sigBuffer.length !== expectedBuffer.length ||
    !crypto.timingSafeEqual(sigBuffer, expectedBuffer)
  ) {
    return res.status(401).send('Assinatura inválida');
  }

  // Processe de forma assíncrona
  processEvent(req.body).catch(console.error);

  // Responda 200 imediatamente
  res.status(200).send('ok');
});
Retorne HTTP 200 imediatamente e processe o evento de forma assíncrona para evitar timeouts.

Ficou travado?

Fala com a gente: [email protected]