SaciPix

Webhooks

Receba eventos em tempo real e valide a assinatura.

Webhooks avisam seu servidor quando algo acontece. Cadastre endpoints HTTPS no painel, em Desenvolvedores, na tela Webhooks, e escolha os eventos de cada um. Em cobranças e saques, o campo opcional webhookUrl envia os eventos daquele recurso para mais uma URL, com o mesmo segredo.

O id identifica o evento, e data é o recurso completo no momento do evento, no mesmo formato da API.

POST para sua URL
{
  "id": "3f0a7d7c-52ce-4c2b-8f0e-1a6d9b2e4c11",
  "type": "charge.paid",
  "livemode": true,
  "createdAt": "2026-11-01T15:06:12.000Z",
  "data": {
    "id": "7c1e4f2a-3b58-4e0d-9a6c-2f8d1b7e5a10",
    "object": "charge",
    "livemode": true,
    "status": "paid",
    "amount": 15000,
    "fee": 299,
    "net": 14701,
    "currency": "BRL",
    "reference": "PEDIDO-0001",
    "description": "Plano anual",
    "customer": {
      "name": "Ana Souza",
      "document": "12345678901",
      "email": "ana@example.com"
    },
    "metadata": {
      "pedido": "0001"
    },
    "pix": {
      "copyPaste": "0002...",
      "qrCodeBase64": "iVBOR..."
    },
    "checkoutUrl": "https://painel.example.com/pay/7c1e4f2a-3b58-4e0d-9a6c-2f8d1b7e5a10",
    "payer": null,
    "failureReason": null,
    "paidAt": "2026-11-01T15:06:12.000Z",
    "refundedAt": null,
    "createdAt": "2026-11-01T15:04:05.000Z"
  }
}

Eventos

EventoQuando
charge.createdCobrança criada, com o Pix disponível.
charge.paidPagamento confirmado e saldo creditado.
charge.refundedPix estornado e saldo debitado.
payout.createdSaque criado e valor reservado.
payout.paidSaque concluído.
payout.failedSaque falhou, foi rejeitado ou cancelado, e a reserva voltou ao saldo. Veja status e failureReason.
test.pingDisparado pelo botão de teste no painel. Tem data vazio.

Verificar a assinatura

Todo envio traz estes cabeçalhos. Valide a assinatura antes de usar o conteúdo, porque sua URL é pública e qualquer um pode chamá-la.

CabeçalhoConteúdo
X-Webhook-IdId do evento. É igual nas retentativas.
X-Webhook-Signaturet=<timestamp>,v1=<assinatura>

A assinatura é o HMAC-SHA256 em hexadecimal de <t>.<corpo cru>, usando o segredo whsec_ do ambiente, disponível no painel.

  • Calcule sobre o corpo exatamente como chegou, antes de qualquer parse.
  • Compare em tempo constante.
  • Recuse t com mais de 5 minutos de diferença para evitar repetição de mensagens capturadas. Cada tentativa traz um novo t.
import express from 'express';
import { Gateway } from '@gateway/sdk';

const app = express();

// O corpo precisa chegar cru: JSON re-serializado invalida a assinatura.
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
  let event;
  try {
    event = Gateway.webhooks.verify(
      req.body,
      req.headers['x-webhook-signature'],
      process.env.WEBHOOK_SECRET,
    );
  } catch {
    return res.sendStatus(400);
  }

  res.sendStatus(200);
  enqueue(event); // processe depois de responder
});

Retentativas

Uma entrega só conta como recebida com resposta 2xx em até 10 segundos. Redirecionamentos não são seguidos e contam como falha. Depois de uma falha, enviamos de novo nestes intervalos:

Retentativa1ª2ª3ª4ª5ª6ª
Espera1 min5 min30 min2 h6 h24 h

Depois da 6ª retentativa a entrega para. O painel mostra cada entrega e permite reenviar manualmente.

Boas práticas

  • Responda 200 imediatamente e processe em uma fila.
  • Use o id do evento para ignorar duplicatas: a entrega é pelo menos uma vez.
  • Não dependa da ordem de chegada. Antes de liberar um pedido, se quiser garantia extra, consulte GET /v1/charges/{id}.
  • Confira o campo livemode para não misturar eventos de teste com produção.
  • Endpoints precisam usar HTTPS e não podem apontar para endereços internos.