n8n HubSpot Integration Tutorial: Connect Leads to Your CRM
Complete n8n HubSpot integration tutorial: private app setup with exact scopes, webhook form-to-contact workflow, deal stage automation, deduplication via upsert, follow-up email, and error handling in one step-by-step guide.
HubSpot Free gives you a CRM but locks native Workflows behind a paid Marketing Hub plan. That means anyone on the free tier who wants a form submission to auto-create a contact, push it to a deal stage, and trigger a follow-up email has to wire that logic outside HubSpot. This n8n HubSpot integration tutorial walks you through the complete workflow in one sitting, from private app credentials to an error-handled webhook that captures leads end to end.
- HubSpot deprecated API keys (hapikey) in November 2022, so all new n8n integrations must use Private App access tokens with explicit scopes.
- The five scopes required for a full lead-to-deal workflow are crm.objects.contacts.read, crm.objects.contacts.write, crm.objects.deals.read, crm.objects.deals.write, and crm.schemas.contacts.read.
- The HubSpot node's Create or Update Contact operation uses email as the upsert key, eliminating the need for a separate Search plus IF branch to handle duplicates.
- HubSpot Free users cannot build trigger-based Workflows inside HubSpot itself, so n8n's webhook trigger is the direct substitute for automating deal stages and follow-ups.
- Across the 11 HubSpot plus n8n pipelines Rain Automation has shipped for clients since 2024, the average webhook-to-contact-creation latency on our production instance is about 1.8 seconds, and every single deployment required the upsert deduplication pattern described below.
Why This n8n HubSpot Integration Tutorial Covers the Full Lead Pipeline
HubSpot Free gives small businesses a CRM and a deal pipeline at zero cost, but it caps new accounts at 1,000 contacts and locks automated Workflows behind Marketing Hub Professional at $800 per month billed annually (or $890 per month billed monthly). n8n plugs that gap: the self-hosted version is free forever, and a single webhook-triggered workflow can replace the entire Workflows feature for most lead capture use cases.
For businesses that outgrew a spreadsheet but can't justify $800 a month for a feature they'll use twice a day, this combination is the practical CRM stack. HubSpot holds the contacts and deals. n8n handles the triggers, conditional logic, and outbound actions. The two talk over a Private App token.
Here's why this matters. Most agencies I've worked with at Rain Automation, our Atlanta-based automation consulting practice, hit this wall around year two: they've accumulated a few hundred contacts, they know response time matters, but they also know their volume doesn't justify paid HubSpot tiers. So leads sit in a contact form inbox for 18 hours because nothing connects the form to the CRM to the salesperson. The n8n HubSpot integration closes that loop in under an hour.
Red Flags That Tell You It's Time to Wire This Up
Most small businesses hit the same five breaking points before they wire this up. Contact forms collect leads that sit unprocessed for hours, duplicate contacts pile up across multiple forms, and deal stages never update without manual effort. If any of the patterns below sound familiar, the n8n HubSpot integration pays for itself the day you deploy it.
Here are the symptoms I see most often on client calls:
- Your contact form sends an email notification, but nobody adds the lead to HubSpot until end of day.
- You have more than one form on your site and each one needs different routing or deal stage logic.
- Duplicate contacts are piling up because two forms fire the same email address into HubSpot.
- You promised a client follow-up email within 5 minutes and you can't hit that SLA consistently.
- You want a deal created automatically when a certain form fires, with the right pipeline stage already set.
For a broader framing of where n8n fits in a small business CRM stack before you commit, our n8n CRM integration tutorial for small businesses covers the conceptual groundwork.
Prerequisites Before You Start
You need three things running before you open a single node: a working n8n instance, a HubSpot account (Free is fine), and about 45 minutes of focused time. No coding experience required, but you'll want basic comfort with clicking through n8n's node editor.
Here's the concrete checklist:
| Requirement | Notes |
|---|---|
| n8n instance | Self-hosted via Docker, n8n Cloud (from €24/month billed annually, verify current pricing at n8n.io/pricing), or Desktop. Self-hosted is free forever. |
| HubSpot account | Free plan works (capped at 1,000 contacts for new accounts). Sign up at hubspot.com/products/crm. |
| Super Admin access | You need it to create a Private App. Regular user permissions won't cut it. |
| A test form | Can be a dev form, Typeform, Webflow, or a curl command for testing. |
| Deal pipeline configured | Know your HubSpot pipeline ID and at least one deal stage ID. |
If you haven't picked a workflow tool yet, our n8n vs Zapier for lead capture comparison breaks down the cost and flexibility trade-offs.
Step 1: Create a HubSpot Private App and Get Your Access Token
Log into HubSpot, click the gear icon to open Settings, then open Integrations, then Private Apps. Click Create a private app, name it something like n8n Lead Capture, then open the Scopes tab before you click Create. This order matters. Generating the app without scopes first is the single most common cause of the Authorization failed error later.
In the Scopes tab, tick exactly these five CRM scopes:
crm.objects.contacts.readcrm.objects.contacts.writecrm.objects.deals.readcrm.objects.deals.writecrm.schemas.contacts.read
Per n8n's official HubSpot credentials documentation, these are the scopes needed for any workflow that reads and writes both contacts and deals. If you're only creating contacts and skipping the deal portion, you can drop the two deal scopes. If you plan to write custom contact properties, keep the schemas.contacts.read scope so n8n can validate property types before submitting.
After ticking the scopes, click Create app in the top right. HubSpot will prompt you to confirm. Once confirmed, the Access Token tab shows up. Click Show token, then copy it. Treat this token like a password. Anyone with it can read and modify your CRM. For deeper context on HubSpot's authentication model, see HubSpot's own Private Apps setup guide.
Why Not the Old API Key Method?
If you've followed an older n8n tutorial and hit a This hapikey doesn't exist error in your HubSpot node, that's because HubSpot sunset API keys (hapikey) as a third-party auth method. The fix is straightforward: delete any credential in n8n that uses the API key auth type and recreate it as Private App. Existing workflows using the old credential need their credential reference updated, but the node configuration itself carries over.
Step 2: Set Up Your n8n Credential for HubSpot
Open n8n, go to Credentials in the left sidebar, click Create New, search for HubSpot, then choose HubSpot API. In the dropdown labeled Authentication, select Private App. Paste the access token from Step 1 into the App Token field, give the credential a clear name like HubSpot Production, and click Save.
n8n will automatically test the credential by making a GET request against HubSpot's API. If it succeeds, you'll see the green checkmark. If it fails with Authorization failed because the provided scopes are missing, the root cause is almost always this: you generated the token before you ticked all the scopes. This exact error pattern is documented across dozens of HubSpot Community threads on the n8n scopes issue, and the resolution is consistent every time. Return to Private Apps in HubSpot, edit your app, verify all five scopes are checked, click Save changes, then regenerate the token from the Access Token tab. Copy the new token back into n8n.
I've walked at least a dozen clients through this exact error. Every time, the order of operations was wrong. Tick scopes first, save, then generate the token. If you create the app with zero scopes and add them later, the existing token may not reflect those additions. Regenerate the token after saving scope changes to guarantee the new permissions are included.
Step 3: Build the Webhook Trigger Node
Create a new workflow in n8n, add a Webhook trigger node, set the HTTP Method to POST, and choose a clear path like hubspot-lead. Copy the Test URL from the node panel, because this is the address you will post form submissions to while building and testing the workflow.
Leave Authentication as None for now, and click Listen For Test Event in the node panel so n8n will capture the next incoming request. The Webhook node has two URLs: Test and Production. The Test URL only fires while you have the workflow open and have clicked Listen For Test Event. The Production URL fires whenever the workflow is activated, but it only works after you toggle the Active switch in the top right.
A mistake I see constantly: developers build with the Test URL, ship it to their form, and then wonder why nothing fires after they close n8n. The moment you flip the workflow to Active, switch your form to post to the Production URL. Keep this in your deploy checklist.
For a complete walkthrough of webhook security (HMAC signing, auth headers, rate limiting), see our webhook lead capture step-by-step guide. It covers the production-hardening pieces this tutorial keeps brief.
Testing Your Webhook Payload
Before connecting HubSpot, confirm your form actually posts the fields you expect. Click Listen For Test Event in the Webhook node, then submit your form (or run this curl):
curl -X POST https://your-n8n.example.com/webhook-test/hubspot-lead \
-H "Content-Type: application/json" \
-d '{"firstName":"Jane","lastName":"Doe","email":"[email protected]","phone":"4045551234","source":"homepage-form"}'
You should see the payload appear in the node's output panel. If the fields don't match what you expect, the problem is on the form side. Fix it before moving on.
Step 4: Map Form Fields and Deduplicate Contacts with Upsert
Add a HubSpot node after the Webhook. Set the Resource to Contact and the Operation to Create or Update. This is the upsert operation. HubSpot's API uses the email address as the unique key, so if a contact with that email already exists, HubSpot updates the existing record instead of creating a duplicate. No Search plus IF branch required.
This is a point most existing tutorials miss completely. They walk you through a Search Contact node, then an IF node to branch on found versus not-found, then separate Create and Update branches. That architecture works, but it's three nodes where one will do. The Create or Update operation has built-in deduplication because HubSpot's own Contacts API treats email as the unique identifier for upsert.
Map the fields from your webhook payload into HubSpot's standard contact properties:
| HubSpot Property | n8n Expression |
|---|---|
{{$json.email}} |
|
| First Name | {{$json.firstName}} |
| Last Name | {{$json.lastName}} |
| Phone Number | {{$json.phone}} |
| Lead Source (custom) | {{$json.source}} |
If you need custom properties that aren't in the standard list, add them under Additional Fields. You'll need to have created the property in HubSpot first, with the internal name matching what you reference in n8n. For a deeper look at field mapping patterns for other form tools, our guide on connecting Google Forms to your CRM with n8n covers several real-world payload shapes.
Click Execute Node to test. The output should return the HubSpot contact object with an id field. Keep that ID reference. You need it in Step 5.
Step 5: Create or Update a Deal and Set the Deal Stage
Add another HubSpot node after the contact node. Set Resource to Deal and Operation to Create. Under Additional Fields, expand Associations, and add the contact ID from the previous node using the expression {{$node["HubSpot"].json.id}}. For Deal Stage, paste the internal stage ID from your HubSpot pipeline, not the display name.
Finding your deal stage ID is the piece that trips people up. HubSpot's UI shows you the display name (New Lead, Qualified, Closed Won), but the API requires the internal stage ID, which looks like appointmentscheduled or a numeric string. To find it:
- Go to HubSpot Settings, then Objects, then Deals.
- Click Pipelines.
- Click Edit stages.
- Click the settings cog next to any stage.
- The stage ID is shown in the URL or the stage details panel.
Copy it. Paste it into the Deal Stage field in your n8n HubSpot Deal node.
Set Deal Name using an expression so each deal is self-documenting:
{{$node["HubSpot"].json.properties.firstname}} {{$node["HubSpot"].json.properties.lastname}} - {{$json.source}}
Set Pipeline to the pipeline ID (also visible in the same settings page). Leave Amount blank for now unless you have a known deal value from the form.
Now. Here's a subtle thing: if you want to avoid creating a duplicate deal every time the same person submits a form, you need a Search Deals node ahead of this one, with a branch on whether a deal already exists for that contact. For most lead-capture use cases, I don't bother. A duplicate deal is a smaller problem than a missed lead, and sales can dedupe in HubSpot's UI. If your use case requires strict one-deal-per-contact enforcement, add the Search and IF logic.
Step 6: Send a Follow-Up Email via the Send Email Node
Add an Email Send node (or a Gmail node if you prefer) after the Deal node. Configure SMTP credentials or OAuth, map the To field to {{$node["HubSpot"].json.properties.email}}, write a short subject and body using HubSpot property references for personalization, then test. This sends the confirmation within seconds of the form submission.
Here's a simple template that works for most lead magnets:
- Subject:
Thanks for reaching out, {{$node["HubSpot"].json.properties.firstname}} - Body:
Hi {{$node["HubSpot"].json.properties.firstname}},Thanks for getting in touch. I received your inquiry about {{$json.source}} and I'll follow up personally within the next business day.
Talk soon,
Ryan
For a complete breakdown of every field on the Send Email node (attachments, HTML versus plain text, reply-to configuration, sender name), see our n8n Send Email node configuration guide.
When to Use HubSpot's Email Instead
One decision point worth calling out: should the follow-up email come from n8n's SMTP or from HubSpot's native email system? The short answer:
- Use n8n's Send Email when you want simple, reliable transactional sends and you don't need HubSpot's email analytics (opens, clicks, unsubscribes).
- Use HubSpot's email (via the HubSpot Engagement node) when you want the send logged against the contact's timeline in HubSpot and subject to HubSpot's deliverability reputation.
For free-plan users, n8n's SMTP is almost always the right call because HubSpot Free limits marketing email volume.
If you want a direct comparison of how these two nodes differ on authentication, threading, and rate limits, the guide on when the Send Email node makes more sense than the Gmail node covers each trade-off in depth.
Step 7: Handle Errors So Failed Webhooks Don't Disappear
Create a second workflow called something like HubSpot Error Alerts. Add an Error Trigger node as the starting node. Add a Slack or Email node after it that sends the error details to your inbox or a dedicated Slack channel. Save and activate the workflow, then go back to your main workflow, click Settings, and select this workflow under Error Workflow.
This is the step every tutorial skips and every production deployment needs. When HubSpot rate limits you (429 errors), when the webhook payload is malformed, when HubSpot's API is temporarily down, something has to tell you about it. Otherwise leads silently vanish and you find out two weeks later when a client complains.
Here's a concrete example. Marcus, a mortgage broker in Atlanta, lost 34 form submissions over six days after his n8n HubSpot credential expired and nothing alerted him. His workflow had been capturing leads fine for three months, then the access token rotated on the HubSpot side and every subsequent webhook hit failed silently. The HubSpot node returned a 401, the workflow kept running past the failure, and the Email node sent confirmations for contacts that were never actually created in the CRM. We added an Error Trigger node pointed at a Slack channel plus a second sanity check on the HubSpot node response, and he hasn't lost a lead since. Total build time: about 20 minutes.
Marcus's situation is one of several silent failure patterns that quietly break n8n workflows, and most of them share the same fix: a trigger that tells you the moment something stops working.
Configure the error workflow body to include at minimum:
- Workflow name
- Node that failed
- Error message
- Execution URL (so you can click into n8n and see the full trace)
- The original webhook payload
You want to be able to diagnose from the alert without opening n8n at 10 PM.
Testing the Full Workflow End to End
Before flipping the switch to Active, run the complete chain once with a test payload. Submit your form (or fire the curl command from Step 3) and verify six outcomes: the Webhook fires, the Contact upserts cleanly, duplicates are suppressed, the Deal appears at the correct stage, the follow-up email lands, and the Error Trigger alerts on a malformed payload. We call this the Rain Six-Gate Launch Check.
Here is the full six-gate sequence. Do not flip the workflow to Active until every gate passes green:
- Gate 1, Payload Gate. Webhook output shows the expected payload fields with the correct types (strings where you expect strings, not objects or arrays).
- Gate 2, Contact Gate. HubSpot contact exists in Contacts with every mapped field populated, custom properties included.
- Gate 3, Dedup Gate. Submit the same email a second time and confirm no duplicate contact is created. The upsert operation should update the existing record instead.
- Gate 4, Deal Gate. Deal appears in your pipeline at the correct stage, associated to the contact, with the deal name format matching your expression.
- Gate 5, Email Gate. Follow-up email arrives at the test address within 60 seconds, with personalization tokens rendered (not showing raw
{{firstname}}placeholders). - Gate 6, Error Gate. Intentionally fire a malformed payload (missing email, or an invalid token) and verify the Error Trigger workflow alerts you within a minute.
Once all six gates tick green, switch the workflow to Active, update your form to point at the Production webhook URL, and you're live. The Six-Gate Launch Check is the pre-flight we run before handing a HubSpot plus n8n workflow back to any client at Rain Automation. If you skip gates 3 and 6, you will find out about the failure mode in production, not staging.
The Cost of Not Wiring This Up
In my experience walking clients through their pre-automation baseline, manual data entry from a contact form into a CRM takes roughly 60 to 90 seconds per lead once you account for tab-switching, copy-paste, and field validation. Call it 90 seconds at the slow end. At 10 leads a day that's 15 minutes. At 40 leads a day that's an hour, and across a standard working year that adds up to around 365 hours of someone's attention copying fields into text boxes.
And that's assuming nobody ever forgets, misspells an email, or routes a deal to the wrong pipeline.
Contrast that with what a wired-up pipeline actually costs to run. Across the 11 HubSpot plus n8n workflows Rain Automation has shipped for clients since 2024, the average webhook-to-contact-creation latency on our production n8n instance is about 1.8 seconds per lead, and every one of those deployments uses the upsert pattern described in Step 4 (the Search plus IF branch pattern showed up in zero of them because it creates three nodes worth of maintenance for no gain). The five-node workflow in this tutorial handles the full form-to-deal-to-email chain in under a second of human attention per lead, with a paper trail in n8n's execution history for every submission. The ROI math is uncomplicated.
Frequently Asked Questions
Does n8n work with HubSpot Free?
Yes. The n8n HubSpot integration works identically on HubSpot Free, Starter, Professional, and Enterprise plans. The scopes available to your Private App are determined by the features enabled in your HubSpot account, but core contact and deal operations are available on the Free plan. You're not missing anything on the n8n side because of your HubSpot tier. If you want a focused walkthrough on how to automate HubSpot deal stages without paying for Marketing Hub, that guide covers the complete free-tier setup from deal creation to follow-up emails.
Do I need a HubSpot developer account to use n8n with HubSpot?
No. You create a Private App inside your regular HubSpot account under Settings, Integrations, Private Apps. Older tutorials reference a developer account because HubSpot required it for API keys, which are now deprecated. You do need Super Admin role to create apps, so ask your admin if you're a regular user.
What scopes does n8n need for the HubSpot integration?
For a full lead-to-deal workflow, five scopes: crm.objects.contacts.read, crm.objects.contacts.write, crm.objects.deals.read, crm.objects.deals.write, and crm.schemas.contacts.read. If your workflow only touches contacts, you can drop the two deal scopes. For workflows that also create companies or tickets, add the corresponding crm.objects scopes. Always tick scopes before generating the token.
How do I stop duplicate contacts from being created when using n8n with HubSpot?
Use the Create or Update Contact operation in the HubSpot node, not the Create Contact operation. HubSpot's API treats email as the unique key for this operation. If the email already exists, the existing contact is updated with new field values rather than creating a duplicate. This eliminates the need for a separate Search plus IF branch architecture.
What HubSpot triggers are available in n8n?
n8n's HubSpot Trigger node supports 18 event types including contact created, contact updated, deal stage changed, deal created, deal updated, company created, and ticket created. For HubSpot Free users, a webhook trigger inside n8n is often more practical than the HubSpot Trigger node because it avoids the paid Workflows requirement.
Can I use n8n with HubSpot without coding?
Yes. The entire workflow in this tutorial is built with zero code, just node configuration and expression-based field mapping. Expressions like {{$json.email}} are visual references, not code. If you outgrow the built-in nodes, n8n has a Function node for custom JavaScript, but 95 percent of lead-capture workflows never need it.
Where to Take This Next
This tutorial covered the happy path: form to contact to deal to email to alert. Once you have that working, the common next steps are lead scoring, multi-step nurture sequences, and routing logic based on form source or deal value. Each builds directly on the five-node foundation you just wired up.
A few places to go from here:
- For scoring logic based on form behavior and firmographic data, our guide on automated lead scoring with n8n and HubSpot extends this workflow with a rules engine.
- Once contacts are landing in HubSpot, you can set up how to enrich those contacts with HubSpot Breeze Intelligence the moment they land in your CRM, pulling company size, industry, and role data without a third-party data provider.
- For 10 pre-built HubSpot automations you can lift and drop into your pipeline, see 10 HubSpot workflow automation examples you can copy.
- If you're still deciding between n8n and Make, our n8n and Make CRM integration comparison breaks down the practical differences.
- If your lead source is an IDX property search, our guide on how to wire an IDX lead source directly into this same HubSpot pipeline covers the real estate-specific setup end to end.
If you'd rather have someone wire this up for you with error handling, monitoring, and deal-stage logic tuned to your exact pipeline, our automation consulting services cover exactly that. Most HubSpot plus n8n deployments take us a few hours end to end and come with documentation you can hand to your team.
Ready to stop losing leads to manual data entry? Get in touch and we'll map your exact form-to-CRM flow on the call.
Affiliate disclosure: Rain Automation receives a referral commission if you sign up for n8n Cloud through our partner link (n8n.partnerlinks.io/rainautomation). We only recommend tools we use ourselves across client deployments. The self-hosted version of n8n is free and not gated behind any affiliate link.
This tutorial references third-party tools whose features, pricing, and API behavior may change. Verify current HubSpot and n8n documentation before production deployment. Screenshots and exact field names may differ slightly from your version. Marcus is a pseudonym; the scenario described reflects a real client engagement with identifying details changed.