Ir al contenido principal
Desarrollo & IA

n8n Webhooks: Tutorial para Automatizar APIs y Eventos [2026]

8 de febrero de 2026
33 min

Aprende n8n webhooks para automatizar APIs y eventos. Tutorial con ejemplos reales de Stripe, GitHub, Shopify y best practices en 2026.

Javier Santos

Especialista en IA & Machine Learning

📧¿Te gusta este contenido?

Únete a 547+ profesionales que reciben tips de IA cada semana. Sin spam, cancela cuando quieras.

n8n Webhooks: Tutorial Completo para Automatizar APIs y Eventos 2026

Los webhooks son uno de los patrones de integración más poderosos en el mundo de la automatización. En lugar de preguntar constantemente "¿Hay nuevos datos?", los webhooks permiten que los servidores externos te notifiquen cuando algo importante sucede. n8n hace que crear y gestionar webhooks sea increíblemente simple.

En este tutorial, aprenderás a crear webhooks en n8n, recibirlos desde Stripe, GitHub, Shopify y otros servicios, y construir workflows automáticos que reaccionen a eventos en tiempo real.

¿Qué Son Los Webhooks?

Un webhook es fundamentalmente una llamada HTTP POST que un servicio externo hace a tu aplicación cuando ocurre un evento.

Comparación: Polling vs Webhooks

Polling (El Viejo Método)

code
1Tu aplicación:
2"¿Hay nuevas órdenes cada minuto?"
3API Stripe:
4"No"
5"No"
6"No"
7"Sí, hay 1"
8 
9Problema: Desperdicia recursos, latencia alta

Webhooks (El Método Inteligente)

code
1Tu aplicación: Esperando...
2Stripe (cuando hay nueva orden):
3"¡PING! Nueva orden: #12345"
4 
5Tu aplicación: Procesa la orden al instante
6 
7Ventaja: Tiempo real, eficiente, bajo costo

Casos de Uso Reales

code
1✓ Procesar pagos de Stripe al instante
2✓ Crear tickets en Jira cuando alguien abre un issue en GitHub
3✓ Enviar notificaciones SMS cuando hay nuevas órdenes
4✓ Sincronizar datos entre aplicaciones en tiempo real
5✓ Ejecutar automáticamente cuando alguien se suscribe
6✓ Generar reportes cuando se actualiza datos en Airtable
7✓ Actualizar inventario cuando hay venta en Shopify

Conceptos Clave de Webhooks

El Flujo Completo

code
1Servicio Externo (Stripe)
2
3 [HTTP POST]
4 (JSON payload)
5
6n8n Webhook Node
7
8 Procesa datos
9
10 [Acciones]
11 (Send Email, etc)
12
13 Respuesta HTTP
14
15Servicio Externo
16(Confirma recepción)

Payload de Webhook Típico

json
1{
2 "id": "evt_1234567890",
3 "object": "event",
4 "api_version": "2023-10-16",
5 "created": 1675857600,
6 "data": {
7 "object": {
8 "id": "ch_1234567890",
9 "object": "charge",
10 "amount": 2000,
11 "currency": "usd",
12 "customer": "cus_1234567890",
13 "description": "Order #12345"
14 }
15 },
16 "livemode": false,
17 "pending_webhooks": 1,
18 "request": {
19 "id": null,
20 "idempotency_key": null
21 },
22 "type": "charge.succeeded"
23}

El Webhook Node en n8n

Crear un Webhook

code
11. Abre n8n
22. Crea nuevo workflow
33. Click "+ Add Node"
44. Busca "Webhook" y selecciona "Webhook"
55. Elige "Webhook" (el que recibe, no el que envía)

Configuración Básica

