Skip to main content

Visão geral

Webhooks são notificações HTTP enviadas pela Upay Gateway API para sua aplicação quando eventos importantes ocorrem. Isso permite que você reaja em tempo real a mudanças de status, pagamentos confirmados e outros eventos sem precisar fazer polling constante.

Pré-requisitos

Antes de começar, você precisa:
  • Uma conta ativa na Upay
  • Sua API Key configurada (veja Autenticação)
  • Um endpoint HTTPS público para receber webhooks

Funcionalidades

  • Eventos em tempo real: Receba notificações instantâneas
  • Múltiplos eventos: Configure webhooks para diferentes tipos de eventos
  • Retry automático: Tentativas automáticas em caso de falha
  • Segurança: Assinatura HMAC para validar requisições
  • Histórico: Visualize todos os eventos enviados
  • Múltiplas URLs: Configure diferentes endpoints para diferentes eventos

Criando uma assinatura de webhook

Requisição Básica

curl -X POST "https://upay-sistema-api.onrender.com/api/v1/webhooks/subscriptions" \
  -H "Authorization: Bearer SUA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://meusite.com.br/webhooks/upay",
    "events": ["transaction.completed", "transaction.failed"],
    "description": "Webhook para notificações de transação"
  }'

Resposta

{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "url": "https://meusite.com.br/webhooks/upay",
    "events": ["transaction.completed", "transaction.failed"],
    "description": "Webhook para notificações de transação",
    "status": "ACTIVE",
    "secret": "whsec_abc123...",
    "createdAt": "2025-12-30T00:00:00.000Z"
  }
}
Guarde o secret em local seguro. Ele é necessário para validar a autenticidade dos webhooks recebidos e não será exibido novamente.
O Gateway envia webhooks usando o método POST para a URL configurada. Cada envio inclui o cabeçalho X-Webhook-Signature para validação de integridade.

Cabeçalhos HTTP

CabeçalhoDescrição
Content-TypeSempre application/json
X-Webhook-SignatureAssinatura HMAC-SHA256 (formato: sha256=ASSINATURA)
X-Webhook-EventTipo do evento disparado
X-Webhook-DeliveryID único da entrega (UUID)
User-AgentUPAY-Webhook/1.0

Eventos Suportados

EventoDescrição
transaction.createdUma nova transação foi gerada
transaction.updatedUma transação teve seus dados atualizados
transaction.completedPagamento confirmado com sucesso
transaction.failedPagamento falhou ou foi recusado
payment_link.createdUm link de pagamento foi criado
payment_link.updatedUm link de pagamento foi editado
balance.updatedO saldo da conta foi alterado

Eventos de Transação (Transaction)

  • transaction.created - Transação criada
  • transaction.updated - Status da transação atualizado
  • transaction.completed - Pagamento confirmado/concluído
  • transaction.failed - Pagamento falhou
  • payment_link.created - Link de pagamento criado
  • payment_link.updated - Link de pagamento atualizado

Exemplo completo

const response = await fetch('https://upay-sistema-api.onrender.com/api/v1/webhooks/subscriptions', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: 'https://meusite.com.br/webhooks/upay',
    events: [
      'transaction.completed',
      'transaction.failed'
    ],
    description: 'Webhook para processar notificações de pagamento'
  })
});

const { data } = await response.json();
console.log('Webhook Secret:', data.secret);

Listando assinaturas

Listar todas as assinaturas

curl -X GET "https://upay-sistema-api.onrender.com/api/webhooks/subscriptions" \
  -H "Authorization: Bearer SUA_API_KEY"

Listar eventos enviados

curl -X GET "https://upay-sistema-api.onrender.com/api/webhooks/events?page=1&limit=20" \
  -H "Authorization: Bearer SUA_API_KEY"

Atualizando uma assinatura

curl -X PUT "https://upay-sistema-api.onrender.com/api/webhooks/subscriptions/{id}" \
  -H "Authorization: Bearer SUA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://meusite.com.br/webhooks/upay-v2",
    "events": ["transaction.completed", "transaction.failed"],
    "isActive": true
  }'

Deletando uma assinatura

curl -X DELETE "https://upay-sistema-api.onrender.com/api/webhooks/subscriptions/{id}" \
  -H "Authorization: Bearer SUA_API_KEY"

Validando a Assinatura

