Integration guide

Connect HubSpot to noombat

A one-way, read-only connection: noombat reads your CRM on a schedule and never writes anything back. One private app, one token — a HubSpot super admin can complete this in about 10 minutes.

Using Salesforce instead? Salesforce setup guide →

Before you start

  • You'll need a super admin — private apps are only visible to super admins, and that's the only HubSpot permission this setup needs.
  • Every HubSpot tier includes private apps — free CRM, Starter, Professional and Enterprise all allow up to 20 per account, at no cost and consuming no user seat.
  • Know your Hub ID (click your account name, top right — it's also the number in your app.hubspot.com URL) and your data hosting region (Settings > Account Defaults > Data Hosting). EU portals issue pat-eu1-… tokens, US portals pat-na1-… — no other setting depends on it, we just need to know.
  • Marketing email opens/clicks need Marketing Hub or CMS Hub Professional/Enterprise (HubSpot doesn't offer the scope below those tiers). That part is optional — everything else works on any tier.
1

Create the private app

~5 min

A private app is HubSpot's built-in way to give one integration its own key with an exact list of permissions — auditable on its own, unaffected by staff changes, and revocable in one click.

Development > Legacy apps > Create legacy app — choose Private. In portals still on the older navigation it's Settings > Integrations > Private Apps > Create a private app — same screen either way.
  • Name: noombat
  • Description: read-only CRM feed for noombat — optional, but it helps the next admin know what this app is

“Legacy apps”? Don't let the label worry you

HubSpot recently re-filed private apps under “Legacy apps” as its new developer platform rolls out. They're fully supported — the label marks the older of two app mechanisms, not a deprecation of your setup.

Scopes tab — tick exactly these, read scopes only

crm.objects.companies.readthe companies you sell to
crm.objects.contacts.readthe people at those companies — this also unlocks the calls, meetings and notes logged on your records (HubSpot has no separate scope for those)
crm.objects.owners.readrecord owners, so activity and companies can be attributed to your reps
crm.lists.readwhich of your lists each company and contact belongs to
sales-email-readthe content of one-to-one emails logged on your records
crm.objects.deals.readoptional — deals and pipelines, so revenue outcomes connect back to the market
formsoptional — form submissions, if you capture demand through HubSpot forms
contentoptional — marketing email opens and clicks; HubSpot only offers this scope on Marketing Hub or CMS Hub Professional/Enterprise

The optional three (deals, forms, marketing email events) are worth ticking if you use those parts of HubSpot — skip any you don't, and tell us which.

No write scopes — that's the whole point

The scope picker pairs most read scopes with a .write sibling. Leave every write scope unchecked: we don't want them, and with only read scopes granted, HubSpot itself rejects any write — read-only is enforced by the platform, not by our promise.

Click Create app and confirm. Scopes can be adjusted any time later — edits apply to the existing token immediately, so a missed scope is a ten-second fix, not a redo.

2

Copy the access token

~1 min
(the app) > Auth > Show token > Copy

The token starts with pat-na1- or pat-eu1- depending on your region. Use the Copy button rather than selecting the text — a surprising number of failed setups are a token that picked up a space or lost a character on the way.

This token is the one secret — treat it like a password

Anyone holding it can read what the scopes allow. It stays viewable to super admins on this Auth tab (so you can come back for it), and the same tab is your kill switch: Rotate and expire now invalidates the old token instantly, and HubSpot emails every super admin whenever a rotation happens.
3

Send us the connection details

~2 min
  • The access token (pat-…)
  • Your Hub ID
  • Your data hosting region (EU, US, …)
  • Which optional scopes you skipped, if any

Share the token securely — never in a plain email

Best: a share from your password manager (1Password, Bitwarden, Keeper…) to integrations@noombat.ai. Also good: a self-destructing link (e.g. onetimesecret.com — paste the value, send the link, it burns after one view). Or read it out on a call. If the token ever leaks, rotate it on the Auth tab and the old one dies instantly.

Once the details arrive we run a read-only verification the same day — connecting with your token and checking each object returns what it should — and confirm back to you. If anything's off, we tell you the exact setting to adjust; the table below is the complete list of what it could be.

Troubleshooting

Real failure modes with the exact fix. If yours isn't here, send it over — we diagnose these quickly.

What you seeWhyFix
403 MISSING_SCOPES — “This app hasn't been granted all required scopes to make this call”A scope from the step-1 checklist wasn't ticked. The response names the missing scope under “requiredGranularScopes”.Open the app → Scopes → tick it → Save. The existing token picks up the new scope immediately — no new token needed.
The same MISSING_SCOPES error, but the scope IS ticked — or the scope doesn't appear in the picker at allYour HubSpot tier doesn't include that feature. The “content” scope (marketing email events) needs Marketing Hub or CMS Hub Professional/Enterprise.It's optional for us — skip that scope and tell us, and we plan the integration around it.
401 INVALID_AUTHENTICATION — “Authentication credentials not found”The token was truncated or picked up whitespace when pasted, or it has been rotated since you copied it.Re-copy with the Copy button on the app's Auth tab (avoids manual selection) and check for spaces or line breaks.
Everything worked for weeks, then every call returns 401The token was rotated, or the app deleted. HubSpot emails every super admin when either happens.Send us the new token the secure way from step 3 and we're back the same day.
You can't find the private apps page, or can't create the appPrivate apps are visible to super admins only.Have a super admin run step 1 — it's the only HubSpot permission this setup needs.
Association lookups fail with USER_DOES_NOT_HAVE_PERMISSIONSThe super admin who created the app has since been removed or downgraded — HubSpot ties some calls to the creator.Rotate the token (or recreate the app) under an active super admin and send us the new value.
“Hub <your id> is unknown to this Hublet”Rare — stale routing state after HubSpot migrated your portal between data centres.Rotate the token; the new one carries the current region and routing fixes itself.

Security & data questions

The questions security-conscious admins ask us, answered the way we answer them.

Is this really read-only?

Yes, and it's enforced by HubSpot, not by our promise. The private app holds only read scopes — every write endpoint checks for the paired .write scope, which the app doesn't have, so the platform itself rejects any write attempt. There is nothing to configure to get this guarantee; it's how HubSpot scopes work.

What does noombat read, and why?

Companies and contacts (who you sell to), deals (pipeline and revenue), the engagements logged on your records — calls, meetings, emails, notes — plus list memberships, form submissions and marketing email opens/clicks (how your market responds), and owners (who works what). noombat keeps a read-only mirror and uses it to score your market, connect the leads it generates to the activity and revenue they produce, and show your team a live, prioritised view. Historical data matters too: the scoring learns from what already happened, which is why a forward-only feed (like a webhook) isn't enough.

Can we keep specific properties private?

Honestly: HubSpot's scopes are object-level, so a token can't be limited to specific properties the way Salesforce field-level security works — HubSpot's own docs note that its user-facing property restrictions don't apply to API access. Two things do help. First, noombat only requests the specific properties it uses (happy to share the exact list). Second, if you're on Enterprise, HubSpot's Sensitive Data feature gates any property you classify as sensitive behind dedicated *.sensitive.* scopes — which we don't request, so those values are platform-blocked to our token.

What does this cost on the HubSpot side?

Nothing. Private apps are included in every HubSpot tier — including the free CRM — with up to 20 per account, and a private app is an account-level credential, not a user, so no seat is consumed. The one tier-dependent piece is the optional content scope (marketing email opens/clicks), which HubSpot only offers on Marketing Hub or CMS Hub Professional/Enterprise; everything else works on any tier.

Couldn't we just send a webhook instead?

A webhook works well for pushing one object's changes in real time, but it can't replace API access here: webhooks only send changes going forward (noombat needs the existing history to learn from), each object needs an automation built and maintained on your side, and to fetch the full record a webhook receiver ends up calling the API anyway. We're happy to add webhooks on top of API access for time-sensitive events later.

How do we revoke access?

Instantly, from your side, in either of two ways: on the app's Auth tab choose Rotate and expire now (the old token dies immediately), or delete the private app (its token is permanently revoked). Nothing on our side can restore access. If you want a graceful handover instead, “Rotate and expire later” keeps the old token alive for 7 days while the new one is delivered.

Can we audit what noombat reads?

Yes. The private app's page in HubSpot has an API call log covering the past 30 days — every request with its method, endpoint and response code, filterable and exportable as CSV. Because noombat is the only thing using this app's token, everything in that log is attributable to us alone. (HubSpot doesn't store request or response payloads in the log, only the calls themselves.)

Where does the data live once noombat has it?

In an isolated per-client database schema hosted in the EU (Frankfurt), encrypted in transit and at rest, never mixed with other customers' data, and deleted if we part ways. We're happy to put data-handling terms in writing or walk through it with your security team.

Anything unclear, or a policy conflict? integrations@noombat.ai — or bring your HubSpot admin and we'll do the whole thing together on a call.