Lead Routing Function w/ Webhook
A real-time lead validation and routing engine — fired by a webhook, it turns a raw demo-form submission into a clean, routed handoff to the right AE in seconds.
⇄Pull vs. push
A routing engine only works if it hears about a lead the instant it arrives. That's the whole difference between an API and a webhook.
An HTTP API pulls — your system asks a database for data, usually on a schedule, for heavier lookups. A webhook pushes — you register a URL, and the moment an event fires, the data is sent to you. For real-time lead capture, push wins: the submission should hit the engine in seconds, not on the next poll.
What it does, and what it needs
The function is a real-time validation and routing engine. It takes the raw identity signature from a demo-form submission, validates and enriches it, cross-references internal routing data, and outputs a clean routing map for downstream execution.
It runs off just two inputs — everything else is derived, so the function stays clean across any dataset:
Every output earns its place
Each mapped output exists to make the handoff to the AE clean and immediate — nothing is enriched for its own sake.
Firing the trigger by hand
The build isn't wired to a live form yet — so I simulate the event. I push a JSON payload from my terminal straight to the Clay webhook URL: the exact shape a form provider would fire the millisecond a prospect clicks Submit. The webhook bypasses Clay's native integration boundaries and drops the raw submission directly into the validation and routing engine within seconds.
$ curl -X POST https://api.clay.com/…/webhook \
-H "Content-Type: application/json" \
-d '{ "company_domain": "acme.com", "full_name": "Dana Reyes" }'
→ 200 · lead ingested · validation + routing engine fired
←Output-backwards
Shipping this exposed the real lesson. I'd built it input-first — wiring enrichment steps one at a time — and because I never mapped the final output payload up front, I missed a required field. In a chained function, one missing upstream point triggers a domino effect that stalls the whole execution line.
If I rebuilt it today, I'd start from the downstream schema — exactly what the CRM and routing maps require — and map every chained field back to the two inputs before writing a single webhook trigger. Data flows forward; the build has to be designed backward.
Craftsman → engineer
Once the webhook was live and I was pushing real payloads, a table stopped feeling like a playground. Any structural mistake in the input breaks the entire downstream chain — so the discipline is strict data contracts, defined before the first call, not fixed on the fly.
That's the line this build helped me cross: from a craftsman making beautiful one-off tables to an engineer building infrastructure that can be securely handed off, automated, and trusted to run on its own.