HubSpot connector: CRM answers for the whole team, writes with a second pair of eyes
This page is for the HubSpot super admin who will connect a portal to OrgRelay. It explains which CRM objects the six tools touch, how to get an access token now that legacy private apps can no longer be created, and what approvers see before a note or ticket appears in HubSpot.
What staff can ask
Sales and support staff who don't live in HubSpot ask things like these. Each maps to one of the standard tools, and sometimes to two in sequence:
- "When did we last talk to anyone at Brightline, and who owns the account?" calls
customers.searchwithkeyword: Brightline. Each contact comes back with its owner ID and last activity time. - "Show me Dana Wu's open deals." calls
customers.searchto find the contact, thencustomers.get, which returns the contact's lifecycle stage, phone, title and associated deal IDs. - "Which deals are in closed won this month?" calls
customers.dealswithstage: closedwon. Stage values are internal IDs, so custom pipelines use their own stage IDs. - "Any tickets mentioning 'refund' still open?" calls
tickets.searchwithkeyword: refund. - "Log that Dana asked for the revised quote by Friday." calls
customers.add_noteand waits for approval.
Tools
| Tool | Access | What it does | Key parameters |
|---|---|---|---|
customers.search |
read | CRM search on contacts: name, email, company, owner, last activity | keyword, limit, cursor |
customers.get |
read | One contact with phone, job title, lifecycle stage and associated deal IDs | customer_id (contact ID), required |
customers.deals |
read | CRM search on deals: name, stage, amount, close date | keyword, stage (stage ID) |
tickets.search |
read | CRM search on tickets: subject, pipeline stage, priority, created date | keyword |
customers.add_note |
write · approval | Creates a note and associates it with the contact (association type 202) | customer_id, note |
tickets.create |
write · approval | Creates a ticket in the default support pipeline, optionally linked to a contact (association type 16) | subject (required), description, priority (LOW, MEDIUM, HIGH), customer_id |
All read tools call POST /crm/v3/objects/{object}/search. limit defaults to 20 and stops at 100, although HubSpot itself allows 200. The cursor is HubSpot's paging.next.after token. Results follow the shared connector spec, so a contact from HubSpot and an account from Salesforce look alike to the AI. Deal amounts come back without a currency, because the deal search does not request the currency property.
Credentials and scopes
The connection form has one required field: App access token, from either a static auth app or a legacy private app. It is stored encrypted and shown afterwards only by its last four characters (details in security). An advanced field lets you change the API base URL, which normally stays https://api.hubapi.com. During Connect, OrgRelay calls GET /account-info/v3/details and shows the portal ID and company currency.
Where the token comes from changed in 2026. HubSpot's legacy private apps overview states that legacy private apps can no longer be created as of 26 October 2026. Existing ones are still supported, and their tokens (they begin with pat-) work with this connector unchanged. For a new connection, HubSpot's create an app guide describes a project-based app. You choose a static token during hs project create, pick distribution restricted to specific accounts, and declare scopes in app-hsmeta.json. A static token app installs into one standard HubSpot account, and the token appears on the app's Distribution tab after install.
Scopes for this connector:
| Scope | Needed for |
|---|---|
crm.objects.contacts.read |
customers.search, customers.get |
crm.objects.companies.read |
Company data on contacts |
crm.objects.deals.read |
customers.deals, deal associations in customers.get |
tickets |
tickets.search, tickets.create |
crm.objects.contacts.write |
customers.add_note (optional) |
Static tokens do not expire on a timer. Rotate one from the Distribution tab, or from the legacy app's settings, then paste the new value into OrgRelay. Rotating expires the old token, so do both steps together. Changing scopes on a static token app requires reinstalling it through the Reinstall URL. The auth guide explains how OrgRelay stores single-token credentials like this.
Which actions need approval and what the approver sees
Both writes go through OrgRelay approvals:
customers.add_note. The approver sees the contact ID and the exact note body. Once approved, HubSpot gets a note withhs_timestampset to the approval time, attached to that contact's timeline. Notes are visible to everyone in the portal who can see the contact, so approvers should read them as if the customer's account manager will.tickets.create. The approver sees subject, description, priority (MEDIUM when none is given) and the contact ID, if any. The ticket goes into pipeline0, stage1, which is the first stage of HubSpot's default support pipeline. Portals that renamed or replaced the default pipeline should check where stage1lands before approving the first ticket. Ticket-based automation in HubSpot, such as assignment rules, runs as usual after creation.
The human-in-the-loop page covers how approver routing works. A good default is to let the support lead approve tickets and the account owner approve notes. The sales agent set-up shows that split. Every approved call carries the key orgrelay-approval-<approval id> and is recorded in the audit log with the approver's name.
Set it up
- If a legacy private app already exists with the scopes above, open it in HubSpot under Development → Legacy apps, copy the access token and go to step 5.
- Otherwise install the HubSpot CLI (
npm i -g @hubspot/cli), runhs initas a super admin to link your portal, then runhs project create. Choose an app, static auth and private distribution when prompted, and name it OrgRelay. - In
app-hsmeta.json, list the scopes from the table underrequiredScopes(putcrm.objects.contacts.writeunderoptionalScopesif you're unsure). RemoveredirectUrls, then runhs project upload. - In HubSpot, go to Development → Projects, open the app, choose Distribution → Install now, and approve. Copy the access token shown on the Distribution tab. You need super admin or a developer seat to view it.
- In OrgRelay, open Admin → Business systems → App directory, choose HubSpot, paste the token and click Connect.
- Grant the connection to sales and support roles. Pages for other CRM and helpdesk systems are in the connector list. Switch off
tickets.createfor teams that should not open tickets.
Limits and things it deliberately does not do
- HubSpot API limits per app (from the legacy private apps documentation): Free and Starter accounts get 100 requests per 10 seconds and 250,000 per day. Professional gets 190 per 10 seconds and 625,000 per day, and Enterprise gets 190 per 10 seconds and 1,000,000 per day.
- Search limits. HubSpot's search endpoints allow five requests per second per account and return at most 10,000 results per query. Because every read tool here is a search call, the five-per-second limit is the one you're likely to meet first.
- OrgRelay's guardrails: 120 calls per minute per connection, a 60-second pause after three straight failures, and about 12,000 characters of any result shown to the AI.
- Not exposed: editing or deleting records, deal stage changes, emails and sequences, marketing lists, forms, quotes, custom objects and owners' names (owner IDs only). Marketing data belongs to a separate HubSpot Marketing connection. For an object this connector leaves out, you can describe the endpoint yourself through an OpenAPI import.
- Test portals. HubSpot offers free developer test accounts, and a static token app can be installed in up to 10 of them, which is a safe place to try approvals.
Official MCP server and OrgRelay
HubSpot publishes its own MCP server (see official MCP servers for how OrgRelay treats vendor servers). It runs at https://mcp.hubspot.com, now generally available to all HubSpot accounts. Setup creates an MCP auth app in HubSpot, and the client then authenticates with OAuth and PKCE. HubSpot documents it in integrate with the remote HubSpot MCP server. There is also a separate local Developer MCP server for building HubSpot apps, which is not meant for CRM data.
For OrgRelay, the authentication model is what decides the fit. A third-party MCP connection authenticates with a bearer token or OAuth client credentials, while HubSpot's remote server expects each user to sign in through OAuth with PKCE. So the connector on this page, with its static token, is the direct way to bring HubSpot into OrgRelay. The remote server suits individual users in their own MCP clients. Through this connector, OrgRelay adds the layer a single-user MCP client does not have. The owner grants HubSpot tools per role or department, writes wait for an approver, HubSpot calls sit in one audit log with Zendesk and finance systems, and the whole thing runs on the company's own Mac mini. The MCP overview and enterprise patterns explain the trade-offs, and the Claude Code guide covers the single-developer alternative.
Common questions
Can I still create a HubSpot private app for this connector? Not a new legacy one. HubSpot stopped the creation of legacy private apps on 26 October 2026. Existing private app tokens keep working. For a new connection, create an app on the current developer platform with static auth and private distribution, then paste its access token.
Which HubSpot scopes are needed if staff should only read?
crm.objects.contacts.read, crm.objects.companies.read, crm.objects.deals.read and tickets. Leave out crm.objects.contacts.write and switch off customers.add_note in OrgRelay. The tickets scope covers both reading and creating tickets, so turn off tickets.create in OrgRelay if tickets must stay read-only.
Does the connector work on a free HubSpot account? Yes. The connector only touches contacts, companies, deals, tickets and notes, which are core CRM objects rather than paid add-ons. HubSpot's API limits on Free and Starter are 100 requests per 10 seconds per app and 250,000 per day per account.