Webhooks

Notificações HTTP em tempo real, com assinatura HMAC e retry.

Webhooks são notificações HTTP POST enviadas pela Stone sempre que um evento relevante acontece — pagamento aprovado, conta criada, transferência liquidada, transação na maquininha conciliada.

Eventos disponíveis (parcial)

charge.created            charge.paid              charge.failed
charge.refunded           charge.disputed
checkout.completed        checkout.expired
pos.transaction.created   pos.transaction.settled  pos.terminal.online
banking.account.opened    banking.transfer.completed
pix.received              pix.return.completed

Assinatura — HMAC-SHA256

Todo webhook traz o header X-Stone-Signature com a assinatura do corpo:

X-Stone-Signature: t=1714248000,v1=5257a869e7ec...

Node.js

const crypto = require('crypto');

function verifyWebhook(rawBody, signatureHeader, secret) {
  const [t, v1] = signatureHeader.split(',').map(p => p.split('=')[1]);
  const signed = \`\${t}.\${rawBody}\`;
  const expected = crypto.createHmac('sha256', secret).update(signed).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}

Python

import hmac, hashlib

def verify_webhook(raw_body: bytes, signature: str, secret: str) -> bool:
    parts = dict(p.split('=') for p in signature.split(','))
    signed = f"{parts['t']}.{raw_body.decode()}".encode()
    expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts['v1'])

Retry e idempotência de entrega

  • Tentamos entregar por até 72 horas, com backoff exponencial (1m, 5m, 30m, 2h, 6h…)
  • Cada entrega traz X-Stone-Delivery-Id único — use para deduplicar
  • Responda 2xx em até 10s. Qualquer outra coisa = retry.
Boa prática

Trate o webhook como fato bruto. Persista o evento, responda 200, e processe assincronamente. Reduz drasticamente os retries e melhora a observabilidade.