Built an n8n Lead Capture Workflow with Apollo, AI Scoring & Failure Handling

:waving_hand:
I built a lead capture and qualification workflow in n8n using Apollo, OpenAI, Airtable, Slack, and Gmail.

I wanted to share how I structured the workflow, especially the fallback logic and error handling.

How the workflow works

  1. Webhook – Captures a new lead submitted through a web form.

  2. Apollo API – Enriches the lead with company information, including industry, company size, revenue, website, and LinkedIn.

  3. AI Scoring – An OpenAI agent analyzes the lead’s message and company data, assigns a score from 0–80, classifies it as Hot / Warm / Cold, and provides a short explanation.

  4. Airtable – Creates or updates the lead record, checking for duplicates by email.

  5. Slack + Gmail – Sends notifications to the team.

The interesting part: what happens when enrichment fails?

During testing, I noticed an issue with AI scoring when enrichment data was missing.

The same lead could receive very different scores - from 25 to 77 - without enough company context.

Instead of letting AI guess, I decided to handle this differently.

If Apollo enrichment fails:

  • The workflow skips AI scoring.

  • The lead is marked as Not Scored.

  • The lead is still saved in Airtable.

  • A separate Slack notification alerts the team about the enrichment failure.

For the AI scoring branch, I also used a Structured Output Parser to keep the response in a consistent format before saving it to Airtable.

Testing

I tested the successful flow and failure scenarios, including intentionally using invalid API credentials to check whether the fallback path worked as expected.

One thing I learned from this project is that a missing AI score is better than an unreliable score that looks accurate.

The goal was to make sure an enrichment failure doesn’t prevent the lead from being saved or result in misleading scoring data.

Tech stack: n8n · Apollo API · OpenAI · Airtable · Slack · Gmail

I’ve attached a screenshot of the workflow.

I’d love to hear your thoughts

How do you handle lead scoring when enrichment data is missing?

Great approach. I agree that an unreliable AI score is worse than marking a lead as “Not Scored” when critical enrichment data is missing.

I’d also keep the scoring status separate from the lead-processing status. For example, a lead can be successfully saved while enrichment or scoring remains pending.

I’d consider adding:

  • A clear reason for the missing score, such as enrichment_failed.

  • A controlled retry for temporary API failures, with rate limits respected.

  • Idempotency checks so retries don’t create duplicate lead records or trigger duplicate notifications.

  • A human review path for leads that remain unscored after retries.

I’ve been testing similar reliability principles in my n8n + FastAPI + PostgreSQL demo, including idempotency, duplicate prevention, and database-failure recovery.

Portfolio: GitHub - katreshital11-commits/ai-n8n-automation: "Production-ready and test-proven n8n AI workflows, automated CRM pipelines, and custom AI Agent architectures." · GitHub

Keeping the lead safe while making uncertainty visible is an important design principle.

إعجاب واحد (1)

Thanks for the thoughtful feedback!

I like your suggestion about keeping the lead-processing status separate from the scoring status.

In my current workflow, the lead is still saved in Airtable when Apollo enrichment fails, and the score is marked as “Not Scored”.

I’m also using the lead’s email to check for existing records and avoid duplicates.

Adding a clear failure reason, controlled retries, and a review process would be useful improvements for a production version.

Thanks for sharing your experience!

One thing I’d add is proper traceability for the scores that actually get generated. I’d store the scoring rubric version, the model and prompt version, and the enrichment data timestamp right alongside each score.
That way, when a lead’s score changes later, you can tell whether it came from new company data or a change in the scoring logic itself. It also makes reviewing borderline leads a lot easier — you don’t have to reconstruct what the AI saw at the time

Really intriguing workflow @Yana1! Does it work swapping in Lusha as the data enrichment layer? I’d love to test the implementation if so.

إعجاب واحد (1)

@JOtt I think it should be possible to use Lusha instead of Apollo. n8n already has a Lusha integration, so the main change would be adjusting the field mapping for AI scoring.

I haven’t tested it with Lusha yet, but if you’d like to try it, I can share my workflow JSON.

إعجابَين (2)

Quick update ! I tested the workflow using mock Lusha API responses because I don’t have a Lusha account. The AI scoring and fallback logic worked as expected. I also added the Lusha node, but I couldn’t test it with the real API.

So, I’ve prepared the workflow JSON and can share it if you’d like to test it with your Lusha account.

إعجاب واحد (1)

@Yana1 actually you can use my custom node message template to test without calling API for demo data or someone can just share it with you https://www.npmjs.com/package/n8n-nodes-message-template

إعجابَين (2)

@SilentJMA Thanks for sharing! I actually used a Code node to simulate Lusha API responses and tested a few cases without calling the real API.

Your node looks like a useful alternative for creating mock data without writing JavaScript. I’ll keep it in mind for future projects! :blush:

إعجاب واحد (1)

The 25-to-77 spread on the same lead is the most useful finding in this thread. One option worth trying: don’t let the model produce the total. Ask it only for the features (is the need clear, budget band, urgency, company size band, fit with your services) as strict JSON, then add up the points in a Code node with fixed weights. Models tend to be more consistent at “is a budget stated, and roughly what band” than at picking a number from 0 to 80, and when a score changes you can see which feature moved it.

It also gives you a middle option instead of “Not Scored” when Apollo fails: score what the form already gives you (message, budget field, work email vs free mail, service mentioned), tag it something like scored_by: rules, enrichment: missing, and have a small scheduled workflow re-enrich and re-score those rows later. Sales still gets a rough priority on day one.

If it helps to compare, I put a free workflow on GitHub with that kind of rules fallback (form-only signals, a scored_by column, upsert by email). It’s called n8n-ai-lead-scoring.
Disclosure: I built it, and I also sell a larger paid version, but the free repo works on its own.