Módulo 1: Triggers Avanzados

Webhook Trigger Avanzado

Descripción de la cápsula

En G1-M04-05 configuraste un Webhook básico: POST a una URL, datos llegan. Funciona para casos simples. Pero webhooks en producción requieren más: autenticación para que cualquiera no pueda spamearlos, validación de signatures cuando vienen de servicios sensibles como Stripe, response modes para devolver datos calculados al caller, manejo de errores HTTP correctos, y patrones de seguridad básica.

En esta cápsula vas a aprender los 4 response modes del Webhook, 3 esquemas de autenticación soportados (Basic, Header, JWT), cómo validar HMAC signatures de servicios como Stripe, y los principios de seguridad que aplican a cualquier webhook public-facing.


Lo que vas a aprender

Al terminar esta cápsula serás capaz de:

  • Configurar los 4 response modes del Webhook
  • Autenticar webhooks con Basic Auth, Header Auth, o JWT
  • Validar HMAC signatures de servicios externos
  • Devolver respuestas calculadas con Respond to Webhook node
  • Aplicar principios de seguridad básica
  • Distinguir Test URL vs Production URL y cuándo cada una

Los 4 response modes

El Webhook Trigger tiene un campo Response Mode que define qué responde al servicio que llamó.

Modo 1: Immediately (default)

Comportamiento: responde 200 OK apenas recibe el request, antes de que el workflow termine.

Cuándo usar:

  • Casi siempre — es el default por una razón
  • Cuando el servicio que llama no espera respuesta detallada
  • Workflows que tardan más que el timeout del caller (la mayoría)

Cuándo NO usar:

  • Si el servicio que llama espera respuesta específica (ver modo 3)

Modo 2: When Last Node Finishes

Comportamiento: espera a que todos los nodos del workflow terminen, después responde.

Cuándo usar:

  • Workflows muy cortos donde el caller espera resultado
  • Cuando necesitas confirmar al caller que todo procesó OK

Cuándo NO usar:

  • Workflows largos (más de 10-30 segundos) — el caller probablemente da timeout

Modo 3: Using 'Respond to Webhook' Node

Comportamiento: tú decides exactamente cuándo y con qué responder, usando un nodo Respond to Webhook en algún punto del flow.

Cuándo usar:

  • Necesitas devolver datos calculados al caller (ej. ID del nuevo registro, status detallado)
  • Quieres validar y responder con error 400 si datos son malos
  • Tienes lógica condicional: responder distinto según condiciones

Cómo funciona:

[Webhook] → [Set: validar] → [IF]
                              ├─ TRUE → [Respond to Webhook: 200 OK + datos]
                              └─ FALSE → [Respond to Webhook: 400 Bad Request]

El nodo Respond to Webhook:

  • Status Code: 200, 201, 400, etc.
  • Response Headers: opcional
  • Response Body: JSON con datos

Modo 4: Stream (avanzado)

Para casos especiales como streaming de respuestas (LLMs). No se cubre acá.


Autenticación: 3 opciones

Sin auth, cualquiera con la URL puede mandar requests a tu webhook. Riesgos: spam, costos por procesar requests basura, datos falsos en tus sistemas.

Opción 1: Basic Auth (HTTP Auth)

Cómo funciona: el caller debe incluir header Authorization: Basic <base64(user:pass)>.

Configuración en n8n:

  1. En el Webhook Trigger → Options → Authentication: Basic Auth
  2. Username: elige uno (ej. acme-webhooks)
  3. Password: elige una random fuerte

Cómo lo usa el caller:

curl -u acme-webhooks:passwordfuerte -X POST https://...

O en HTTP request: Authorization: Basic YWNtZS13ZWJob29rczpwYXNzd29yZGZ1ZXJ0ZQ==

Pros: universalmente soportado. Contras: credenciales en cada request — si la URL se loggea, las credenciales también.

Opción 2: Header Auth (custom header)

Cómo funciona: el caller incluye un header específico con un secret.

Configuración:

  1. Authentication: Header Auth
  2. Header Name: ej. X-Webhook-Secret
  3. Header Value: un secret largo random

Cómo lo usa el caller:

curl -H "X-Webhook-Secret: your-secret-here" -X POST https://...

Pros: simple, separa el secret de la URL. Contras: mismo issue que Basic — el secret va en cada request.

Opción 3: JWT Auth

Cómo funciona: el caller incluye un token JWT firmado en el header Authorization: Bearer <jwt>. n8n verifica la firma con una key compartida.

