Guías
December 19, 2025

Webhooks Event-Driven: Tutorial Paso a Paso con Código Real | gigstack API 2025

TL;DR

Qué vas a aprender: Implementar webhooks event-driven con gigstack para recibir notificaciones en tiempo real de facturas emitidas, pagos recibidos y cambios de estatus fiscal.
Tiempo estimado: 25-30 minutos
Stack técnico: Node.js + Express + gigstack API


El Problema Técnico

Integrar facturación electrónica en México es un dolor de cabeza. Tienes que:

  • Hacer polling constante a una API para ver si cambió algo (ineficiente, costoso)
  • Entender todo el marco legal del SAT (eres developer, no contador)
  • Manejar certificados, sellos, timbrado, validaciones fiscales
  • Sincronizar estados entre tu sistema y el proveedor de facturación

Antes intenté conectar una API de facturación, tienes que aprender toda la parte fiscal, no eres contador, es frustrante como dev. gigstack te quita esa carga fiscal.

Con webhooks event-driven de gigstack, tu aplicación recibe notificaciones automáticas cuando algo importante sucede: se emite una factura, llega un pago, el SAT valida un CFDI. Nada de polling. Arquitectura reactiva, eficiente, escalable.


Pre-requisitos

Antes de empezar, asegúrate de tener:

  • ✅ Cuenta gigstack activa → Regístrate aquí
  • ✅ API key → Obtén la tuya en app.gigstack.pro/settings?subtab=api
  • ✅ Node.js v16+ instalado
  • ✅ Conocimientos básicos de Express.js y HTTP requests
  • ✅ Una URL pública accesible (puedes usar ngrok para desarrollo local)

Paso 1: Setup Inicial del Proyecto

Primero, crea tu proyecto Node.js e instala las dependencias necesarias:

# Crear directorio del proyecto
mkdir gigstack-webhooks-tutorial
cd gigstack-webhooks-tutorial

# Inicializar npm
npm init -y

# Instalar dependencias
npm install express body-parser crypto dotenv

Crea un archivo .env para tus credenciales:

GIGSTACK_API_KEY=tu_api_key_aqui
GIGSTACK_WEBHOOK_SECRET=tu_webhook_secret_aqui
PORT=3000

⚠️ Importante: El WEBHOOK_SECRET lo obtienes desde el dashboard de gigstack cuando configures tu webhook endpoint. Lo usaremos para validar que las peticiones realmente vienen de gigstack.


Paso 2: Crear el Servidor Express Básico

Crea server.js con la estructura base:

require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const crypto = require('crypto');

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware para parsear JSON
app.use(bodyParser.json());

// Health check endpoint
app.get('/health', (req, res) => {
  res.status(200).json({ status: 'ok', service: 'gigstack-webhooks' });
});