code
1Authentication: None (o API Key si necesitas seguridad)
2HTTP Method: POST (típicamente)
3Response Code: 200
4Webhook URL: auto-generado (ej: https://n8n.tudominio.com/webhook/12345)

Ejemplo Simplísimo

yaml
1Webhook Node:
2├── Authentication: None
3├── HTTP Method: POST
4└── Response Code: 200
5 
6
7Procesamiento:
8├── Acceso a datos: $json.body
9├── Logging: console.log()
10└── Transformación: JavaScript node
11 
12
13Acción:
14├── Enviar email
15├── Guardar en BD
16└── Llamar otra API

Paso a Paso: Tu Primer Webhook en n8n

Paso 1: Crear el Webhook Node

code
11. Nuevo workflow
22. Agregar "Webhook" node
33. HTTP Method: POST
44. Copiar la URL generada
5 
6URL Ejemplo:
7https://n8n.example.com/webhook/webhook-test-1234

Paso 2: Recibir el Payload

code
1El webhook recibe automáticamente:
2- Headers: headers HTTP enviados
3- Body: JSON payload
4- Query: parámetros de URL
5- Method: POST, GET, etc.
6 
7Acceso en n8n:
8- $json.body → accede al JSON
9- $json.headers → headers HTTP
10- $json.query → query parameters

Paso 3: Procesar los Datos

javascript
1// JavaScript Node en n8n
2 
3// Acceder payload
4const payload = $json.body;
5const orderId = payload.data.object.id;
6const amount = payload.data.object.amount;
7 
8// Transformar
9return {
10 orderId: orderId,
11 amountUSD: (amount / 100), // Stripe usa centavos
12 timestamp: new Date().toISOString()
13};

Paso 4: Ejecutar Acciones

code
1Ejemplos de acciones después del webhook:
2- Enviar email notificando la orden
3- Guardar en Airtable
4- Crear issue en GitHub
5- Actualizar CRM
6- Enviar mensaje en Slack

Paso 5: Activar y Testar

code
11. Click "Activate" en el workflow
22. Copiar Webhook URL
33. Enviar test POST a la URL
44. Ver ejecución en n8n
55. Revisar logs

Integraciones: Recibir Webhooks de Servicios Reales

Integración 1: Stripe

Procesar pagos automáticamente con Stripe.

Configurar Webhook en Stripe:

code
11. Stripe Dashboard → Developers → Webhooks
22. Click "+ Add endpoint"
33. Pegar URL de n8n webhook
44. Seleccionar eventos: charge.succeeded, charge.failed
55. Copiar "Signing Secret" (importante para seguridad)

Verificar Firma de Stripe (Seguridad)

javascript
1// Stripe firma todos los webhooks con HMAC
2// Necesario para verificar que viene de Stripe
3 
4const crypto = require('crypto');
5const stripe_secret = process.env.STRIPE_WEBHOOK_SECRET;
6 
7const sig = $json.headers['stripe-signature'];
8const body = $json.body;
9 
10const expectedSig = crypto
11 .createHmac('sha256', stripe_secret)
12 .update(body)
13 .digest('base64');
14 
15if (sig !== expectedSig) {
16 throw new Error('Firma de Stripe no válida');
17}
18 
19// Si llegó aquí, es seguro procesar
20return {
21 verified: true,
22 payload: JSON.parse(body)
23};

Workflow Completo: Procesar Pagos Stripe

code
1[Webhook Node]
2
3[Verificar Firma]
4
5[Extraer Información]
6 ├── orderId
7 ├── amount
8 ├── customer email
9 └── status
10
11[If charge.succeeded?]
12 ├─→ [Guardar en Airtable]
13 ├─→ [Enviar Email de Confirmación]
14 └─→ [Webhook Slack: Nueva venta!]
15
16[Else charge.failed]
17 ├─→ [Guardar fallo en BD]
18 └─→ [Email al cliente: Reintenta]

Integración 2: GitHub

Crear un ticket en Jira cuando alguien abre un issue en GitHub.

Setup GitHub Webhook:

code
1GitHub Repo → Settings → Webhooks
2URL: https://n8n.example.com/webhook/github-issues
3 
4Eventos a disparar:
5- Issues: Push, Pull Request, Issues

Payload de GitHub (Pull Request abierto)

json
1{
2 "action": "opened",
3 "pull_request": {
4 "id": 1,
5 "number": 1234,
6 "title": "Add new feature",
7 "body": "This PR adds XYZ functionality",
8 "user": {
9 "login": "octocat",
10 "avatar_url": "..."
11 },
12 "head": {
13 "ref": "feature-branch"
14 },
15 "base": {
16 "ref": "main"
17 }
18 }
19}

Workflow: GitHub → Jira

javascript
1// Recibir webhook de GitHub
2const github = $json.body;
3 
4// Solo procesar PRs nuevos
5if (github.action !== 'opened') {
6 return null;
7}
8 
9// Extraer información
10const prTitle = github.pull_request.title;
11const prBody = github.pull_request.body;
12const prAuthor = github.pull_request.user.login;
13const prUrl = github.pull_request.html_url;
14 
15// Crear issue en Jira
16return {
17 fields: {
18 project: { key: 'PROJ' },
19 summary: `[GitHub PR] ${prTitle}`,
20 description: `${prBody}\n\nAutor: ${prAuthor}\nURL: ${prUrl}`,
21 issuetype: { name: 'Task' }
22 }
23};

Integración 3: Shopify

Sincronizar nuevas órdenes de Shopify a Google Sheets.

Configurar Webhook en Shopify:

code
1Shopify Admin → Apps → Manage webhooks
2Topic: Orders/create (nueva orden)
3Delivery URL: https://n8n.example.com/webhook/shopify

Workflow: Shopify → Google Sheets

yaml
1[Webhook: Shopify Order]
2
3[Procesar Payload]
4 ├── order.id
5 ├── order.total_price
6 ├── customer.email
7 └── created_at
8
9[Google Sheets: Agregar fila]
10 ├── Columna A: Order ID
11 ├── Columna B: Email Cliente
12 ├── Columna C: Total
13 └── Columna D: Fecha
14
15[Enviar Slack Notification]
16 └── "Nueva orden: $XXX de nombre@email.com"

Testing de Webhooks

Método 1: curl (Línea de Comandos)

bash
1# Enviar POST simple
2curl -X POST https://n8n.example.com/webhook/webhook-id \
3 -H "Content-Type: application/json" \
4 -d '{
5 "order_id": "12345",
6 "amount": 99.99,
7 "email": "cliente@example.com"
8 }'
9 
10# Con headers personalizados
11curl -X POST https://n8n.example.com/webhook/webhook-id \
12 -H "Content-Type: application/json" \
13 -H "Authorization: Bearer token123" \
14 -d @payload.json

