docs
Integrations

HubSpot

Connect HubSpot, configure the recipe that decides which customer voice becomes signals, and see what is live while HubSpot ingestion rolls out.

HubSpot is a customer-voice source for nima. nima reads your portal, learns where your data lives with a per-portal recipe, and turns customer text (tickets, survey comments, deal reasons, meeting, call, email and note text) into signals. It also keeps a thin account index so beacons can show the ARR at stake. nima is read-only against HubSpot and never copies your CRM.

HubSpot ingestion status

Connecting HubSpot, scanning the portal and saving a recipe work today. Importing and syncing are rolling out: they run only once the nima team switches HubSpot ingestion on, so for now POST /v1/hubspot/import and POST /v1/hubspot/sync-now succeed but report queued: false and no HubSpot signals arrive.

Enabled by the nima team on request. Connect, scan, recipe and settings work now; importing customer voice is rolling out for all workspaces at once, so ask the nima team when you want it.

What this means in practice:

  • You can connect and finish setup ahead of time. The recipe you confirm is kept.
  • Nothing syncs on connect. Even when ingestion is on, a workspace needs a confirmed recipe and an Import press before the 15-minute sweep reads anything.
  • No workspace control turns ingestion on. There is no route, MCP tool or admin-panel switch for it.

Every /v1/hubspot/... and /v1/integrations/hubspot... route needs a signed-in owner or admin session. The account routes under HubSpot accounts and ARR at stake need a signed-in session of any member. None of these routes accepts an API key or an OAuth token, and none is available over MCP.

Connect HubSpot

Connecting HubSpot is an owner or admin action, done from Integrations in the admin panel: open the HubSpot card, choose Connect HubSpot, pick the portal and approve. nima returns you to Integrations and the card shows the portal it is reading. The connect request is POST /v1/integrations/hubspot/connect, which returns the HubSpot authorization URL.

A workspace connects one HubSpot portal. The three required scopes must be granted; the eleven optional scopes can be declined, and a source whose scope was declined shows as not granted instead of failing.

ScopeRequiredWhat it lets nima read
oauthYesBasic HubSpot sign-in
crm.objects.contacts.readYesContacts, and the meeting, call, note, task, communication and postal-mail activity attached to them
crm.objects.companies.readYesCompanies, the account index
crm.objects.deals.readNoDeals, deal won and lost reasons
crm.objects.tickets.readNoTickets
crm.objects.feedback_submissions.readNoSurvey submissions (needs Service Hub Professional or Enterprise)
crm.objects.owners.readNoAccount owners
crm.objects.custom.readNoCustom objects used as voice sources
crm.schemas.contacts.readNoContact property definitions
crm.schemas.companies.readNoCompany property definitions
crm.schemas.deals.readNoDeal property definitions
crm.schemas.custom.readNoCustom object property definitions
conversations.readNoTicket conversation threads
sales-email-readNoEmail bodies

Reconnecting works two ways:

  • Same portal. nima keeps the recipe, cursors and settings.
  • Different portal. nima resets the recipe, sync state and settings, and purges the previous portal's account data.

If HubSpot access fails for good, the connection is marked invalid, runs stop, and the fix is to connect again.

Scan and the HubSpot recipe

A HubSpot recipe tells nima where your portal keeps account identity, ARR, segments and customer voice. Every portal is configured differently, so nima proposes a recipe from a scan and you confirm it before anything is imported.

You run setup from the HubSpot card in Integrations: Scan, then Continue to mapping to review the proposed recipe, then Continue to import to set the backfill window and caps and press Import. Each step calls the route named below.

  1. Scan. POST /v1/hubspot/scan reads the shape of the portal: objects with record counts, property names, labels, types and fill rates, pipelines, owner count and lifecycle stages. A scan reads metadata only, never record values.
  2. Propose. POST /v1/hubspot/recipe/propose builds a recipe with heuristics and one model call. It never overwrites a recipe you have confirmed.
  3. Review and confirm. GET /v1/hubspot/recipe returns the stored recipe with its status, problems and the last cached scan; the evidence explaining each mapping comes back only from POST /v1/hubspot/recipe/propose. PUT /v1/hubspot/recipe saves it with { recipe, confirm }. A body that is not { recipe, confirm } returns 400 with up to 10 issues; a recipe that fails validation returns 400 with up to 20 issues, each path.to.field: message. confirm: true makes it the recipe the sync runs from.

Segments group accounts as customer, partner, prospect, churned or other, and a segment can be tracked, which stores its accounts in the index. A prospect segment cannot be tracked, and neither can a catch-all segment, because nima never stores plain leads. Before a recipe is confirmed nima counts what the tracked segments would store and refuses above 10,000 tracked accounts with a 400.