// Webhook endpoint principal
app.post('/webhooks/gigstack', async (req, res) => {
  try {
    // Validar firma del webhook (seguridad)
    if (!validateWebhookSignature(req)) {
      console.error('❌ Firma de webhook inválida');
      return res.status(401).json({ error: 'Invalid signature' });
    }

    // Procesar el evento
    const event = req.body;
    console.log('✅ Webhook recibido:', event.type);
    
    await handleWebhookEvent(event);
    
    // Responder rápido (gigstack espera 200 en <5 segundos)
    res.status(200).json({ received: true });
    
  } catch (error) {
    console.error('❌ Error procesando webhook:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

app.listen(PORT, () => {
  console.log(`🚀 Servidor escuchando en puerto ${PORT}`);
  console.log(`📥 Webhook endpoint: http://localhost:${PORT}/webhooks/gigstack`);
});

Paso 3: Implementar Validación de Firma (Seguridad Crítica)

Los webhooks deben validarse para evitar ataques. gigstack firma cada request con HMAC-SHA256:

/**
 * Valida que el webhook realmente venga de gigstack
 * gigstack envía la firma en el header 'X-Gigstack-Signature'
 */
function validateWebhookSignature(req) {
  const signature = req.headers['x-gigstack-signature'];
  const secret = process.env.GIGSTACK_WEBHOOK_SECRET;
  
  if (!signature || !secret) {
    console.warn('⚠️ Falta signature o secret');
    return false;
  }
  
  // Recrear la firma con el payload recibido
  const payload = JSON.stringify(req.body);
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  // Comparación segura contra timing attacks
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

🔒 Best Practice: Nunca proceses webhooks sin validar la firma. Un atacante podría enviar eventos falsos a tu endpoint.


Paso 4: Manejar Diferentes Tipos de Eventos

gigstack envía varios tipos de eventos. Implementa handlers específicos:

/**
 * Router principal de eventos webhook
 */
async function handleWebhookEvent(event) {
  const { type, data } = event;
  
  switch (type) {
    case 'invoice.created':
      await handleInvoiceCreated(data);
      break;
      
    case 'invoice.paid':
      await handleInvoicePaid(data);
      break;
      
    case 'invoice.cancelled':
      await handleInvoiceCancelled(data);
      break;
      
    case 'payment.received':
      await handlePaymentReceived(data);
      break;
      
    case 'cfdi.validated':
      await handleCFDIValidated(data);
      break;
      
    default:
      console.log(`⚠️ Evento no manejado: ${type}`);
  }
}

/**
 * Handler: Nueva factura creada
 */
async function handleInvoiceCreated(data) {
  console.log('📄 Nueva factura creada:', {
    id: data.id,
    folio: data.folio,
    total: data.total,
    cliente: data.customer.name
  });
  
  // Aquí va tu lógica de negocio:
  // - Actualizar base de datos
  // - Enviar email al cliente
  // - Notificar a tu sistema de contabilidad
  // - Trigger analytics event
  
  // Ejemplo: Actualizar DB
  // await db.invoices.create({
  //   gigstack_id: data.id,
  //   folio: data.folio,
  //   status: 'created',
  //   amount: data.total
  // });
}

/**
 * Handler: Factura pagada
 */
async function handleInvoicePaid(data) {
  console.log('💰 Factura pagada:', {
    id: data.id,
    folio: data.folio,
    payment_method: data.payment_method,
    paid_at: data.paid_at
  });
  
  // Lógica de negocio para pago recibido:
  // - Marcar como pagada en tu sistema
  // - Liberar producto/servicio
  // - Enviar confirmación al cliente
  // - Actualizar métricas de revenue
}

/**
 * Handler: Factura cancelada
 */
async function handleInvoiceCancelled(data) {
  console.log('🚫 Factura cancelada:', {
    id: data.id,
    folio: data.folio,
    reason: data.cancellation_reason
  });
  
  // Lógica para cancelaciones:
  // - Actualizar status en tu sistema
  // - Revertir operaciones si es necesario
  // - Notificar a contabilidad
}

/**
 * Handler: Pago recibido (puede aplicar a múltiples facturas)
 */
async function handlePaymentReceived(data) {
  console.log('💳 Pago recibido:', {
    id: data.id,
    amount: data.amount,
    method: data.method,
    invoices: data.applied_to_invoices
  });
}

/**
 * Handler: CFDI validado por el SAT
 */
async function handleCFDIValidated(data) {
  console.log('✅ CFDI validado por SAT:', {
    uuid: data.uuid,
    status: data.sat_status,
    validated_at: data.validated_at
  });
}

Paso 5: Testing con ngrok (Desarrollo Local)

Para probar webhooks en local, necesitas exponer tu servidor a internet. Usa ngrok:

# Instalar ngrok (macOS)
brew install ngrok

# O descarga desde https://ngrok.com/download

# Exponer tu servidor local
ngrok http 3000

Ngrok te dará una URL pública tipo https://abc123.ngrok.io. Copia esa URL y ve al dashboard de gigstack:

  1. Ve a app.gigstack.pro/settings?subtab=webhooks
  2. Crea un nuevo webhook endpoint
  3. URL: https://tu-ngrok-url.ngrok.io/webhooks/gigstack
  4. Selecciona los eventos que quieres recibir
  5. Guarda y copia el WEBHOOK_SECRET generado

Actualiza tu .env con el secret y reinicia tu servidor.


Paso 6: Disparar un Test Webhook

Desde el dashboard de gigstack, puedes enviar un webhook de prueba. Verás en tu consola:

🚀 Servidor escuchando en puerto 3000
📥 Webhook endpoint: http://localhost:3000/webhooks/gigstack
✅ Webhook recibido: invoice.created
📄 Nueva factura creada: {
  id: 'inv_abc123xyz',
  folio: 'A-1234',
  total: 1000.00,
  cliente: 'Cliente Demo SA de CV'
}

✅ ¡Funciona! Ahora puedes crear facturas desde gigstack y tu sistema reaccionará automáticamente.


Errores Comunes y Soluciones

❌ Error 1: "Invalid signature" constante

  • Solución: Verifica que el WEBHOOK_SECRET en tu .env coincida exactamente con el del dashboard. No agregues espacios ni saltos de línea.
// ❌ Incorrecto
GIGSTACK_WEBHOOK_SECRET= tu_secret_con_espacio

// ✅ Correcto
GIGSTACK_WEBHOOK_SECRET=tu_secret_sin_espacios

❌ Error 2: Timeout - gigstack reintenta el webhook

  • Solución: Responde 200 OK rápido (<5 segundos). Si tu lógica toma tiempo, usa una queue (Bull, BullMQ, AWS SQS):
app.post('/webhooks/gigstack', async (req, res) => {
  // Validar firma
  if (!validateWebhookSignature(req)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  // ✅ Encolar para procesamiento asíncrono
  await queue.add('process-webhook', req.body);
  
  // Responder inmediatamente
  res.status(200).json({ received: true });
});

❌ Error 3: Webhooks duplicados procesados múltiples veces

  • Solución: Implementa idempotencia. Guarda el event.id y verifica que no lo hayas procesado antes:
const processedEvents = new Set(); // En producción, usa Redis

async function handleWebhookEvent(event) {
  // Verificar idempotencia
  if (processedEvents.has(event.id)) {
    console.log('⚠️ Evento ya procesado:', event.id);
    return; // Skip
  }
  
  // Procesar evento
  await processEvent(event);
  
  // Marcar como procesado
  processedEvents.add(event.id);
}

❌ Error 4: ngrok URL cambia cada vez que reinicias

  • Solución: Usa una cuenta gratuita de ngrok para obtener un subdominio fijo:
ngrok http 3000 --subdomain=tu-subdominio-fijo

Best Practices

🔒 Seguridad:

  • Siempre valida la firma del webhook antes de procesar
  • Usa HTTPS en producción (nunca HTTP)
  • No expongas tu WEBHOOK_SECRET en logs o repos públicos
  • Implementa rate limiting por si alguien descubre tu endpoint

⚡ Performance:

  • Responde 200 OK en <5 segundos, procesa después de forma asíncrona
  • Usa una message queue (Bull, RabbitMQ, AWS SQS) para operaciones pesadas
  • Implementa retry logic con backoff exponencial para operaciones fallidas

🛡️ Resiliencia:

  • Implementa idempotencia (gigstack puede reintentar webhooks si no recibe 200)
  • Guarda webhooks en una tabla de auditoría para debugging
  • Logea todos los eventos para troubleshooting
  • Maneja edge cases (facturas canceladas después de pagadas, etc.)

📊 Monitoring:

  • Logea cada webhook recibido con timestamp
  • Configura alertas si el endpoint devuelve errores 5xx
  • Monitorea el tiempo de respuesta (debe ser <5s)
  • Trackea eventos no manejados para identificar nuevos tipos
// Ejemplo de logging estructurado
const winston = require('winston');

const logger = winston.createLogger({
  format: winston.format.json(),
  transports: [new winston.transports.Console()]
});

app.post('/webhooks/gigstack', async (req, res) => {
  const startTime = Date.now();
  
  try {
    await handleWebhookEvent(req.body);
    
    logger.info('webhook_processed', {
      event_type: req.body.type,
      event_id: req.body.id,
      duration_ms: Date.now() - startTime
    });
    
    res.status(200).json({ received: true });
  } catch (error) {
    logger.error('webhook_error', {
      event_type: req.body.type,
      error: error.message,
      stack: error.stack
    });
    res.status(500).json({ error: 'Internal error' });
  }
});

Próximos Pasos

Ahora que tienes webhooks funcionando, puedes:

  • Automatizar flujos completos: Emite factura → recibe pago → marca como pagada → envía producto
  • Integrar con otros sistemas: CRM, ERP, plataformas de ecommerce
  • Construir dashboards en tiempo real: Reacciona a eventos y actualiza analytics al instante
  • Implementar reconciliación automática: Cruza pagos con facturas sin intervención manual
  • Escalar a arquitectura event-driven: Usa webhooks como fuente de eventos para microservicios

Features avanzadas de gigstack API:

  • Facturación automatizada por venta
  • Conciliación bancaria con machine learning
  • Cobranza inteligente con recordatorios automáticos
  • Reportes fiscales mensuales generados automáticamente
  • Multi-tenant con gigstack Connect

Recursos


Prueba en Sandbox Gratis

gigstack ofrece un ambiente de sandbox completo donde puedes probar toda la API sin afectar facturas reales. Crea facturas de prueba, simula pagos, dispara webhooks y valida tu integración antes de ir a producción.

👉 Regístrate gratis en gigstack y empieza a construir tu integración hoy.

Como developer, no deberías perder tiempo aprendiendo leyes fiscales del SAT. gigstack es la infraestructura fiscal que necesitas para enfocarte en lo que sabes hacer: construir producto.

Blogs que te pueden gustar