Connectors
/
HubSpot
Live · 11 tools

HubSpot Integration for AI Agents

The HubSpot API is well-documented. Getting your agent to call it correctly — for real users, with tokens that never expire at the wrong moment and scopes that never mismatch — is the part that takes longer than it should.
HubSpot
Live

CRM

Marketing Automation

Status
Live
Tools
11 pre-built
Auth
OAuth 2.0
Credential storage
Zero
Sandbox support
No

OAuth 2.0

Auto token refresh

Zero credential storage

Revocation detection

BYOC required

The real problem

Why this is harder than it looks

HubSpot's API documentation is genuinely good. The authorization flow is standard OAuth 2.0. Most developers expect to spend an afternoon on it. The problems start when you go beyond a single-user prototype and try to run this for actual customers.

HubSpot access tokens expire after 30 minutes. That's not a typo — thirty minutes. In production, where an agent might be processing a background workflow or acting on a trigger that fires at midnight, a stale token means a silent failure mid-operation unless you've built proactive refresh logic that runs ahead of expiry. Most teams build the refresh only after they've been burned by the 401 in production.

Then there's HubSpot's scope model. Every CRM object — contacts, companies, deals — has separate read and write scopes. Schema access is another scope entirely. HubSpot enforces an exact match: the scopes your agent requests at authorization time must match exactly what you declared in your developer app settings. A single mismatch blocks the entire install with a cryptic error that users can't resolve themselves. As your agent's capabilities grow and you add new tools, you'll need users to re-authorize — and managing that re-authorization gracefully across a multi-tenant user base is a non-trivial problem.

Finally, HubSpot requires you to register your own Public App to get a Client ID and Secret. Each of your customers authorizes through your app, and you're responsible for keeping those credentials secure, rotating them when needed, and wiring up the redirect URI exactly as registered.

Scalekit handles the token lifecycle, scope configuration, credential storage, and revocation detection. Your agent code calls a tool by name. The plumbing is invisible.

Capabilities

What your agent can do with HubSpot

Once connected, your agent has 11 pre-built tools covering the core HubSpot CRM object model:

  • Search contacts, companies, and deals: full-text search with filter groups and pagination across all major CRM objects
  • Create and update contacts: with email, name, job title, lifecycle stage, and lead status
  • Create and update deals: with pipeline, deal stage, amount, close date, and priority
  • Create and retrieve companies: with industry, revenue, headcount, domain, and location metadata
  • List contacts with cursor pagination: including archived records, with field selection
Setup context

What we're building

This guide connects a sales assistant agent to HubSpot — helping reps search contacts, manage deals, and update CRM records without leaving your product.

🤖
Example agent
Sales assistant managing HubSpot pipeline on behalf of each rep
🔐
Auth model
B2B SaaS — each rep connects their own HubSpot portal. identifier = your user ID
⚙️
Scalekit account
app.scalekit.com — Client ID, Secret, Env URL
🔑
HubSpot Public App
Register at developers.hubspot.com — required for BYOC setup
Setup

1 Setup: One SDK, One credential

Install the Scalekit SDK. The only credential your application manages is the Scalekit API key — no HubSpot secrets, no user tokens, nothing belonging to your customers.

pip install scalekit-sdk-python
import scalekit.client import os from dotenv import load_dotenv load_dotenv() scalekit = scalekit.client.ScalekitClient( client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), env_url=os.getenv("SCALEKIT_ENV_URL"), ) actions = scalekit.actions
Connected Accounts

2 Per-User Auth: Creating connected accounts

Each rep gets their own Connected Account, giving them a dedicated auth context. The identifier is any unique string from your system — a UUID, email, whatever you use internally.

