HubSpot integration: two-way contact and deal sync
Push ZenMode contacts, deals and activities into HubSpot and pull contacts, deals and notes back, on three sync triggers.
Verified against the product on September 3, 2026 · Updated · Set up in /dashboard/settings
What this integration is
HubSpot is a native OAuth integration. You click Connect, approve ZenMode on HubSpot's consent screen, and ZenMode stores and refreshes the tokens for you — there is no API key to paste, and nothing sits in between the two products. It runs in both directions: ZenMode pushes contacts, deals and activities into your HubSpot portal when you press Sync Now (or, with auto-sync on, when you edit a record in ZenMode's CRM), and pulls contacts, deals and notes back. There is no plan gate on it; the connection is tied to the ZenMode account you are signed in as.
What syncs
| What | Direction | Exact fields written or read |
|---|---|---|
| Contacts | ZenMode → HubSpot | firstname, lastname, email, phone, company, jobtitle, hs_linkedin_url |
| Deals | ZenMode → HubSpot | dealname, amount, dealstage, closedate, associated to the contact |
| Activities | ZenMode → HubSpot | Written as HubSpot notes: hs_timestamp, hs_note_body, associated to the contact |
| Contacts | HubSpot → ZenMode | Pulled on each sync, oldest change first, up to 500 per run; the next run carries on |
| Deals | HubSpot → ZenMode | Pulled on each sync, the same way |
| Activities | HubSpot → ZenMode | Notes only, the same way |
Before creating a record, ZenMode looks for one that already exists in HubSpot: a contact by email address, then by LinkedIn URL; a deal by the contact it belongs to together with its name. When it finds one, it fills in the fields that are empty in HubSpot and leaves the rest as they are, instead of creating a second. If that lookup cannot run (a HubSpot outage or rate limit), nothing is created and the record is tried again on the next sync. A LinkedIn profile URL (linkedin.com/in/…) is matched however it is written: with or without www, a trailing slash, capital letters or tracking parameters. A contact with only a Sales Navigator URL cannot be matched to the same person saved under their profile URL, so if it has no email address it is skipped and listed by Sync Now rather than created. And if another of your ZenMode contacts with the same LinkedIn profile is already in HubSpot, the second one is held and listed instead of becoming a duplicate. A contact with neither an email address nor a LinkedIn URL has nothing to match on, so syncing it again after a disconnect creates it again. If two of your ZenMode deals share the same contact and the same name, ZenMode skips both rather than risk updating the wrong HubSpot deal. Deals are associated to their contact rather than left floating.
Edits made in HubSpot are not overwritten. For a record that is already synced, ZenMode compares each field with its value at the last sync: a field changed in HubSpot since then keeps HubSpot's value, which also comes back into ZenMode, and only fields changed in ZenMode since then are sent. A contact's name is written when the contact is created and never afterwards, so a first and last name split you set in HubSpot stays as you set it. An empty deal value is never sent as an amount of 0, and a deal's stage is set only when ZenMode creates the deal. A record you delete in HubSpot is not created again.
What does not sync: nothing outside that table moves. The activity pull reads notes only, so calls, emails and tasks logged natively in HubSpot stay in HubSpot. hs_note_body defaults to a short line naming the activity type and saying it was logged from ZenMode, not the message text. And a pull reads at most 500 records of each type per run, so a very large portal is caught up across several syncs rather than one; each run carries on from where the last one stopped.
HubSpot Meetings booking detection
Booking detection is a separate piece of wiring from the CRM sync above — a different inbound webhook, with its own parser. HubSpot Meetings is one of four providers ZenMode parses properly (the others are Calendly, Cal.com and Acuity Scheduling); for HubSpot it reads properties.firstname.value, lastname and email out of the payload. When a booking arrives, ZenMode promotes that connection to meeting_booked and stamps the time. The promotion is one-way only: a lead already further along is never knocked backwards. Attribution uses the signed token on the tracked calendar link the prospect clicked, falling back to a name match.
How to set it up
- Go to /dashboard/settings (the same card also appears on /dashboard/crm) and click "Connect HubSpot".
- Approve ZenMode on HubSpot's consent screen. You are returned to ZenMode with the connection live — there is nothing else to configure for the sync itself.
- On the HubSpot card, decide whether to turn auto-sync on. It is off by default. The same card carries Sync Now and Disconnect.
- For booking detection, open the Calendar section of Settings, choose HubSpot, and copy the tokenized webhook URL ZenMode shows you. That URL is unique to your account — paste it into HubSpot as the destination for Meetings booking events.
When it runs
Four triggers, and only four:
- Manual — the Sync Now button on the HubSpot card. A sync reads HubSpot first, then sends contacts, then deals. A large CRM takes more than one click: each click carries on from where the last one stopped, the card shows how far it has got (for example "Contacts: 790 of 2,713") and the button reads Continue Sync until the sync is complete. It also lists anything it did not send, and why.
- After connecting — right after you connect or reconnect HubSpot, ZenMode reads your HubSpot records in. Nothing is sent to HubSpot until that read has finished.
- On write — a contact or deal you create or edit in ZenMode's CRM pushes immediately, but only when auto-sync is enabled (it is off unless you turn it on) and only once the read after connecting has finished. Contacts that a campaign adds to the CRM are not pushed on write: they reach HubSpot when you press Sync Now.
- Nightly — a scheduled run at 06:00 UTC that pulls changes from HubSpot into ZenMode. It pushes nothing, and it runs only when auto-sync is on.
So campaign contacts go to HubSpot on Sync Now, not on a schedule. It is not a continuous feed. The Meetings webhook is different: it fires when the booking event happens, and is authenticated by the token embedded in the URL you pasted into HubSpot.
What it's useful for
A reply lands in ZenMode, and on your next Sync Now the contact is pushed with their LinkedIn URL on hs_linkedin_url, and whoever owns the account picks the conversation up inside HubSpot without retyping anything. A deal you open in ZenMode's CRM appears in your HubSpot pipeline with its stage, value and close date, so forecasting stays in one place. And a prospect who books through HubSpot Meetings flips to meeting_booked in ZenMode automatically, which keeps your ZenMode reporting honest without anyone marking rows by hand.
What it doesn't do (yet)
- The HubSpot inbound change webhook is not registered automatically. The receiving route exists and pulls a five-minute window when called, but nothing registers it with HubSpot on your behalf, its URL is not shown anywhere in the product, and it does no signature verification. In practice, a change made in HubSpot reaches ZenMode on the next sync — not the moment it happens.
- An older API-key-based HubSpot sync exists in the codebase with no UI, and it is broken. The OAuth integration described here is the working one.
- Booking detection covers Calendly, Cal.com, HubSpot Meetings and Acuity. Microsoft Bookings, Google Calendar, Chili Piper, SavvyCal and "Other" are link-and-click tracking only — no automatic booking detection.
FAQ
Which plans include the HubSpot integration?
All of them. Neither the CRM integrations nor the CRM webhooks carry a plan gate — the only integration surface that does is the public REST API, which needs Practitioner or above. Full tiers are on pricing.
Does connecting HubSpot need my LinkedIn password?
No. Integrations never touch LinkedIn credentials. Connecting HubSpot is an OAuth handshake with HubSpot and nothing else.
Is it two-way?
Yes for data — contacts, deals and notes move in both directions. It is not two-way in real time: inbound changes arrive on the next sync, because the HubSpot change webhook is not registered for you. If you are choosing between connectors, Salesforce and Monday.com run on the same Sync Now, on-write and nightly triggers.