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: $resumeWebhookUrl al 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