Método 2: Postman (UI)

code
11. Abre Postman
22. Method: POST
33. URL: Pegar webhook URL de n8n
44. Body → raw → JSON
55. Agregar JSON de prueba
66. Click Send
77. Ver respuesta en n8n

Método 3: n8n Testing (Integrado)

code
11. En el Webhook node, click en el ícono de prueba
22. n8n genera una URL de prueba
33. Enviar POST a esa URL
44. Ver datos en el node automáticamente

Autenticación y Seguridad

Autenticación con API Key

yaml
1Webhook Node:
2├── Authentication: API Key
3├── Header Name: X-API-Key
4└── Value: tu-clave-secreta-123
5 
6Entonces el cliente debe enviar:
7Headers:
8 X-API-Key: tu-clave-secreta-123

Verificación de Firma (HMAC)

javascript
1// Patrón usado por Stripe, GitHub, etc.
2 
3const crypto = require('crypto');
4const webhook_secret = process.env.WEBHOOK_SECRET;
5 
6const signature = $json.headers['x-signature'];
7const payload = $json.body;
8 
9// Calcular HMAC esperado
10const hmac = crypto
11 .createHmac('sha256', webhook_secret)
12 .update(JSON.stringify(payload))
13 .digest('hex');
14 
15// Comparar (timing-safe)
16const isValid = crypto.timingSafeEqual(
17 Buffer.from(signature),
18 Buffer.from(hmac)
19);
20 
21if (!isValid) {
22 throw new Error('Firma webhook inválida');
23}
24 
25return { verified: true };

