A HubSpot JobNimbus integration that holds up is a small connector on HubSpot's contact webhook that creates the JobNimbus contact and a job on the right board with the source set, writes the JobNimbus id back to a HubSpot property, appends a note when the person already exists instead of creating a duplicate, and runs a daily reconcile that lists what is in one system and missing from the other. That is the pattern we used to replace a Make automation that was producing contacts with no source and plenty of duplicates. This piece covers why the no-code version failed, the connector design, the JobNimbus API realities, the daily reconcile, and a comparison of Zapier or Make, a native connector, and manual entry.
The setting is a roofing company where marketing lives in HubSpot and production lives in JobNimbus, which is a common split. HubSpot gets the forms, the ads and the call tracking; JobNimbus gets the estimate, the crew and the invoice. The question is how a lead becomes a job without a person retyping it and without the source getting lost on the way.
Why the No-Code Sync Broke.
The original automation was a Make scenario, and the Zapier version would have failed the same way. It watched for new HubSpot contacts and created a JobNimbus contact with the name, phone and email. Four problems appeared within weeks.
- Missing sources. The scenario mapped name and phone but not the HubSpot original source or the campaign, so every JobNimbus contact read as blank or website. The office lost the ability to tell which jobs came from ads.
- Duplicates. A returning customer who filled out a new form was a new HubSpot contact event, so the scenario created a second JobNimbus contact. Sales had two records with half the history each.
- No job. The scenario created a contact but not a job, so the production board did not show the lead, and the office created the job by hand, sometimes twice.
- Silent failures. When JobNimbus returned an error the scenario stopped or skipped, and nobody knew until a customer called asking why no one had come out.
None of these are bugs in Make or Zapier. They are the result of a tool that runs one step per trigger and has no memory of what it did yesterday. Lookups, conditional appends and reconciliation are possible in those tools, but by the time you have built them you have written a program in a worse editor. If you are still choosing between platforms rather than connecting them, GoHighLevel versus HubSpot for contractors is the earlier decision.
The Native Connector Pattern.
Definition: a native connector is a small service you own that receives HubSpot's webhook, decides what to do based on the state of both systems, and writes to both. Ours runs as a serverless function with a queue in front of it. The flow on a new lead:
- HubSpot fires a webhook on contact created, or on a property change that marks the contact as a lead worth pushing.
- The connector fetches the full contact from HubSpot, including original source, campaign, form name and the phone in E.164 format.
- It searches JobNimbus by phone, then by email. If a contact exists, it appends a note with the new inquiry and the source, and updates the open job if there is one. If not, it creates the contact.
- It creates a job on the intake board (call it New Leads or New Opportunity, whatever the office uses) with the source set from HubSpot and the lead details in the description.
- It writes the JobNimbus contact id and job id back to HubSpot custom properties, and sets a synced timestamp.
- It logs the run. Any failure goes to the retry queue and, after the retries are spent, to a channel a person reads.
That is the whole thing. The only clever part is the lookup before the write, and that is the part the no-code flow skipped.
“A sync is not the code that copies records. It is the code that notices when the copy is wrong.”
JobNimbus API Realities.
A few facts about the JobNimbus side that shape the design. Authentication is an API key per account, generated in the account settings and sent as a header; there is no per-user token, so the connector acts as the account and its writes show as the integration user. Contacts and jobs are separate objects, and a job carries the workflow and status names the office uses, so the connector has to know the exact strings, which you read from the API once and store in configuration rather than hard-coding.
The API sits behind CloudFront, and a burst of requests, the kind a backfill or a busy Monday morning produces, can return 403 responses that look like an authentication failure and are not. Treat a 403 during a burst as retryable: back off, wait, retry, and only alert if it persists. That is why the queue is in front of the function. Sequential writes with a short delay finish reliably; a parallel blast gets blocked.
Source lives on the job, not only on the contact. Set it on both, because the reports the office runs come from the job. If the office keeps a fixed list of sources, add the marketing sources to that list first, or the API write goes through with a value nobody can filter on.
One Front Door for Every Lead.
Web forms are the easy case. Calls tracked in CallRail, leads from Local Services Ads, chat leads and Meta lead forms all need to become jobs too, and they should enter through the same path. Our approach is to make HubSpot the front door: CallRail creates or updates the HubSpot contact with the call source, LSA leads arrive through an email parser that posts to HubSpot, and lead forms post through their native HubSpot integrations. The connector then sees one kind of event and every job carries a source, whether it started as a call, a click or a form. The HubSpot and CallRail integration covers the call side.
The alternative, a separate automation per source straight into JobNimbus, is how duplicates come back. Two paths that do not know about each other will create the same customer twice.
Push Delay and Human Review.
Some offices want a person to look at a lead before a job appears on the production board, because the board is where the crews and the estimators look, and a spam form submission there is noise. The connector has a push delay setting, in minutes, that holds the job creation after the contact is created; a coordinator can mark the contact as junk in HubSpot inside that window and the job never appears. Set it to zero and the job is created immediately. Set it to the length of the office's triage routine and the board stays clean. The contact sync itself is not delayed, so a returning customer's note still lands right away.
The Daily Reconcile.
Once a day the connector pulls contacts created in HubSpot in the last window and contacts created in JobNimbus in the same window, matches by phone and email, and produces two lists: in HubSpot but not in JobNimbus, and in JobNimbus but not in HubSpot. The first list is a connector failure or a contact that was held by the push delay and forgotten. The second is a lead the office typed straight into JobNimbus, which is usually a phone call that bypassed tracking, and it is a marketing blind spot as much as a data problem.
The reconcile output goes to a channel or an email as a short list with links. On a healthy day it is empty. The first week it will not be, and clearing it is how the office learns to route everything through the front door. This is the piece that Make and Zapier cannot do well, because it is a comparison across both systems rather than a reaction to one event.
Zapier or Make, a Native Connector, or Manual Entry.
| Method | Speed | Dedupe | Source fidelity | Cost of maintenance |
|---|---|---|---|---|
| Zapier or Make automation | Seconds to minutes, depending on the plan's polling interval | Only if you build lookup steps; most flows do not | Whatever fields were mapped; sources usually missed | Low to build, high to trust; breaks quietly when a field or a status name changes |
| Native connector on the HubSpot webhook | Seconds, on the webhook | Lookup by phone and email before every write; appends notes for returning customers | Source set on contact and job from HubSpot data, every time | A day or two to build, then a daily reconcile; needs someone who can read a log |
| Manual entry by the office | Whenever someone gets to it | Depends on the person searching first | Depends on the person asking; often blank | No build cost, ongoing labor, and errors that no report catches |
For a roofing company with more than a handful of leads a day, the connector pays for itself the first time it catches a returning customer. For the wider set of tools that plug into the production side, JobNimbus integrations for roofing marketing lays out the landscape.
What Usually Goes Wrong.
- Matching on name. Two people with the same name become one customer and one customer with a typo becomes two. Match on phone and email.
- Hard-coding status names. The office renames a board column and every job lands in the wrong place or fails to create.
- Treating CloudFront 403s as fatal. The backfill stops halfway and the log says unauthorized.
- Creating the job without the source. The production board fills up and the marketing report goes blank.
- No write-back to HubSpot. Nobody can tell from HubSpot whether a lead made it to JobNimbus, so the reconcile has nothing to check against.
- Reopening lost leads. A returning customer's new inquiry should append to the record and create a new job, not flip an old lost job back to open.
Is there a native HubSpot JobNimbus integration?
There is no official two-way sync that sets sources and dedupes on its own. The options are a Zapier or Make automation, which copies fields per event; a small connector you own on HubSpot's webhook, which looks up before writing and reconciles daily; or manual entry. The connector is the one that keeps source and dedupe right.
How does the connector avoid duplicate JobNimbus contacts?
It searches JobNimbus by normalized phone number and then by email before every write. If a contact exists, it appends a note with the new inquiry and source and creates a new job on the intake board rather than a second contact. It also writes the JobNimbus id back to HubSpot so the link is visible in both places.
Why does the JobNimbus API return 403 errors?
Under a burst of requests, such as a backfill or a busy morning, the API's CloudFront layer can return 403 responses that look like authentication failures but are throttling. Put a queue in front of the connector, write sequentially with a short delay, retry 403 and 5xx responses with backoff, and only alert when the retries are spent.
What should the daily reconcile check?
Contacts created in HubSpot in the last window that have no JobNimbus id, and contacts created in JobNimbus in the same window with no matching HubSpot record by phone or email. The first list catches connector failures and held leads; the second catches leads typed directly into JobNimbus that marketing never saw.