Módulo 7: Wait Nodes y Flujos Asíncronos
Resume Webhook: Continuar con Trigger Externo
Descripción de la cápsula
El modo más poderoso (y complejo) del Wait: Wait for Webhook. n8n pausa el workflow y genera una URL única. Cuando algo manda un POST a esa URL, el workflow reanuda desde ahí.
Es la base para integraciones asíncronas reales: aprobar acciones, esperar jobs externos, recibir confirmaciones, callbacks de servicios.
Lo que vas a aprender
- ✅ Configurar Wait for Webhook
- ✅ Cómo se genera y usa el resume URL
- ✅ Capturar datos del POST de resume
- ✅ Casos típicos: jobs externos, callbacks, aprobaciones
Configuración
Wait node:
- Mode: Wait for Webhook
- Options:
- HTTP Method: POST (típico)
- Response Mode: cómo responder al caller del resume
- Timeout (importante): si no llega webhook, fallar después de X
El resume URL
n8n genera al ejecutar el Wait:
https://your-instance/webhook-waiting/{execution-id}
Este URL:
- Es único por execution
- Solo válido hasta que llegue el resume o expire timeout
- POST a este URL reanuda ESA ejecución específica
Pattern 1: Job externo asíncrono
Caso: lanzar un job en sistema externo. El job toma 5-30 minutos. Cuando termina, te avisa.
[Trigger]
│
[HTTP POST: iniciar job en sistema X]
body: { ..., callback_url: $resumeUrl }
│
[Wait for Webhook: timeout 1 hora]
│
[procesar resultado del job]
Donde $resumeUrl es la URL que generó el Wait. Cuando el sistema X termina, hace POST a esa URL con el resultado del job. Workflow reanuda.
Cómo obtener el resume URL
En el Wait node, hay una expression para acceder al resume URL: {{ $resumeWebhookUrl }} o similar (depende de versión).
Lo pasas al servicio externo en el body del request inicial.
Pattern 2: Aprobación humana
Caso: workflow procesa solicitud. Antes de actuar, requiere aprobación de admin.
[Trigger: nueva solicitud]
│
[Send Email a admin]
con 2 links:
- Aprobar: $resumeUrl?action=approve
- Rechazar: $resumeUrl?action=reject
│
[Wait for Webhook: timeout 48 horas]
│
[Set: leer action del query]
│
[Switch: action]
├─→ "approve" → continuar con procesamiento
├─→ "reject" → notificar al solicitante
└─→ timeout (rama default) → escalar
Admin recibe email con botones. Click reanuda el workflow con el query parameter action.
Pattern 3: Webhook callback de servicio
Caso: Stripe te avisa cuando un pago se completa (después de un proceso async).
[Trigger: order recibida]
│
[HTTP POST a Stripe: crear payment intent]
Include: webhook_url = $resumeUrl
│
[Wait for Webhook]
│
[Procesar respuesta de Stripe]
(Stripe normalmente usa webhooks separados, no este pattern — es ejemplo conceptual.)
Acceder al payload del resume
Cuando llega el POST al resume URL, el body queda disponible en el output del Wait node:
{{ $json.body.action }}
{{ $json.body.result }}
(Igual que cualquier Webhook trigger.)
Manejo de timeout
Configurar timeout en el Wait node:
- Options → Timeout: "1 hour" (o lo que sea)
Si no llega webhook en ese tiempo, el Wait falla. Puedes manejar con:
[Wait for Webhook con Continue on Fail]
│
[IF: error/timeout?]
├─ TRUE → fallback (notify, retry, etc.)
└─ FALSE → continuar con datos del webhook
Security del resume URL
El resume URL es un poco predecible (basado en execution ID). Si alguien la adivina, puede reanudar tu workflow.
Mitigations
Auth en el Wait
Configurar Header Auth en el Wait — solo POSTs con el header correcto reanudan.
Verificar payload
Después del resume, validar contenido:
[IF: $json.body.secret_token === "expected_value"]
├─ TRUE → continuar
└─ FALSE → log intento sospechoso + cancelar
Expires automáticamente
Si configuras timeout corto, el URL expira pronto. Limita ventana de abuso.
Limitaciones
Workflow vive mucho tiempo
Wait for Webhook puede durar horas o días. Workflow está en "Waiting" todo ese tiempo.
URL solo válida una vez
Después del primer POST que reanuda, el URL no es reutilizable. Si quieres respuesta múltiple, necesitas Wait + loop.
Difícil de testear
Para testear Wait for Webhook localmente, necesitas:
- Workflow corriendo
- Llegar al Wait (con datos pineados)
- Hacer POST al resume URL (que solo existe mientras Wait está activo)
Más complejo que workflows síncronos.
Trampas comunes
Trampa 1: Wait for Webhook sin timeout
Qué pasa: Webhook nunca llega. Workflow espera indefinidamente.
Cómo evitar: Siempre timeout.
Trampa 2: Resume URL filtrada en logs
Qué pasa: Loggeas $resumeUrl en algún lado público. Alguien malicioso reanuda el workflow.
Cómo evitar: No loggear resume URLs. Tratar como secret.
Trampa 3: Resume URL no llega al destinatario
Qué pasa: Workflow manda email con resume URL. El email va a spam. Admin nunca lo ve. Workflow espera hasta timeout.
Cómo evitar: Múltiples canales (email + Slack). Timeout razonable + fallback.
Trampa 4: Asumir que el resume URL es el mismo entre executions
Qué pasa: Tu workflow corre 10 veces. Cada vez genera URL distinta. Si "guardas" la URL en algún lado fijo (Sheet), las viejas no funcionan.
Cómo evitar: El resume URL es único por execution. No reutilizable.
Resumen
- Wait for Webhook: pausa hasta que llegue POST a URL única
- 3 patterns: job externo, aprobación humana, callback
- Pass the URL:
$resumeWebhookUrlal servicio externo - Manejar timeout siempre
- Security: auth header, validar payload
- 4 trampas: sin timeout, URL filtrada, URL no llega, no reutilizable
Lo que sigue: Human-in-the-loop — aprobación humana con Slack/email actionable.
Creado: Mayo 11, 2026 Versión: 1.0