HubSpot Access and API Setup
Version: 1.6
Date: April 21, 2026
Owner: AI Team
1. Purpose
This guide explains how Brainforge team members and Cursor agents should access HubSpot.
Agents in Cursor (default): use HubSpot MCP first for anything the MCP tools can do (search, reads, property discovery, and other supported CRM operations). Use the REST API / tools/hubspot-api-service only when MCP does not support the operation, when MCP is impractically slow for the volume (e.g. scripted rollups, WBR dry-run markdown), or when the user explicitly wants a CLI/script path.
Humans: the HubSpot web app remains the right place for extended review, settings, and manual work that is easier in the UI.
2. Access Policy
Agents: HubSpot MCP first
In Cursor (and similar clients wired to this repo’s MCP launcher), treat HubSpot MCP as the standard for CRM context: resolve record IDs, search companies/contacts/deals, inspect properties, and answer questions without leaving chat.
When to use the REST API or service CLI instead
Use tools/hubspot-api-service, direct curl, or other automation when:
- Capability gap — MCP does not expose the write or association pattern you need (e.g. scripted
POST /crm/v3/objects/noteswith association payloads,log-new-opportunity, partner CLI batch patterns). - Performance / volume — many sequential calls or large extracts are faster or clearer as a script than through MCP in a single thread.
- Explicit automation — scheduled jobs, CI, or
npm run hubspot:*workflows (WBR dry-run, property audits with--apply, etc.).
Humans: HubSpot web app
Use the HubSpot app for:
- Long-form pipeline review, settings, and imports
- Manual edits when the UI is faster than describing the change in chat
- Confirming CRM state before staffing or delivery decisions when you are already in HubSpot
Repo wiring (Cursor / OpenCode): mcp.json starts node on scripts/hubspot-mcp-stdio.mjs, which:
- Loads
HUBSPOT_ACCESS_TOKEN(orPRIVATE_APP_ACCESS_TOKEN) from the process environment and, if missing, from optional gitignored files in order:apps/platform/.env.local, repo-root.env.local, repo-root.env.hubspot.mcp(via dotenv). - Sets
PRIVATE_APP_ACCESS_TOKENfor HubSpot’s official @hubspot/mcp-server and dynamic-imports its ESM entry (avoids brokenrequire()on"type": "module").
One-time install: From repo root run npm run hubspot:install so @hubspot/mcp-server exists under tools/hubspot-api-service/node_modules/ (declared as a devDependency there). Commit the updated tools/hubspot-api-service/package-lock.json after install. Restart Cursor after installing.
Why not raw npx in mcp.json? On Windows, Cursor often spawns MCP without cmd.exe; npx/npx.cmd batch scripts then fail or never start. node + a repo script is reliable.
Why not only ${env:HUBSPOT_ACCESS_TOKEN} in mcp.json? Cursor’s MCP subprocess can have a minimal environment; reading the same token from apps/platform/.env.local matches how developers already configure the platform.
Why not the hosted URL https://mcp.hubspot.com in Cursor? That OAuth path conflicts with Cursor’s dynamic client registration expectations; HubSpot does not support DCR → Incompatible auth server: does not support dynamic client registration. The stdio + private app token path avoids that.
Remote MCP (advanced): HubSpot remote MCP + MCP Auth App + static OAuth in clients that support it; not what committed .cursor/mcp.json uses.
OpenCode / OpenWork: opencode.jsonc uses the same node … scripts/hubspot-mcp-stdio.mjs command (with ${workspaceFolder} where supported).
3. When to Use the API (after MCP)
Typical triggers:
- User says: “log this in HubSpot”, “add to HubSpot”, “log in HS”, “make sure it’s in HubSpot as an activity” — resolve company/contact/deal IDs with MCP when possible; create the note or other write via API when MCP cannot perform the write.
- After Slack/email/call touchpoints that should count in GTM metrics
- Any outreach or engagement that should be visible on the company/contact/deal record
Agent behavior: Prefer MCP for lookup and confirmation; use the HubSpot API (this playbook + tools/hubspot-api-service where applicable) for writes and for operations MCP does not support. Do not only document a checklist in the vault; perform the CRM write when the user asked for HubSpot logging.
4. Credentials
1Password
- Vault:
Brainforge AI Team(orEmployeefor personal) - Item: Store an item (for example
HubSpot API) with a token that supports the required write scopes. - Field: Store the token as
credentialorpassword.
op item list --vault "Brainforge AI Team" | grep -i hubspot
op read "op://Brainforge AI Team/HubSpot API/credential"If no HubSpot write token exists yet, add one to 1Password before attempting agent-driven writes.
Environment variable (optional)
HUBSPOT_ACCESS_TOKEN=pat-na1-xxxxx5. Create a Note (Activity) via API
Base URL
https://api.hubapi.com
Find company or contact ID
Agents: use HubSpot MCP search first (search_crm_objects / equivalent) with objectType companies or contacts and the known name, domain, or email.
Fallback: Search API POST /crm/v3/objects/companies/search (or /contacts/search) when MCP is unavailable, returns errors, or you need a filter MCP does not expose.
Humans: use the HubSpot app when already working there.
Create note and associate to company
Endpoint: POST /crm/v3/objects/notes
Headers:
Authorization: Bearer {access_token}Content-Type: application/json
Body (note → company, associationTypeId 190):
{
"properties": {
"hs_timestamp": "2026-02-09T15:07:00.000Z",
"hs_note_body": "Slack touch-base with Sigal: congrats on Breezy $10M pre-seed (Axios 2/2); asked how analytics is going; offered Brainforge help."
},
"associations": [
{
"to": { "id": "COMPANY_ID_STRING" },
"types": [
{
"associationCategory": "HUBSPOT_DEFINED",
"associationTypeId": 190
}
]
}
]
}Note → contact (associationTypeId 202):
"associations": [
{
"to": { "id": "CONTACT_ID_STRING" },
"types": [{ "associationCategory": "HUBSPOT_DEFINED", "associationTypeId": 202 }]
}
]cURL example
curl -X POST "https://api.hubapi.com/crm/v3/objects/notes" \
-H "Authorization: Bearer $HUBSPOT_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"properties": {
"hs_timestamp": "2026-02-09T15:07:00.000Z",
"hs_note_body": "Slack touch-base: [summary of outreach]"
},
"associations": [{
"to": { "id": "223907255032" },
"types": [{ "associationCategory": "HUBSPOT_DEFINED", "associationTypeId": 190 }]
}]
}'6. Association type IDs (reference)
| From → To | associationTypeId |
|---|---|
| Note → Company | 190 |
| Note → Contact | 202 |
| Company → Note | 189 |
| Contact → Note | 201 |
7. Common agent workflow
- User asks to log something in HubSpot (for example, “log this touchpoint in HS”).
- Resolve company/contact/deal with HubSpot MCP when possible; use the app if the human is already there and prefers manual entry.
- If a write is required and MCP cannot do it, get token:
op read "op://Brainforge AI Team/<HubSpot item>/credential"(or Brainforge Sales vault item such as Cursor HubSpot app — see team runbook) and use the API ortools/hubspot-api-serviceCLI. - Build body:
hs_timestamp(ISO 8601),hs_note_body(summary of the touchpoint). - POST to
https://api.hubapi.com/crm/v3/objects/noteswith associations to company (190) and/or contact (202) when using the note API path. - Confirm to the user that the activity was created and will appear in HubSpot metrics.
8. HubSpot CLI (developer platform)
For CLI-driven HubSpot work (projects, CMS, app deploy, hs open), use the pinned CLI under tools/hubspot-cli/ and a Personal Access Key. That flow is separate from the Private App token used for CRM REST calls in this guide. See hubspot-cli-setup.md.
9. API reference
10. Version history
- v1.6 (April 21, 2026) — MCP-first for agents; API/CLI when MCP lacks capability or is too slow for volume; humans still use the app for deep UI work; workflow §7 updated
- v1.5 (April 13, 2026) — Launcher script
scripts/hubspot-mcp-stdio.mjs(node, not npx; ESM import; dotenv paths);@hubspot/mcp-serverundertools/hubspot-api-service - v1.4 (April 13, 2026) — HubSpot MCP in repo uses stdio
@hubspot/mcp-server+HUBSPOT_ACCESS_TOKEN(avoid Cursor DCR error with hosted MCP) - v1.3 (April 13, 2026) — Document repo
.cursor/mcp.json/ OpenCode HubSpot MCP env vars and MCP Auth App redirect - v1.2 (April 1, 2026) — Cross-link HubSpot CLI setup for developer-platform workflows
- v1.1 (April 1, 2026) — Reframed access guidance: HubSpot app first, MCP fallback, API for writes/automation
- v1.0 (February 9, 2026) — Initial guide for logging activities via HubSpot API