The Lead Pipeline Gap That Makes No Noise
When we rebuilt the /ai page and launched the Impeccable Skill Clone offer, we built a new API endpoint for it: /api/skill-clone. The form collects a name, email, and what the person is building. The endpoint fires two Resend emails: one to the visitor with their clone instructions, one to us as a notification.
Both emails worked fine from day one.
What didn't work: nothing was reaching Airtable. Nothing was hitting Slack. The leads were coming in, getting their emails, and then disappearing from our pipeline entirely.
No errors. No alerts. Just silence.
Why It Happened
We already had a working lead pipeline. The original /api/lead-capture endpoint posts to a LEAD_CAPTURE_WEBHOOK_URL, which triggers an n8n workflow that logs to Airtable and pings Slack. That workflow was built once, it runs reliably, and it handles every lead from every source.
When we wrote /api/skill-clone, we copied the email logic but not the webhook forward. The new endpoint had its own job to do (send Resend emails for a different lead magnet) and we wired that part completely. The pipeline wiring just didn't make the trip.
The problem is that a lead form has two jobs, and they're easy to conflate:
- Transactional comms: send the visitor what they asked for, notify the team.
- Pipeline logging: get the lead into Airtable, trigger Slack, start any automations.
Job one fails loudly. A failed email returns an error, the API returns 502, the form shows an error state, someone notices. Job two fails silently. The webhook call isn't blocking anything. If it's missing entirely, you don't find out until you look at Airtable and wonder where the submissions went.
The Fix
After both Resend calls fire, we forward to the existing pipeline webhook. The key detail: we don't await it.
const forwardLead = forwardToLeadCapture({ name, email, context });
const [userResult, notifyResult] = await Promise.all([sendUser, sendNotify]);
// Don't await — pipeline is best-effort, never blocks the response.
forwardLead.catch((err) => {
console.error("[skill-clone] Lead capture webhook failed:", err);
});
The emails are awaited because they're critical. If Resend fails, we return 502 and the visitor knows something went wrong. The webhook forward is fire-and-forget because a flaky n8n instance should never block a visitor from getting their instructions.
The payload matches the shape the n8n workflow already expects, with one addition: lead_magnet: "impeccable-skill-v1". That version tag lets n8n branch on lead source. The Impeccable leads skip the generic welcome email sequence because they already got a more specific one from Resend. Everything else, Airtable and Slack, runs the same as any other lead.
The Lesson
Every new form endpoint needs to wire both jobs. Transactional comms and pipeline logging are separate concerns and they fail differently. Transactional failures surface immediately. Pipeline failures are invisible until you go looking.
If your site has multiple lead forms, an API route that sends email but doesn't call your webhook isn't partially wired. It's missing half its job.
The fix is also simple: one function, one .catch(), one environment variable already set. The infrastructure was there. We just had to connect the new endpoint to it.