Los flujos de trabajo de n8n se interrumpen cuando las API de enriquecimiento devuelven JSON inconsistente: un cliente potencial tiene un campo de teléfono, el siguiente no, un tercero devuelve un valor nulo en lugar de una cadena vacía. Este tutorial crea un normalizador de enriquecimiento compatible con n8n que consulta la API de Scavio para conocer el contexto de la empresa y luego normaliza cada respuesta en un esquema garantizado sin campos faltantes.
Requisitos previos
- n8n instalado (autohospedado o en la nube)
- Una clave API de Scavio de scavio.dev
- Familiaridad básica con los nodos de solicitud HTTP n8n
Guia paso a paso
Paso 1: Configurar el nodo de solicitud HTTP para Scavio
Configure un nodo de solicitud HTTP n8n para llamar a la API de Scavio para la empresa de cada cliente potencial.
// n8n HTTP Request Node:
// Method: POST
// URL: https://api.scavio.dev/api/v1/search
// Headers: x-api-key: {{ $env.SCAVIO_API_KEY }}
// Body: { "query": "{{ $json.company_name }} company", "country_code": "us" }
// Python equivalent for testing:
import os, requests
API_KEY = os.environ['SCAVIO_API_KEY']
def enrich_company(name):
return requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
json={'query': f'{name} company', 'country_code': 'us'}).json()
print(f"Results: {len(enrich_company('Scavio').get('organic_results', []))}")Paso 2: Normalizar la respuesta en un esquema garantizado
Utilice un nodo de función n8n para transformar respuestas sin procesar en objetos con campos garantizados.
// n8n Function Node after HTTP Request
const raw = $input.first().json;
const results = raw.organic_results || [];
const top = results[0] || {};
const kg = raw.knowledge_graph || {};
return [{ json: {
company_name: $('Trigger').first().json.company_name || '',
lead_email: $('Trigger').first().json.email || '',
website: top.link || '',
description: top.snippet || '',
serp_title: top.title || '',
kg_description: kg.description || '',
kg_type: kg.type || '',
total_results: results.length,
enriched_at: new Date().toISOString(),
has_data: results.length > 0,
}}];Paso 3: Agregar enriquecimiento de contexto de Reddit
Encadene una segunda solicitud HTTP para buscar la empresa en Reddit, agregando contexto de sentimiento.
// Second HTTP Request: POST https://api.scavio.dev/api/v1/search
// Body: { "query": "{{ $json.company_name }} review", "platform": "reddit", "country_code": "us" }
// Reddit Normalizer Function Node:
const raw = $input.first().json;
const results = raw.organic_results || [];
const prev = $('Google Normalizer').first().json;
return [{ json: {
...prev,
reddit_mentions: results.length,
reddit_top_title: results[0]?.title || '',
reddit_top_snippet: results[0]?.snippet || '',
has_reddit_presence: results.length > 0,
}}];Paso 4: Rutas lideradas por calidad de enriquecimiento
Utilice nodos IF para enviar clientes potenciales enriquecidos a la divulgación y los débiles a la revisión manual.
// n8n IF Node:
// Condition: {{ $json.has_data }} equals true AND {{ $json.total_results }} >= 3
// True -> auto-route to CRM
// False -> manual review queue
// Python routing equivalent:
def route_lead(enriched):
if enriched['has_data'] and enriched['total_results'] >= 3:
return 'high_confidence' if enriched['has_reddit_presence'] else 'medium_confidence'
return 'manual_review'
for lead in [{'company_name': 'Stripe', 'has_data': True, 'total_results': 5, 'has_reddit_presence': True},
{'company_name': 'Unknown', 'has_data': False, 'total_results': 0, 'has_reddit_presence': False}]:
print(f"{lead['company_name']}: {route_lead(lead)}")Ejemplo en Python
import os, requests
API_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
def enrich(company):
g = requests.post('https://api.scavio.dev/api/v1/search',
headers=H, json={'query': f'{company} company', 'country_code': 'us'}).json()
r = requests.post('https://api.scavio.dev/api/v1/search',
headers=H, json={'query': f'{company} review', 'platform': 'reddit', 'country_code': 'us'}).json()
gr = g.get('organic_results', [])
rr = r.get('organic_results', [])
return {'company': company, 'website': gr[0]['link'] if gr else '', 'google': len(gr),
'reddit': len(rr), 'confidence': 'high' if len(gr) >= 3 and rr else 'low'}
for c in ['Stripe', 'Scavio', 'Unknown']:
e = enrich(c)
print(f"{e['company']}: {e['confidence']} ({e['google']}G, {e['reddit']}R)")Ejemplo en JavaScript
const API_KEY = process.env.SCAVIO_API_KEY;
const H = { 'x-api-key': API_KEY, 'Content-Type': 'application/json' };
async function enrich(company) {
const [g, r] = await Promise.all([
fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: H,
body: JSON.stringify({ query: `${company} company`, country_code: 'us' })
}).then(r => r.json()),
fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: H,
body: JSON.stringify({ query: `${company} review`, platform: 'reddit', country_code: 'us' })
}).then(r => r.json()),
]);
const gr = g.organic_results || [];
const rr = r.organic_results || [];
console.log(`${company}: ${gr.length}G, ${rr.length}R`);
}
(async () => { for (const c of ['Stripe', 'Scavio']) await enrich(c); })();Salida esperada
Stripe: high (5G, 3R)
Scavio: high (4G, 2R)
Unknown: low (0G, 0R)
Cost: $0.030