Recaudo Docs

Eventos

Webhooks

Os webhooks avisam você em tempo real sobre eventos na sua conta. Configure um endpoint HTTPS e receba atualizações automáticas.

Tipos de eventos

Pagamentos

  • payment.created
  • payment.succeeded
  • payment.failed
  • payment.refunded

Links de pagamento

  • payment_link.created
  • payment_link.paid
  • payment_link.expired

Assinaturas

  • subscription.created
  • subscription.updated
  • subscription.canceled
  • subscription.paused
  • subscription.resumed
  • subscription.trial_ending

Faturas

  • invoice.created
  • invoice.paid
  • invoice.payment_failed
  • invoice.upcoming

Formato dos dados

Dados do webhook
{
  "id": "evt_1a2b3c4d5e6f",
  "object": "event",
  "type": "payment.succeeded",
  "api_version": "2024-01-01",
  "created": 1705312200,
  "data": {
    "object": {
      "id": "pi_abc123xyz",
      "object": "payment_intent",
      "amount": 500.00,
      "currency": "MXN",
      "status": "succeeded",
      "customer_id": "8e250c25-9d84-4892-98ec-d71fc1fcd3c7",
      ...
    }
  }
}

Verificação de assinatura (HMAC)

Cada webhook inclui um cabeçalho X-Recaudo-Signature que você deve verificar para garantir que a mensagem vem do Recaudo.

<?php
// Obtener el payload y la firma
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_RECAUDO_SIGNATURE'];
$secret = 'whsec_tu_webhook_secret';

// Extraer timestamp y firma del header
// Formato: t=timestamp,v1=signature
$parts = explode(',', $signature);
$timestamp = substr($parts[0], 2);
$receivedSignature = substr($parts[1], 3);

// Calcular la firma esperada
$signedPayload = $timestamp . '.' . $payload;
$expectedSignature = hash_hmac('sha256', $signedPayload, $secret);

// Verificar
if (hash_equals($expectedSignature, $receivedSignature)) {
    // Firma valida - procesar el evento
    $event = json_decode($payload, true);

    switch ($event['type']) {
        case 'payment.succeeded':
// Manejar pago exitoso
break;
        case 'subscription.canceled':
// Manejar cancelacion
break;
    }

    http_response_code(200);
} else {
    // Firma invalida
    http_response_code(400);
}
const crypto = require('crypto');

app.post('/webhooks/recaudo', express.raw({type: 'application/json'}), (req, res) => {
  const payload = req.body;
  const signature = req.headers['x-recaudo-signature'];
  const secret = 'whsec_tu_webhook_secret';

  // Extraer timestamp y firma
  const parts = signature.split(',');
  const timestamp = parts[0].split('=')[1];
  const receivedSignature = parts[1].split('=')[1];

  // Calcular firma esperada
  const signedPayload = `${timestamp}.${payload}`;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  // Verificar
  if (crypto.timingSafeEqual(
    Buffer.from(expectedSignature),
    Buffer.from(receivedSignature)
  )) {
    const event = JSON.parse(payload);

    switch (event.type) {
      case 'payment.succeeded':
        // Manejar pago exitoso
        break;
      case 'subscription.canceled':
        // Manejar cancelacion
        break;
    }

    res.status(200).send('OK');
  } else {
    res.status(400).send('Invalid signature');
  }
});
import hmac
import hashlib
from flask import Flask, request

app = Flask(__name__)

@app.route('/webhooks/recaudo', methods=['POST'])
def webhook():
    payload = request.data
    signature = request.headers.get('X-Recaudo-Signature')
    secret = 'whsec_tu_webhook_secret'

    # Extraer timestamp y firma
    parts = signature.split(',')
    timestamp = parts[0].split('=')[1]
    received_signature = parts[1].split('=')[1]

    # Calcular firma esperada
    signed_payload = f"{timestamp}.{payload.decode()}"
    expected_signature = hmac.new(
        secret.encode(),
        signed_payload.encode(),
        hashlib.sha256
    ).hexdigest()

    # Verificar
    if hmac.compare_digest(expected_signature, received_signature):
        event = request.json

        if event['type'] == 'payment.succeeded':
# Manejar pago exitoso
pass
        elif event['type'] == 'subscription.canceled':
# Manejar cancelacion
pass

        return 'OK', 200
    else:
        return 'Invalid signature', 400

Boas práticas

  • Sempre verifique a assinatura HMAC antes de processar o evento
  • Responda com 200 rapidamente e processe de forma assíncrona
  • Implemente idempotência usando o ID do evento
  • Use HTTPS com um certificado válido
  • Os webhooks são reenviados automaticamente se falharem (até 3 vezes)

API de Webhook Endpoints

Gerencie seus webhook endpoints de forma programática.

POST /v1/webhook-endpoints

Criar um novo webhook endpoint.

Corpo da requisição
{
  "url": "https://tu-servidor.com/webhooks/recaudo",
  "events": ["payment.succeeded", "invoice.paid", "customer.created"],
  "description": "Webhook principal de producción",
  "is_active": true
}
GET /v1/webhook-endpoints

Listar todos os webhook endpoints configurados.

GET /v1/webhook-endpoints/{'{id}'}

Ver os detalhes do endpoint incluindo o secret para verificar assinaturas.

Resposta
{
  "id": "we_abc123",
  "url": "https://tu-servidor.com/webhooks/recaudo",
  "events": ["payment.succeeded", "invoice.paid"],
  "secret": "whsec_tu_webhook_secret",
  "is_active": true,
  "description": "Webhook principal",
  "created_at": "2026-04-01T00:00:00Z"
}
PUT /v1/webhook-endpoints/{'{id}'}

Atualizar a URL, os eventos ou o status do endpoint.

Corpo da requisição
{
  "url": "https://nueva-url.com/webhooks",
  "events": ["payment.succeeded", "payment.failed"],
  "is_active": false
}
DELETE /v1/webhook-endpoints/{'{id}'}

Excluir um webhook endpoint.

POST /v1/webhook-endpoints/{'{id}'}/test

Enviar um evento de teste ao endpoint para verificar a conectividade.

POST /v1/webhook-endpoints/{'{id}'}/rotate-secret

Gerar um novo secret para o endpoint. O secret anterior deixa de valer imediatamente.

GET /v1/webhook-endpoints/{'{id}'}/deliveries

Ver o histórico de entregas do endpoint com status e códigos de resposta.

POST /v1/webhook-endpoints/{'{id}'}/deliveries/{'{delivery_id}'}/resend

Reenviar uma entrega com falha.

Esta página ajudou? Obrigado por avisar.
Esc