Visão Geral de Webhooks
A A55 envia webhooks via HTTP POST para o seu servidor quando os status de cobrança, assinatura e pagamento mudam. Webhooks permitem reações em tempo real sem polling.
Por que webhooks
| Abordagem | Latência | Confiabilidade | Carga na A55 |
|---|---|---|---|
| Webhooks (push) | Segundos | At-least-once com retentativas | Mínima |
| Polling (pull) | Depende do intervalo | Nunca perde (compensa atrasos) | Maior |
Use webhooks como canal primário de notificação e polling como fallback de reconciliação.
Configuração
Defina webhook_url na requisição de cobrança, ou configure uma URL padrão no dashboard da A55.
| Parâmetro | Escopo | Descrição |
|---|---|---|
webhook_url na cobrança | Por cobrança | Recebe eventos apenas daquela cobrança |
| URL padrão no dashboard | Toda a conta | Usada quando webhook_url é omitida |
Detalhes de entrega
| Propriedade | Valor |
|---|---|
| Método | POST |
| Content-Type | application/json |
| Timeout | 30 segundos |
| TLS | Somente HTTPS (HTTP é rejeitado) |
Verificação de assinatura HMAC
A A55 assina todo webhook com HMAC-SHA256. Sempre verifique antes de processar.
| Header | Conteúdo |
|---|---|
X-Webhook-Signature | sha256={hex_signature} |
X-Webhook-Timestamp | Timestamp Unix (segundos) |
Etapas de verificação
- Extraia os headers
X-Webhook-SignatureeX-Webhook-Timestamp - Rejeite se o timestamp for mais antigo que 5 minutos (proteção contra replay)
- Construa o payload assinado:
{timestamp}.{raw_body} - Compute HMAC-SHA256 com seu webhook secret
- Compare usando comparação timing-safe
- Processe o evento somente se a assinatura corresponder
- Python
- JavaScript
import hmac, hashlib, time
def verify_webhook(payload: bytes, signature: str, timestamp: str, secret: str) -> bool:
if abs(time.time() - int(timestamp)) > 300:
return False
signed_payload = f"{timestamp}.".encode() + payload
expected = hmac.new(secret.encode(), signed_payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature.removeprefix("sha256="))
const crypto = require('crypto');
function verifyWebhook(payload, signature, timestamp, secret) {
if (Math.abs(Date.now() / 1000 - parseInt(timestamp)) > 300) return false;
const expected = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${payload}`)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature.replace('sha256=', ''))
);
}
Nunca processe um webhook sem verificar a assinatura HMAC. Webhooks não verificados podem ser forjados por atacantes.
Política de retentativas
Entregas com falha são retentadas com backoff exponencial ao longo de 24 horas:
| Tentativa | Atraso | Acumulado |
|---|---|---|
| 1 | Imediata | T+0 |
| 2 | 1 minuto | T+1m |
| 3 | 5 minutos | T+6m |
| 4 | 30 minutos | T+36m |
| 5 | 2 horas | T+2h 36m |
| 6 | 6 horas | T+8h 36m |
| 7 | 24 horas | T+32h 36m |
Após 7 tentativas falhadas, o evento é marcado como falha no dashboard.
O que dispara uma retentativa
| Resposta | Retenta? | Motivo |
|---|---|---|
| 200–299 | Não | Entregue com sucesso |
| 400–499 | Não | Erro do cliente — retentar não ajudará |
| 500–599 | Sim | Erro do servidor — transiente |
| Timeout (>30s) | Sim | Endpoint muito lento |
| Conexão recusada | Sim | Endpoint indisponível |
Idempotência
Webhooks usam entrega at-least-once. O mesmo evento pode chegar mais de uma vez. Seu handler deve ser idempotente.
def handle_webhook(event):
event_id = event["id"]
if db.webhook_events.find_one({"event_id": event_id, "status": "completed"}):
return Response(status=200)
db.webhook_events.upsert({"event_id": event_id, "status": "processing"})
process_event(event)
db.webhook_events.update({"event_id": event_id, "status": "completed"})
return Response(status=200)
Retorne HTTP 200 imediatamente após receber o evento. Processe lógica pesada em um job de background para que o handler não estoure o timeout.
Tipos de evento
| Domínio | Eventos |
|---|---|
| Cobranças | charge.authorized, charge.captured, charge.failed, charge.refunded, charge.cancelled, charge.chargeback |
| PIX | pix.received, pix.expired, pix.refunded |
| Boleto | boleto.paid, boleto.expired, boleto.cancelled |
| Assinaturas | subscription.created, subscription.renewed, subscription.failed, subscription.cancelled |
Veja Webhook de cobrança para detalhes do payload.
Testes
| Ferramenta | Melhor para |
|---|---|
| webhook.site | Inspecionar payloads visualmente |
| ngrok | Encaminhar para localhost |
| A55 sandbox | Eventos de teste similares a produção |