Other recipe limits: 20 segments and 20 voice sources per recipe, and 10 conditions per rule.

HubSpot voice sources

A voice source is one stream of customer text that the recipe reads. The recipe starts from presets, which are switched off automatically when the scan shows the object or scope is unavailable. Each source has a budget weight that sets its share of the daily cap, and a minimum length in customer characters.

Source idReadsWeightMinimum charactersProduct-content gate
meetingsMeeting notes1.030On
emailsInbound emails0.930On
ticketsTickets with their conversation thread0.830Off
surveysSurvey comments0.810Off
callsCompleted calls with a body0.730On
deal_lostLost-deal reasons0.720Off
deal_wonWon-deal reasons0.520Off
notesNotes0.530On
communicationsCommunications0.430On
tasksTasks0.360On
postal_mailPostal mail0.330On

Each source also sets an origin for its signals. The default, from_segment, marks a signal customer when the account is a customer or partner and external otherwise; a source can instead pin external or internal. Contact email addresses go to a contacts table only after a signal exists and are never copied into signal content, metadata or the knowledge graph.

Why a HubSpot record does not become a signal

A HubSpot record becomes a signal only if it passes a fixed funnel, and nima counts each drop by source and reason over the last 7 days in the connection status (GET /v1/hubspot/app/status). Counts are never stored beyond that window. The reasons, in funnel order:

ReasonMeaning
filtered_scopeThe record is not tied to a tracked account, or to a contact that resolves to one
too_shortFewer customer characters than the source minimum after cleaning
automatedOut-of-office, bounce or no-reply text
calendar_boilerplateCalendar invite text
score_onlyA survey score with no comment; nima stores it as an account NPS fact instead
picklist_reasonA deal reason that is only a picklist value
duplicateIdentical normalized text within 30 days; attached as evidence to the existing signal
near_duplicateNear-identical text within 30 days; attached as evidence to the existing signal
no_product_contentThe source has the product-content gate on and the text has none
budget_heldThe daily cap is reached; the cursor holds until capacity returns
budget_expiredHeld for more than 7 days, then dropped
errorThe record failed to process

Cleaning strips HTML, quoted replies, signatures, footers, calendar text and AI-notetaker boilerplate before these checks run. Contacts and deletions are never signals.

HubSpot import, backfill and daily caps

Import starts the backfill for a confirmed recipe, and after that a sweep runs every 15 minutes. POST /v1/hubspot/import returns { queued, backfillFrom } and answers 409 until the recipe is confirmed. POST /v1/hubspot/sync-now returns { queued }, which is false when a run is already queued or running, or while ingestion is not switched on. After Import the card shows Edit mapping and Sync now.

Settings are saved with PUT /v1/hubspot/settings, which takes all three fields every time (dailySignalCap is a whole number):

SettingValuesDefaultEffect
backfillDays30, 90, 180 or 36590How far back Import reads voice
dailySignalCap0 to 5000300Most signals created per UTC day
dailyUsdCap0 to 1003Estimated extraction spend per UTC day, in USD

nima estimates each voice signal at $0.008 and stops at whichever cap is reached first. Each enabled source gets a share of the day's capacity by weight, so one busy source cannot starve the others.

HubSpot webhooks are only a doorbell: a company, deal or ticket creation pulls the next run forward, debounced by 60 seconds, but nima never uses the webhook payload. Records are always re-read through the API.

HubSpot accounts and ARR at stake

Signals from HubSpot are attributed to accounts in the index, up to 10 accounts per signal, and beacons roll up the ARR at stake across their evidence. GET /v1/accounts lists accounts with filters search, segmentKind, minArrUsd and ownerName. GET /v1/accounts/:id returns one account with its facts, latest signals, beacons and shipped specs. PUT /v1/signals/:signalId/accounts with { "accountIds": [...] } (up to 10 account ids) sets a signal's accounts by hand, and an empty list clears them. These routes need a signed-in session of any workspace member (owner, admin or member), and the account index is empty until a sync has run.

Delete HubSpot data and disconnect

DELETE /v1/hubspot/data removes the account index, contacts and signal-to-account links, and resets cursors and the Import state. It returns the counts removed. Signals already created are kept. The card's Delete account data button calls this route.

Disconnect with the Disconnect button on the HubSpot card in Integrations, which calls DELETE /v1/integrations/hubspot. nima revokes its HubSpot token, deletes the connection, and purges the account index, contacts and signal-to-account links. The signals themselves stay, with their source links to the HubSpot records, but nima can no longer re-read those originals. The On or Paused switch on the card is a label only and does not stop a sync.

On this page