Configuración:

  1. Authentication: JWT Auth
  2. Secret: la key compartida
  3. Algorithm: HS256 (común) u otro

Cuándo usar: integraciones más sofisticadas, especialmente entre tu app y n8n internamente.


Validación HMAC (para servicios como Stripe)

Servicios profesionales como Stripe, GitHub, Slack firman cada webhook con HMAC. El header incluye una signature que tú validas con un secret compartido.

Cómo funciona (concepto)

  1. Stripe te da un webhook signing secret (whsec_abc123...)
  2. Cada webhook que te manda, incluye header Stripe-Signature: t=...,v1=...
  3. Para validar:
    • Tomas el body raw del request
    • Lo concatenas con el timestamp del header
    • Calculas HMAC SHA-256 con tu signing secret
    • Comparas con el v1=... del header
  4. Si matchea → request legítimo. Si no → es spoofing, rechazar.

En n8n

n8n no tiene HMAC validation nativa en el Webhook Trigger para todos los servicios. Soluciones:

Opción A: Usar el trigger nativo del servicio

Stripe tiene Stripe Trigger en n8n que ya valida HMAC internamente. Si existe trigger nativo, siempre usarlo sobre Webhook genérico.

Opción B: Validar manualmente con Code node

Después del Webhook Trigger, agregar un Code node que recibe el body raw + headers, calcula HMAC, y verifica. Si falla → throw error y workflow termina.

// Pseudocódigo — Code node
const crypto = require('crypto');
const secret = 'whsec_tu_secret';
const payload = $input.first().json.body;
const signature = $input.first().json.headers['stripe-signature'];

const expected = crypto
  .createHmac('sha256', secret)
  .update(JSON.stringify(payload))
  .digest('hex');

if (expected !== extractFromSignature(signature)) {
  throw new Error('Invalid webhook signature');
}

return $input.all();

(El código exacto depende del servicio.)

Opción C: Webhook auth + IP whitelist

Si el servicio tiene IPs fijas (Stripe publica sus IPs), puedes:

  • Webhook Auth con header secret (las dos partes)
  • Verificar IP del caller con Code node (rechazo si no es Stripe)

Patrones de respuesta avanzada

Patrón 1: Responder con ID del registro creado

[Webhook] → [Validar] → [Crear registro en DB] → [Respond to Webhook]
                                                   Body: { "id": "{{ $json.id }}" }
                                                   Status: 201

Útil cuando el caller necesita el ID para hacer follow-up.

Patrón 2: Responder con 400 si validación falla

[Webhook] → [Validar] → [IF: válido?]
                         ├─ TRUE → [procesar] → [Respond: 200 OK]
                         └─ FALSE → [Respond: 400 + razón]

Es buena práctica: en lugar de procesar datos malos silenciosamente, devolver error explícito al caller.

Patrón 3: Responder con redirect (302)

[Webhook] → [Respond to Webhook]
            Status: 302
            Headers: { Location: "https://thank-you.your-site.com" }

Útil para formularios que esperan redirect después del submit.


Test URL vs Production URL (importante)

Lo cubrimos brevemente en G1, pero acá vale insistir:

Test URLProduction URL
Path/webhook-test/abc123/webhook/abc123
Activa cuandoClick "Listen for test event" en editorWorkflow activo (toggle ON)
Para quéIterar mientras desarrollasProducción real
LatenciaInmediata cuando estás escuchandoInmediata siempre
Auth requeridaSí, si configurasteSí, si configuraste

Error #1 al pasar a producción: el caller (formulario, servicio) sigue apuntando a Test URL. Resultado: a veces funciona (cuando alguien está escuchando), a veces no. Confunde.

Solución: después de development, cambiar a Production URL en el servicio externo.


Headers útiles para verificar en el workflow

A veces necesitas inspeccionar headers del request en tu workflow:

$json.headers['user-agent']        // qué app llamó
$json.headers['content-type']      // formato del body
$json.headers['x-forwarded-for']   // IP del caller (en proxies)
$json.headers['authorization']     // si vino con auth

Útil para:

  • Loggear qué servicio llamó (debugging)
  • Bifurcar workflow según user agent
  • Auditoría de seguridad

Trampas comunes

Trampa 1: Activar sin auth en producción

Qué pasa: activas el workflow para producción sin configurar auth. Pasa tiempo, bots descubren la URL, empiezan a mandar requests basura. Saturas tu plan o ensucias datos.

