Ilustrativo: el HTTP Request del centro se comunica con cualquier servicio; la paginación procesa listas en lotes.
🌐 Solicitudes HTTP y API REST
O HTTP Request node es la navaja suiza: cuando no hay un node nativo, se comunica con cualquier API REST. Defines el método, la URL, los headers y el body, y recibes la respuesta como un item.
GET https://api.exemplo.com/v1/pedidos
?status=={{ $json.status }}&limit=50
// a resposta vira item; acesse com: ={{ $json.data }}
📊 Los verbos REST que importan
- GET - leer datos (no cambia nada en el servidor).
- POST - crear un nuevo registro.
- PUT/PATCH - actualizar un registro existente.
- DELETE - eliminar. Revisa siempre el código de estado: 2xx correcto, 4xx error tuyo, 5xx error de ellos.
🪪 Autenticación
El error 401 Unauthorized es el error nº1 en una integración. La API necesita comprobar quién eres: un token en el header (Bearer) o un flujo de consentimiento (OAuth2).
Authorization: Bearer ={{ $env.API_TOKEN }}
Content-Type: application/json
✓ Bearer token
- ✓Simple: 1 clave fija en el header.
- ✓Bueno para APIs de servidor (OpenAI, Stripe).
- ✓Guarda la clave en $env/credential.
✓ OAuth2
- ✓Para acceder a la cuenta de un usuario (Google, Slack).
- ✓n8n renueva el token automáticamente (refresh).
- ✓Configúralo una vez en la credential y reutilízalo.
⚠️ ¿Te dio 401? Revisa en este orden
¿La clave es correcta? Encabezado con el nombre exacto (Authorization)? Prefijo Bearer ¿con espacio? ¿Token expirado (OAuth)? ¿Alcance suficiente? El 90% de los 401 se deben a esto.
🗄️ Supabase / base de datos: leer y escribir
El banco es la memoria de la automatización. Sin él, cada ejecución lo olvida todo. Con Supabase/Postgres lees con SELECT y escribes con INSERT/UPDATE — o mejor, UPSERT, que guarda o actualiza por clave única.
POST https://abcd.supabase.co/rest/v1/leads
Headers:
apikey: ={{ $env.SUPABASE_SERVICE_KEY }}
Prefer: resolution=merge-duplicates
Body:
{ "email": "={{ $json.email }}", "intencao": "={{ $json.intencao }}" }
🔑 Clave única = tu ancla
Define una columna única (p. ej.: correo electrónico). El UPSERT la usa para decidir entre crear y actualizar; así se evitan los duplicados (tema del módulo 4.4).
- •SELECT con filtro ?email=eq.ana@x.com para leer.
- •Prefer: resolution=merge-duplicates hace el UPSERT en Supabase.
📊 Hojas de cálculo (Google Sheets)
Google Sheets es el «banco» favorito de quienes no son desarrolladores. El cliente entiende las hojas de cálculo. Entregar resultados en una pestaña es la forma más rápida de mostrar valor sin capacitar a nadie: lectura por fila, escritura mediante append o update.
Nome: ={{ $json.nome }}
Email: ={{ $json.email }}
Prioridade: ={{ $json.prioridade }}
Data: ={{ $now.format('dd/MM/yyyy') }}
Agrega una línea nueva
Por clave/columna
Hoja de cálculo como entrada
Pestaña y rango
💡 Consejo práctico
La hoja de cálculo es excelente para entrega visible, pero pésima como base de datos transaccional. Para deduplicar y manejar volumen, usa Supabase; para el cliente ver el resultado, refléjalo en una pestaña.
🔄 Paginación y procesamiento de listas
Las API limitan cuántos elementos devuelven por llamada e imponen rate limit. Procesarlo todo de una vez falla. SplitInBatches (Loop Over Items) divide la lista en lotes; el cursor/offset busca página por página.
GET https://api.exemplo.com/v1/itens?cursor=={{ $json.next_cursor }}
// repita o HTTP node em loop enquanto next_cursor não for null
// SplitInBatches: tamanho 50 + Wait 1s entre lotes p/ respeitar rate limit
⚠️ El error N+1 y el rate limit
Disparar una llamada por elemento, sin lote ni espera, lleva al 429 Too Many Requests y a un costo absurdo. Siempre agrupa en lotes y agrega un Wait entre ellos.
Divide la lista
SplitInBatches con tamaño de lote (ej.: 50) divide 500 elementos en 10 ciclos.
Procesa el lote y espera
Haz el trabajo del lote, agrega un nodo Wait y vuelve a SplitInBatches.
Detente cuando se acabe
El loop termina cuando ya no hay más lotes (o next_cursor es null).
🧮 Tratar valores nulos y mapear campos
Un campo nulo inesperado interrumpe el flujo a mitad de camino. Expresiones de n8n ={{ }} con valor predeterminado y optional chaining hacen que la automatización sea resistente a datos sucios.
// valor padrão quando vem nulo/undefined ={{ $json.email ?? 'sem-email@placeholder.com' }} // optional chaining evita "cannot read property of undefined" ={{ $json.cliente?.endereco?.cidade ?? 'N/D' }} // renomear/formatar ao mapear ={{ $json.valor ? 'R$ ' + $json.valor.toFixed(2) : 'R$ 0,00' }}
✓ Mapeo resiliente
- ✓Siempre ?? valor_padrao en un campo que puede faltar.
- ✓?. en objetos anidados de fuentes externas.
- ✓Dar formato a los tipos (fecha, número) en el mapeo.
✗ Mapeo frágil
- ✗Suponer que todos los elementos tienen todos los campos.
- ✗Acceder $json.a.b.c sin protección.
- ✗Grabar undefined en la base de datos/hoja de cálculo.
📌 Resumen del módulo
Próximo Módulo:
4.4 - Confiabilidad (errores, reintentos, idempotencia, observabilidad, lista de verificación de producción)