What this workflow does
- New inquiry receives the form submission as JSON on a webhook.
- Normalize lead maps common field names (email, company, state, employees, message), lowercases the email and rejects submissions without a valid address.
- Find existing contact searches HubSpot by exact email, and by company domain for non-free email providers.
- Classify inquiry sends the message to Claude, which returns intent, product line, urgency, a one-line summary and a reason. It uses structured outputs with low effort.
- Read routing table loads your rules from Google Sheets.
- Apply routing rules is plain JavaScript. Spam is logged only. Support requests, partnerships, vendor pitches and job seekers go to the right queue. Existing contacts and accounts stay with their owner. Everything else gets the matching rule with the lowest priority number, then weighted round-robin with daily caps. Gaps fall back to a default owner and alert sales ops.
- Log routing decision appends a row to the
Routing logtab. - Route sends sales leads to Assign owner in HubSpot (create or update the contact with its owner), and both sales and non-sales items to Notify rep or queue in Slack.
- Every 30 min SLA check runs on weekdays from 8am to 6:30pm, finds leads assigned one to four hours ago with no logged contact, and Format SLA misses sends each one to the alert channel.
- Errors, refusals and table problems go to Alert: routing needs attention.
Before you import
- A current n8n version with a public URL for the production webhook.
- A HubSpot private app token with contact read and write scopes.
- A Google Sheet for the routing table and log.
- An Anthropic API key and a Slack app that can post to your channels.
Setup
- Import the JSON, then build the
RoutingandRouting logtabs from the layout in the yellow note. - Attach credentials: Google Sheets OAuth2 on both sheet nodes, HubSpot Service Key on the two HubSpot search nodes and the HubSpot node, Anthropic on Classify inquiry, Slack on both Slack nodes.
- Replace
REPLACE_WITH_ROUTING_SHEET_ID(two nodes) with your sheet ID. - In Apply routing rules, replace
REPLACE_WITH_DEFAULT_OWNER_IDwith a HubSpot owner ID. - Replace
REPLACE_WITH_SALES_CHANNEL,REPLACE_WITH_OPS_CHANNELandREPLACE_WITH_ALERTS_CHANNEL. - Edit the
product_linevalues in the Claude schema to match your catalog, and use the same values in the sheet. - If your form sends nested data (Typeform does), adjust the field mapping in Normalize lead.
Test it
Activate the workflow, then POST a sample lead to the production URL with curl, for example an email, company, state PA, employees of 120 and a message asking for pricing. Check that the contact appears in HubSpot with the expected owner, the rep is tagged in Slack and a row lands in the log. Repeat with a job application message and confirm it goes to the ops channel with no owner. Round-robin counters only persist in active executions, so test rotation with the workflow switched on.
Make it production-ready
- Deduplicate. Ignore repeat submissions from the same email within a short window before assigning.
- Secure the webhook. Turn on header authentication in the Webhook node and send the secret from your form.
- Error workflow. Add an n8n error workflow so failures outside the alert path still reach someone.
- Business-hours SLAs. Adjust the SLA query so overnight leads are measured from the next business morning.
- Rate limits. HubSpot limits requests per private app, so keep retries on and avoid bulk replays through the webhook.
- Review misroutes. Check the log weekly and fix the sheet, not the prompt.
The AI lead routing guide covers routing design, enrichment timing and what breaks in production. For a hand with your routing rules, get in touch.