IP Whitelisting

yaml
1# Restricción a IPs conocidas
2Webhook Node:
3├── Authentication: None
4├── Advanced Settings
5└── Allowed IPs:
6 - 1.2.3.4 # Servidor Stripe
7 - 5.6.7.8 # Servidor GitHub
8 - 9.10.11.12 # Servidor Shopify

Manejo de Errores y Reintentos

Responder al Servicio

javascript
1// El servicio necesita saber si el webhook se procesó
2 
3try {
4 // Procesar webhook
5 await procesarPago($json.body);
6 
7 // Responder con éxito
8 return {
9 statusCode: 200,
10 body: {
11 success: true,
12 message: 'Webhook procesado correctamente'
13 }
14 };
15 
16} catch (error) {
17 // Responder con error
18 return {
19 statusCode: 400,
20 body: {
21 success: false,
22 error: error.message
23 }
24 };
25}

Implementar Reintentos

yaml
1# Si el webhook falla, configurar reintentos
2 
3Webhook Node:
4├── Retry on Failure: true
5├── Max Retries: 3
6├── Retry Delay: 5 segundos
7└── Exponential Backoff: true
8 
9Timing:
101er intento: Inmediato
112do intento: 5 seg
123er intento: 25 seg
134to intento: 125 seg

Queue de Webhooks Fallidos

javascript
1// Guardar webhooks fallidos para procesar luego
2 
3const failedPayload = $json.body;
4const timestamp = new Date().toISOString();
5 
6// Guardar en tabla fallidos_webhooks
7await db.insert('webhooks_fallidos', {
8 id: generateUUID(),
9 payload: JSON.stringify(failedPayload),
10 timestamp: timestamp,
11 error: error.message,
12 servicio: 'stripe',
13 reintentado: false
14});
15 
16// Email al admin
17await enviarEmail({
18 to: 'admin@example.com',
19 subject: `Webhook fallido: ${failedPayload.type}`,
20 body: `Webhook ID: ${failedPayload.id}`
21});

Casos Prácticos Completos

Caso 1: E-commerce Automático

Flujo: Shopify → Múltiples Integraciones

code
1[Webhook Shopify: Nueva Orden]
2
3[Extraer datos]
4├── items
5├── cliente
6└── dirección
7
8[Paralelo]
9├→ [Fulfillment API: Enviar a almacén]
10├→ [Google Sheets: Registrar orden]
11├→ [Stripe: Procesar pago]
12└→ [Email: Confirmación al cliente]
13
14[Guardar en Base de Datos]
15 ├── orders tabla
16 ├── customers tabla
17 └── order_items tabla
18
19[Slack Notification]
20 └── "Orden #123 - $99.99"

Caso 2: Notificaciones en Tiempo Real

Flujo: Múltiples Fuentes → Usuarios

code
1[GitHub Webhook: Nuevo Issue]
2[Jira Webhook: Issue Asignada]
3[Slack Webhook: Menciono a equipo]
4
5[Deduplicación: Es el mismo issue?]
6
7[Normalizar datos]
8 ├── titulo
9 ├── descripción
10 └── prioridad
11
12[Slack: Notificar equipo]
13[Email: Notificar interesados]
14[SMS: Para crítico]

Caso 3: Sincronización de Datos

Flujo: CRM ↔ Sheets ↔ Mailchimp

code
1[Webhook: Nuevo contacto en CRM]
2
3[Agregar a Google Sheets]
4
5[Subscribir a Mailchimp]
6
7[Enviar email bienvenida]
8
9[Slack: Nuevo lead!]
10
11[Webhook: Informar CRM de inscripción]

Best Practices en Producción

1. Logging Exhaustivo