Para garantir que o webhook foi enviado pela UPAY, você deve validar o header X-Webhook-Signature.
  1. Obtenha o corpo bruto (raw body) da requisição.
  2. Gere um HMAC-SHA256 usando o corpo bruto e o seu WEBHOOK_SECRET.
  3. Compare o resultado (em hexadecimal) com o valor recebido no header (removendo o prefixo sha256=).
Exemplo em Node.js:
const crypto = require('crypto');

function verifySignature(payload, signatureHeader, secret) {
  const [algorithm, signature] = signatureHeader.split('=');

  if (algorithm !== 'sha256') return false;

  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// No seu endpoint de webhook
app.post('/webhooks/upay', express.json(), (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const secret = process.env.UPAY_WEBHOOK_SECRET;

  if (!verifySignature(req.rawBody, signature, secret)) { // req.rawBody é necessário para a validação
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Processar webhook
  const event = req.body;
  console.log('Evento recebido:', event.type);

  res.status(200).json({ received: true });
});

Exemplo de Validação (Python)

import hmac
import hashlib
import json

def validate_webhook_signature(payload, signature, secret):
    expected_signature = hmac.new(
        secret.encode('utf-8'),
        json.dumps(payload).encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    
    return hmac.compare_digest(signature, expected_signature)

# No seu endpoint de webhook
@app.route('/webhooks/upay', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Webhook-Signature', '').replace('sha256=', '')
    secret = os.getenv('UPAY_WEBHOOK_SECRET')
    
    if not validate_webhook_signature(request.json, signature, secret):
        return jsonify({'error': 'Invalid signature'}), 401
    
    # Processar webhook
    event = request.json
    print(f"Evento recebido: {event['type']}")
    
    return jsonify({'received': True}), 200

Estrutura do payload

Exemplo: transaction.completed

{
  "id": "evt_5f9d7a2b-1234-5678-90ab-cdef12345678",
  "type": "transaction.completed",
  "timestamp": "2024-03-15T10:30:00.000Z",
  "data": {
    "id": "tx_240315_a7b2c9",
    "userId": "usr_987654321",
    "value": 150.00,
    "amountCents": 15000,
    "status": "PAID",
    "paymentMethod": "PIX",
    "paymentDate": "2024-03-15T10:29:55.000Z",
    "completedAt": "2024-03-15T10:30:00.000Z"
  },
  "subscription": {
    "id": "sub_12345678",
    "url": "https://suaapiv1.com/webhooks"
  }
}

Exemplo: transaction.failed

{
  "id": "evt_def456",
  "type": "transaction.failed",
  "createdAt": "2025-12-30T00:00:00.000Z",
  "data": {
    "transactionId": "550e8400-e29b-41d4-a716-446655440000",
    "paymentLinkId": "550e8400-e29b-41d4-a716-446655440001",
    "amount": 199.00,
    "amountCents": 19900,
    "currency": "BRL",
    "paymentMethod": "credit_card",
    "status": "FAILED",
    "error": "Cartão recusado",
    "errorCode": "CARD_DECLINED"
  }
}

🔄 Retry e Confiabilidade

A UPay tenta entregar webhooks automaticamente:
  1. Primeira tentativa: Imediata
  2. Retry 1: Após 1 minuto
  3. Retry 2: Após 5 minutos
  4. Retry 3: Após 15 minutos
  5. Retry 4: Após 1 hora
Seu endpoint deve responder com status HTTP 200-299 para confirmar o recebimento. Respostas com erro ou timeout resultarão em retry.

Boas práticas

  1. Responda rapidamente: Processe webhooks de forma assíncrona quando possível
  2. Valide a assinatura: Sempre valide o X-Webhook-Signature
  3. Idempotência: Processe eventos de forma idempotente usando o id do evento
  4. Logs: Mantenha logs de todos os webhooks recebidos
  5. Testes: Use webhooks de teste para validar sua implementação

Testando webhooks

Usando ngrok (Desenvolvimento Local)

# Instale o ngrok
npm install -g ngrok

# Exponha sua aplicação local
ngrok http 3000

# Use a URL do ngrok na assinatura do webhook
# Ex: https://abc123.ngrok.io/webhooks/upay

Endpoint de Teste

app.post('/webhooks/upay', express.json(), (req, res) => {
  console.log('Webhook recebido:', JSON.stringify(req.body, null, 2));
  res.status(200).json({ received: true });
});

Próximos passos

Referência da API

Veja todos os endpoints disponíveis

Links de Pagamento

Configure webhooks para links de pagamento