Cómo evitar: antes de activar para producción, siempre verificar: ¿tiene auth (header secret o similar)? Si no, agregar.


Trampa 2: Logging de headers con secrets

Qué pasa: tu workflow loggea $json.headers completo en un Sheet. Los logs incluyen Authorization headers con credenciales.

Cómo evitar:

  • No loggear headers completos
  • Si necesitas loggear algo, redactar los headers sensibles primero:
    {{ JSON.stringify({...$json.headers, authorization: 'REDACTED'}) }}

Trampa 3: Respond timing wrong

Qué pasa: Tu Respond to Webhook node está al final de un workflow de 30 segundos. El caller hace timeout en 10 segundos. Nunca recibe la respuesta.

Cómo evitar:

  • Si el caller espera respuesta rápida, usar Respond to Webhook temprano en el flow (después de validar)
  • Resto del procesamiento sigue después del Respond
  • O cambiar response mode a Immediately

Trampa 4: HMAC validation manual con errores sutiles

Qué pasa: Implementaste validación HMAC custom. Funciona en testing pero falla con requests reales por una diferencia sutil (encoding, whitespace, etc.).

Cómo evitar:

  • Preferir trigger nativo si existe (Stripe, GitHub, etc.)
  • Si haces validación custom, probar con el sandbox del servicio antes de producción

Trampa 5: URL del webhook hardcoded en código de servicio

Qué pasa: En tu form de Tally configuras la Production URL. Después regeneras el path del webhook en n8n. El form sigue apuntando al viejo. Ningún request entra.

Cómo evitar:

  • No regenerar paths una vez en producción a menos que sea inevitable
  • Si lo regeneras, actualizar TODOS los servicios externos que lo usan
  • Documentar dónde está usado cada webhook

Ejercicio: agregar auth a un webhook

Objetivo: practicar Header Auth en el workflow de G1-M08.

Tu tarea

  1. Abre tu workflow [PROY-M08] de G1
  2. En el Webhook Trigger: agregar Authentication: Header Auth
  3. Header Name: X-Webhook-Secret
  4. Header Value: una string random de 32+ chars (puedes usar random.org/strings)
  5. Save y activate

Verificar

Manda 2 requests:

Request 1: sin header (debería rechazar)

curl -X POST 'https://...' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Test","email":"t@t.com","marketing_consent":true}'

Esperado: respuesta 401 Unauthorized o similar.

Request 2: con header (debería procesar)

curl -X POST 'https://...' \
  -H 'Content-Type: application/json' \
  -H 'X-Webhook-Secret: your-secret-here' \
  -d '{"name":"Test","email":"t@t.com","marketing_consent":true}'

Esperado: respuesta 200 OK y workflow procesa.

Lo que aprendiste

  • Auth es 2 minutos de setup que previene 100% del spam
  • El "costo" de auth es cero para callers legítimos (1 header más)

Resumen y siguiente paso

  • 4 Response Modes: Immediately (default), When Last Node, Using Respond Node, Stream
  • 3 esquemas de auth: Basic, Header, JWT — preferir Header Auth para mayoría de casos
  • HMAC validation para servicios pro (Stripe, GitHub) — siempre usar trigger nativo si existe
  • Respond to Webhook node te deja devolver datos calculados, status codes específicos, headers
  • Test vs Production URL: verificar siempre cuál usa el caller
  • 5 trampas: sin auth, log headers con secrets, respond timing, HMAC custom errors, URL hardcoded sin update

Antes de avanzar deberías poder:

  • Configurar Header Auth en cualquier Webhook Trigger
  • Decidir entre los 4 response modes según caso
  • Validar HMAC con trigger nativo (cuando aplica)
  • Distinguir Test URL de Production URL en producción

Lo que sigue (cápsula 05):

Pasamos a la categoría 4 de la taxonomía: app-event triggers. Vas a ver cómo se configuran los triggers nativos de Gmail, Slack, Calendar, Notion. Son más simples que Webhook genérico porque n8n hace el setup interno por ti — pero hay decisiones de configuración que importan.


Recursos adicionales

  1. Webhook Trigger Documentation - Referencia oficial.
  2. Respond to Webhook Node - Para responder con datos.
  3. Stripe Webhook Signature Verification - Ejemplo de HMAC en servicio real.
  4. Webhooks.fyi: Security - Guía general de seguridad de webhooks.

Creado: Mayo 11, 2026 Versión: 1.0