response = actions.get_or_create_connected_account( connection_name="hubspot", identifier="user_hs_456" # your internal user ID ) connected_account = response.connected_account print(f"Status: {connected_account.status}") # Status: PENDING — user hasn't authorized yet

This call is idempotent — safe to call on every session start. Returns the existing account if one already exists.

Authorization Flow

3 The authorization flow

The rep authorizes your agent once. Scalekit generates the OAuth URL with correct scopes, redirect handling, and state pre-configured. After approval, you never see the token.

if connected_account.status != "ACTIVE": link = actions.get_authorization_link( connection_name="hubspot", identifier="user_hs_456" ) # Redirect user → HubSpot consent screen # Scalekit captures the token on callback return redirect(link.link)
Token management is automatic
After the user approves, Scalekit stores encrypted tokens and the connected account moves to ACTIVE. HubSpot access tokens expire after 30 minutes — Scalekit refreshes them before expiry. If a rep uninstalls your app from their HubSpot portal, the account moves to REVOKED — no silent failures. Check account.status before critical operations.
BYOC is required for HubSpot
Unlike some connectors, HubSpot requires you to register your own Public App and supply your own Client ID and Client Secret. Create your app at developers.hubspot.com, add the Scalekit redirect URI under Auth settings, configure your scopes, then paste the credentials into the Scalekit dashboard. Token management stays fully handled.
Already have credentials?
Calling HubSpot

4 Calling HubSpot: What your agent writes

With the connected account active, your agent calls Salesforce actions using execute_tool. Name the tool, pass parameters. Scalekit handles token retrieval, request construction, and response parsing.

Search contacts

Full-text search across all contacts. Use filterGroups for advanced property-based filtering.

result = actions.execute_tool( identifier="user_hs_456", tool_name="hubspot_contacts_search", tool_input={ "query": "acme corp", "properties": "firstname,lastname,email,jobtitle,lifecyclestage", "limit": 10 } ) # { "results": [ { "id": "...", "properties": { "firstname": "Jane", ... } }, ... ] }

Create a contact

Email is the unique identifier and the only required field. All other properties are optional.

result = actions.execute_tool( identifier="user_hs_456", tool_name="hubspot_contact_create", tool_input={ "email": "jane@acmecorp.com", "firstname": "Jane", "lastname": "Smith", "jobtitle": "VP of Engineering", "company": "Acme Corp", "lifecyclestage": "lead" } )

Create a deal

dealname, amount, and dealstage are required. Pipeline defaults to the account's primary pipeline if not specified.

result = actions.execute_tool( identifier="user_hs_456", tool_name="hubspot_deal_create", tool_input={ "dealname": "Acme Corp — Enterprise 2026", "amount": 75000, "dealstage": "presentationscheduled", "pipeline": "default", "closedate": "2026-06-30", "hs_priority": "HIGH" } )

Search deals with filter groups

For precise queries — deals above a certain amount in a specific stage — pass filterGroups as a JSON string.

import json result = actions.execute_tool( identifier="user_hs_456", tool_name="hubspot_deals_search", tool_input={ "filterGroups": json.dumps([{ "filters": [ {"propertyName": "dealstage", "operator": "EQ", "value": "presentationscheduled"}, {"propertyName": "amount", "operator": "GT", "value": "50000"} ] }]), "properties": "dealname,amount,dealstage,closedate,hs_priority", "limit": 20 } )
Framework wiring

5 Wiring into your agent framework

Scalekit's tools load directly into LangChain. The agent decides what to call; Scalekit handles auth on every invocation. No token plumbing in your agent logic.

from langchain_anthropic import ChatAnthropic from langchain.agents import AgentExecutor, create_tool_calling_agent from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from scalekit.langchain import get_tools hs_tools = get_tools( connection_name="hubspot", identifier="user_hs_456" ) prompt = ChatPromptTemplate.from_messages([ ("system", "You are a CRM assistant. Use the available tools to help manage HubSpot contacts, companies, and deals."), MessagesPlaceholder("chat_history", optional=True), ("human", "{input}"), MessagesPlaceholder("agent_scratchpad"), ]) agent = create_tool_calling_agent(ChatAnthropic(model="claude-sonnet-4-6"), hs_tools, prompt) result = AgentExecutor(agent=agent, tools=hs_tools).invoke({ "input": "Find all high-priority deals over $50k in presentation stage and summarize the pipeline" })
Other frameworks supported
Tool reference

All 11 HubSpot tools

Grouped by object and capability. Your agent calls tools by name — no API wrappers to write.

Contacts
hubspot_contact_create
Create a contact with email (required), name, phone, job title, company, and lifecycle stage
hubspot_contact_get
Retrieve a specific contact by ID with field selection
hubspot_contact_update
Update any contact property by contact ID — name, email, lifecycle stage, lead status, and more
hubspot_contacts_list
List contacts with cursor-based pagination, field selection, and optional archived record inclusion
hubspot_contacts_search
Full-text search across contacts with optional filter groups for property-based queries
Companies
hubspot_company_create
Create a company with name (required), domain, industry, revenue, headcount, and location
hubspot_company_get
Retrieve a specific company by ID with field selection
hubspot_companies_search
Full-text search across companies with optional filter groups and pagination
Deals
hubspot_deal_create
Create a deal with name, amount, and stage (all required). Supports pipeline, close date, type, and priority
hubspot_deal_update
Update any deal property by deal ID — stage, amount, close date, pipeline, and priority
hubspot_deals_search
Full-text search across deals with filter groups for stage, amount, priority, and custom properties
Connector notes

HubSpot-specific behavior

BYOC is required — no managed app available
Unlike some Scalekit connectors, HubSpot does not provide a managed app for getting started. You must register a Public App at developers.hubspot.com, copy the Scalekit redirect URI into your app's Auth settings, and paste your Client ID and Client Secret into the Scalekit dashboard before the authorization flow will work.
Scope mismatches block installation silently
HubSpot enforces an exact match between the scopes declared in your Public App settings and the scopes requested at authorization time. A single mismatch blocks the install with an error your users cannot resolve themselves. Ensure the scope set in the Scalekit dashboard matches your declared app scopes exactly — and plan for re-authorization when you add new tool capabilities that require new scopes.
Access tokens expire every 30 minutes
HubSpot's access tokens have a 30-minute lifetime — shorter than most OAuth providers. Scalekit refreshes them proactively before expiry, so your agent never hits a stale token mid-operation. This is handled automatically; no code changes required on your end.
Infrastructure decision

Why not build this yourself

The HubSpot OAuth flow is documented. Token storage isn't technically hard. But here's what you're actually signing up for:

PROBLEM 01
30-minute access token expiry means refresh logic must be proactive, not reactive — a failed call mid-workflow is not a graceful failure
PROBLEM 02
Scope mismatch enforcement that blocks installs silently — and forces re-authorization across all users whenever you add new agent capabilities
PROBLEM 03
Per-user token isolation across a multi-tenant system — one rep's HubSpot portal credentials must never be accessible to another
PROBLEM 04
Revocation detection when a rep uninstalls your app from their HubSpot portal — and graceful handling so the agent stops making calls immediately

That's one connector. Your agent product will eventually need Salesforce, Gmail, Slack, Notion, and whatever else your customers ask for. Each has its own OAuth quirks and failure modes.

Scalekit maintains every connector. You maintain none of them.

Ready to ship

Connect your agent to Salesforce in minutes

Free to start. No Salesforce Connected App required. Token management fully handled.