javascript
1// Registrar todo para debugging
2 
3const webhook_id = $json.headers['x-webhook-id'];
4const timestamp = new Date().toISOString();
5 
6console.log(`[${timestamp}] Webhook recibido: ${webhook_id}`);
7console.log(`Payload: ${JSON.stringify($json.body)}`);
8 
9// Guardar en base de datos también
10await db.insert('webhook_logs', {
11 webhook_id: webhook_id,
12 timestamp: timestamp,
13 payload: $json.body,
14 status: 'received'
15});

2. Idempotencia (Procesar Solo Una Vez)

javascript
1// Los webhooks pueden llegar duplicados a veces
2// Asegurar procesar solo una vez
3 
4const idempotency_key = $json.body.id;
5 
6// Verificar si ya procesamos
7const exists = await db.query(
8 'SELECT id FROM webhooks_procesados WHERE id = ?',
9 [idempotency_key]
10);
11 
12if (exists.length > 0) {
13 return { statusCode: 200, message: 'Ya procesado' };
14}
15 
16// Procesar
17await procesarPago($json.body);
18 
19// Guardar como procesado
20await db.insert('webhooks_procesados', { id: idempotency_key });
21 
22return { statusCode: 200 };

3. Monitoreo y Alertas

yaml
1# Monitorear salud de webhooks
2 
3Métricas a rastrear:
4- Total webhooks/hora
5- % de éxito vs fallo
6- Latencia promedio
7- Webhooks duplicados
8- Errores más comunes
9 
10Alertas:
11- Tasa de error > 5%
12- Latencia > 10 segundos
13- Sin webhooks en 1 hora

4. Versionado de Webhooks

yaml
1# Mantener compatibilidad hacia atrás
2 
3v1:
4 payload:
5 id: order_123
6 amount: 99.99
7 
8v2:
9 payload:
10 order:
11 id: order_123
12 total:
13 amount: 99.99
14 currency: USD
15 
16# En n8n:
17if (payload.order) {
18 // v2
19 const amount = payload.order.total.amount;
20} else {
21 // v1
22 const amount = payload.amount;
23}


FAQ: Preguntas Sobre Webhooks en n8n

¿Cuál es la diferencia entre Webhook (entrante) y HTTP Request (saliente)?

Webhook Node es para RECIBIR eventos POST de servicios externos. HTTP Request Node es para ENVIAR datos a servicios externos. En un flujo típico: Webhook recibe → procesa → HTTP Request envía a otra API.

¿Qué pasa si el webhook falla en n8n?

Si configuraste reintentos, n8n intentará procesar el webhook de nuevo automáticamente. Si sigue fallando, n8n responde con un código de error al servicio (ej: 500), y el servicio reintentará según su política. Es buena idea guardar los webhooks fallidos en una tabla para procesarlos manualmente luego.

¿Cuántos webhooks puedo recibir simultáneamente?

Depende de tu plan n8n. Cloud Plan: aproximadamente 100 ejecutiones simultáneas. Self-hosted: depende de tus recursos (CPU, RAM). En producción, configura una queue de webhooks si esperas alto volumen.

¿Cómo evito procesar un webhook dos veces?

Usa idempotency keys. Cada webhook debe tener un ID único. Antes de procesar, verifica si ya existe ese ID en tu base de datos. Si existe, retorna 200 OK sin procesar de nuevo. Esto es crítico para transacciones financieras.

¿Puedo usar webhooks para datos sensibles como contraseñas?

NUNCA envíes contraseñas, tokens de API o PII sensible en webhooks. Usa variables de entorno para credenciales. Si necesitas enviar datos sensibles, encripta el payload y verifica la firma HMAC del servicio origen para asegurar autenticidad.

📬

¿Te ha gustado? Hay más cada semana

Únete a "IA Sin Humo" — la newsletter donde comparto lo que realmente funciona en inteligencia artificial. Sin teoría innecesaria, sin postureo.

📚

1 Tutorial

Paso a paso, práctico

🛠️

3 Herramientas

Probadas y útiles

💡

0 Bullshit

Solo lo que importa

+547 suscriptores • Cada martes • Cancela cuando quieras